Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cluster setting and Distributed Table tests #186

Merged
merged 14 commits into from
Oct 26, 2023
Merged

Conversation

gfunc
Copy link
Contributor

@gfunc gfunc commented Aug 23, 2023

Summary

  • added attribute should_on_cluster for ClickHouseRelation class to indicate whether theon_cluster_clause macro should return content.
  • added cluster setting for tests.
  • debug marcos.
  • added tests for distributed_table materialization and replicated table engines.
  • changed github workflow test to use docker-compose which starts a 3 nodes ClickHouse cluster

Checklist

Delete items not relevant to your PR:

  • Unit and integration tests covering the common scenarios were added

Caveats

  • tests for distributed_incremental is not added yet.

@CLAassistant
Copy link

CLAassistant commented Aug 23, 2023

CLA assistant check
All committers have signed the CLA.

Copy link
Contributor

@zli06160 zli06160 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 The modifications in dbt/include/clickhouse/macros/materializations/distributed_table.sql do make sense.
We should indeed

  • define the default sharding_key, cluster, etc;
  • or show the error messages(instructions) if they are not defined in template.sql and/or dbt_project.yml.

@gfunc
Copy link
Contributor Author

gfunc commented Sep 6, 2023

Hi @genzgd any update on the review of this MR, or any thoughts/suggestions?

@gfunc gfunc requested a review from zli06160 September 14, 2023 03:43
group by name, schema, type, db_engine
{%- else -%}
0 as is_on_cluster
from system.tables as t JOIN system.databases as db on t.database = db.name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe join in lower case. Same comments for other sql keywords in several files.

from dbt.tests.util import run_dbt

from tests.integration.adapter.incremental.test_incremental import uniq_schema

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add more comments to describe the tests more clearly 1) at the beginning of the .py file, or 2) at the beginning of each test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, will do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid most tests are self explainatory by names, and mostly base off dbt's sample tests. I will try to add more comments for distributed materialization tests.

engine: ReplicatedMergeTree('/clickhouse/tables/{uuid}/one_shard', '{server_index}' )
- name: added
config:
engine: ReplicatedMergeTree('/clickhouse/tables/{uuid}/one_shard', '{server_index}' )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it will be better if test at least once with multiple shards x multiple replicas?
e.g. ReplicatedMergeTree('/clickhouse/tables/{shard}/{database}/table_name', '{replica}') (example from https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/replication)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for integration tests, if we managed to set a multiple shards * multple replicas matrix, data will always exist in one shard (same zk path), maybe it is not worth adding another test?

Copy link
Contributor

@zli06160 zli06160 Oct 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me it is an usual usage.
But it is more managed by dbt-core & the clickhouse cluster, so any integration test(in the current project) on the cluster mode is enough.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I did not get the reason why the data persist in one shard.
Do you use drop table distributed_table_name on cluster cluster_name or create or replace table, or something similar?

Copy link
Contributor Author

@gfunc gfunc Oct 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant for the Replicated Engine tables with non-distributed materializations, like this seed. If I understand it correctly, during our tests, insert into query will be performed by one node and data will be replicated among nodes with the same shard (same zk path).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, if create (non-distributed)table xxx on cluster xxx then insert into the non-distributed table, the data will on only one shard(and its replicated shards); and the next insert into can target to another shard😿.

For the seeding step, I see 3 possible ways:

  • insert into a distributed table, which is based on a table with any replicated engine;
  • or use a view as interface;
  • or use File Table Engine <= the best in my opinion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My approach is to make sure seed are using the same shard and different replica, i.e. to broadcast the whole dataset.
I have never used File Table Engine before, could you explain a bit more? How it would help in this situation?

Copy link
Contributor

@zli06160 zli06160 Oct 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File Table Engine(or just file function) reads the csv files directly, not sure if it will help.
https://clickhouse.com/docs/en/engines/table-engines/special/file
https://clickhouse.com/docs/en/sql-reference/table-functions/file

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think now I understand how you test the distributed_table. I still recommend a separate .py for each main materialization, or, if not applicable, document more.

@zli06160
Copy link
Contributor

zli06160 commented Sep 19, 2023

  • The distributed_table works well on the cluster with my test case (several dbt run, no error, correct count(*) );
  • The distributed_incremental works well on the cluster with my test case (several dbt run, no error, correct count(*) ).

@gfunc
Copy link
Contributor Author

gfunc commented Sep 20, 2023

Hi @zli06160 any thoughts on the logic for should_on_cluster attribute in relation.py?

    @property
    def should_on_cluster(self) -> bool:
        if self.include_policy.identifier:
            return self.can_on_cluster
        else:
            # create database/schema on cluster by default
            return True
    @classmethod
    def get_on_cluster(
        cls: Type[Self], cluster: str = '', materialized: str = '', engine: str = ''
    ) -> bool:
        if cluster:
            return 'view' == materialized or 'distributed' in materialized or 'Replicated' in engine
        else:
            return False

I think we should start the discussion early since this is changing the behavior of this adapter once a cluster is set. Also, I tried to make logic compatible with the previous version by adding the attribute can_on_cluster for existing models.

Maybe it is worth mentioning in README?

@zli06160
Copy link
Contributor

zli06160 commented Sep 20, 2023

For me, the query must contain the on cluster clause: 1) if the connection is to a cluster; 2)or if any keyword like distributed/Replicated/etc detected in the .sql file.

The logic of get_on_cluster seems correct, just need to include MATERIALIZED VIEW (of course this materialization is not implemented yet), and prevent the case cluster = ' '.

Other contributors do need more detailed comments and README to understand the project-specific notions.

@gfunc
Copy link
Contributor Author

gfunc commented Oct 8, 2023

I will be available starting tomorrow (Oct 09) for further modifications.

@gfunc gfunc requested a review from zli06160 October 13, 2023 04:56
@@ -9,7 +11,13 @@
from dbt.tests.adapter.basic.test_singular_tests import BaseSingularTests
from dbt.tests.adapter.basic.test_snapshot_check_cols import BaseSnapshotCheckCols
Copy link
Contributor

@zli06160 zli06160 Oct 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to set "DBT_CH_TEST_CLUSTER"(I guess the value should be 'test_shard'?) somewhere for integration testing.

After I cloned the project, checkout to the branch, build + up the docker containers, there is no such variable, so many tests are ignored.

Then, in this file, in order to fully run the tests, with os.environ["DBT_CH_TEST_CLUSTER"] = 'test_shard' added, there is an error related to BaseSnapshotCheckCols:

09:11:29  Database Error in snapshot cc_all_snapshot (snapshots/cc_all_snapshot.sql)
09:11:29    :HTTPDriver for http://localhost:8123 returned response code 400)
09:11:29     Code: 15. DB::Exception: Column dbt_change_type specified more than once. (DUPLICATE_COLUMN) (version 23.9.1.1854 (official build))

Copy link
Contributor Author

@gfunc gfunc Oct 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am using test_shard for unit tests. And I added the env var in github workflow file.
And tests returned no error. I will take a look at this BaseSnapshotCheckCols.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not seeing any problem with this test.env file

DBT_CH_TEST_USE_DOCKER=true
DBT_MACRO_DEBUGGING=true
DBT_CH_TEST_INCLUDE_S3=false
DBT_CH_TEST_CLUSTER=test_shard

and command

pytest tests/integration/adapter/test_basic.py::TestSnapshotCheckCols

result attached:

============================= test session starts ==============================
platform linux -- Python 3.9.18, pytest-7.4.0, pluggy-1.2.0
rootdir: /home/xxx/projects/dbt-clickhouse
configfile: pytest.ini
plugins: dotenv-0.5.2
collected 1 item

tests/integration/adapter/test_basic.py .                                [100%]

============================== 1 passed in 19.58s ==============================

Please share your env file for me to reproduce

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is that I didn't have the test.env.

With the same env file as yours,

pytest tests/integration/adapter/test_basic.py -c pytest.ini -s

=> everything is ok after double check test by test.

pytest tests/integration/ -c pytest.ini

=> 107 passed, 2 skipped, 2 warnings .

Copy link
Contributor

@zli06160 zli06160 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK for me 👍

@genzgd
Copy link
Contributor

genzgd commented Oct 26, 2023

Thanks for all the work here, @gfunc and @zli06160. I'll do a 1.4.9 release shortly.

@genzgd genzgd merged commit 96474f1 into ClickHouse:main Oct 26, 2023
21 checks passed
Savid pushed a commit to Savid/dbt-clickhouse that referenced this pull request Jan 17, 2024
* added can_on_cluster var in ClickhouseRelation

* add tests for cluster

* fix lint issue

* debug set cluster env variable

* debug test

* debug and add tests

* skip distributed table grant test

* debug workflow

* debug workflow

* debug test

* add tests fro distributed_incremental

* fix zk path error

* fix wrong alias for distributed materializations

update aliase test

* update base on review
Solovechik added a commit to tekliner/dbt-clickhouse that referenced this pull request May 27, 2024
* fix: SYSTEM SYNC REPLICA for on_cluster_clause (ClickHouse#156)

* fix SYSTEM SYNC REPLICA

* add schema

* Update version and pypi job

* Fix incompatible return type (ClickHouse#162)

* Distributed table materialization (ClickHouse#163)

* distributed table materialization

* fix rebase

* PR fixes

* Bump version

* Tweak PyPI build Python release

* Add space to exchange_tables_atomic macro (ClickHouse#168)

* Add space to exchange_tables_atomic macro

This changes the SYSTEM SYNC REPLICA query to have a space between the
ON CLUSTER clause and the table name.

* Move whitespace to on_cluster_clause

* Fix bad logging/error handling (ClickHouse#170)

* Distributed incremental materialization (ClickHouse#172)

* distributed table materialization

* fix rebase

* PR fixes

* distributed incremental materialization

* fix

* fix

* add insert_distributed_sync to README.md

* add checks on  insert_distributed_sync

* add checks on  insert_distributed_sync

* review fixes

* Update version and tweak docs

* Lw delete set fix (ClickHouse#174)

* Move lightweight delete settings to per query for HTTP stickiness fix

* Minor cleanup and doc updates

* Fix legacy incremental materialization (ClickHouse#178)

* fix: distributed_table materialization issue (ClickHouse#184)

* Bump version and changelog (ClickHouse#185)

* cluster names containing dash characters (ClickHouse#198) (ClickHouse#200)

Co-authored-by: the4thamigo-uk <the4thamigo-uk>

* Add basic error test, fix minor merge conflict (ClickHouse#202)

* Cluster setting and Distributed Table tests (ClickHouse#186)

* added can_on_cluster var in ClickhouseRelation

* add tests for cluster

* fix lint issue

* debug set cluster env variable

* debug test

* debug and add tests

* skip distributed table grant test

* debug workflow

* debug workflow

* debug test

* add tests fro distributed_incremental

* fix zk path error

* fix wrong alias for distributed materializations

update aliase test

* update base on review

* Update version and CHANGELOG, incorporate cluster name fix (ClickHouse#203)

* Release 1 5 0 (ClickHouse#210)

* Initial 1.5.0 commit

* Reorganize basic tests

* Fix lint

* Add case sensitive cache

* Fix s3 bucket bug

* Checkpoint for constraints/contracts

* Fix native column query

* Loosen replication test

* Checkpoint for constraints tests

* Checkpoint for constraints tests

* Add rendering of model level CHECK constraints

* Fix lint

* Reorganize test files

* Add one hooks test

* Fix lint

* Update test and dependency versions. (ClickHouse#211)

* Adjust the wrapper parenthesis around the table materialization sql code (ClickHouse#212)

* Update for 1.5.1 bug fix

* Fix creation of replicated tables when using legacy materialization (ClickHouse#208)

* On cluster sync cleanup

* Bug fixes related to model settings. (ClickHouse#214)

* Add materialization macro for materialized view (ClickHouse#207)

* Add materialization macro for materialized view

* fix isort issues in materialized view test

* Release 1 6 0 (ClickHouse#215)

* Initial dbt 1.6 update

* Add skipped clone test

* Clean up MV PR

* Release 1 6 1 (ClickHouse#217)

* Identifier quoting checkpoint

* Identifier quoting checkpoint

* Fix distributed table local quoting

* Fix issues with deduplication settings

* Release 1 6 2 (ClickHouse#219)

* Limited fix to completely broken `on_schema_change`

* Tweak changelog

* Release 1 7 0 (ClickHouse#220)

* Initial dependency updates for 1.7.x

* Initial dependency updates for 1.7.x

* Correctly warn or error if light weight deletes not available

* Wrap columns_in_query query in select statement (ClickHouse#222)

* Wrap columns_in_query query in select statement

* formatting

* Update changelog

* allows to add a comment in table's or view's metadata

* add settings_section flag as comment for code using settings

* override test sql macro and add limit-placer macro

* update CHANGELOG.md

* fix: use correct schema for MV target tables (ClickHouse#244)

* fix: use correct schema when updating MVs

The existing implementation passes just the name for `target_table`,
which ultimately means that the target schema is not included when the
final SQL is generated. By passing the entire relation object, the
correct target schema will be present in the final SQL.

* update MV tests

Provide a custom schema to make sure that the full target table
name (schema + relation name) is included in the CREATE MATERIALIZED
VIEW statement

* Update changelog

* rename end of query flag

* Bug/223 relationship test with limit (ClickHouse#245)

* add settings_section flag as comment for code using settings

* override test sql macro and add limit-placer macro

* update CHANGELOG.md

* rename end of query flag

* Revert "Bug/223 relationship test with limit (ClickHouse#245)" (ClickHouse#247)

This reverts commit d8afb93.

* always return --end_of_sql when asking for settings

* Add model settings based on materialization type

* support setting clause on view creation

* edit CHANGELOG.md

* Bump version and tweak changelog

* change list syntax to satisfy lint test

* change list syntax to satisfy lint test

* change imports order to satisfy lint test

* Add typing to satisfy lint

* Add snapshot materialization to default settings

* Fix tests - add distributed_table and distributed_incremental materializations

* Fix tests - make sure to call the get_model_settings only when materialization is view

* clean up recent changelog

* Add materialization macro for dictionaries

* address lint issue in dictionary test

* address lint issue with enum

* Fix model settings with custom materialization

* Release 1.7.4 housekeeping (ClickHouse#261)

* Bump black from 23.11.0 to 24.3.0 (ClickHouse#259)

Bumps [black](https://github.com/psf/black) from 23.11.0 to 24.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](psf/black@23.11.0...24.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Release 1 7 5 (ClickHouse#265)

* Release 1.7.5 housekeeping

* Upgrade setuptools requirement for clickhouse_driver install

* Remove flake8 checks for the moment

* Update workflow actions

* Fix black comma

* fix(clients): add newlines around subquery when retrieving columns to avoid a syntax error (ClickHouse#262)

* Fix lint

* lazy load agate (ClickHouse#263)

* feat: add TTL support (ClickHouse#254)

* Fix lint

* Update table relation after exchange command (ClickHouse#230)

Related to ClickHouse#226

* feat: allow to add connection overrides for dictionaries (ClickHouse#267)

* Housekeeping for 1.7.6 release (ClickHouse#268)

* Revert "allows to add a comment in table's or view's metadata"

* Fix bool_or behavior (ClickHouse#270)

* feat: support column codecs

* Use Column.data_type in ClickHouseAdapter.format_columns

* Always apply query_settings in clickhouse__insert_into macro

* Add ClickHouseColumn.is_low_cardinality

* Update column type test cases for LowCardinality

* Omit empty dictionary connection_overrides from materialization DDL

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Schum <68906108+Schum-io@users.noreply.github.com>
Co-authored-by: Geoff Genz <geoff@clickhouse.com>
Co-authored-by: Sergey Reshetnikov <resh.sersh@gmail.com>
Co-authored-by: gladkikhtutu <88535677+gladkikhtutu@users.noreply.github.com>
Co-authored-by: Damir Basic Knezevic <damirbasicknezevic@gmail.com>
Co-authored-by: Zhenbang <122523068+zli06160@users.noreply.github.com>
Co-authored-by: Andy <email@elevatesystems.co.uk>
Co-authored-by: gfunc <fcjchaojian@gmail.com>
Co-authored-by: Kristof Szaloki <szalokikristof@gmail.com>
Co-authored-by: Steven Reitsma <4895139+StevenReitsma@users.noreply.github.com>
Co-authored-by: Rory Sawyer <rory@sawyer.dev>
Co-authored-by: ptemarvelde <45282601+ptemarvelde@users.noreply.github.com>
Co-authored-by: Dmitrii Tcimokha <dstsimokha@gmail.com>
Co-authored-by: bentsileviav <bentsi.leviav@clickhouse.com>
Co-authored-by: Dmitriy Sokolov <silentsokolov@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: triou <teva.riou@gmail.com>
Co-authored-by: Daniel Reeves <31971762+dwreeves@users.noreply.github.com>
Co-authored-by: Cristhian Garcia <crisgarta8@gmail.com>
Co-authored-by: Thomas Schmidt <somtom91@gmail.com>
Co-authored-by: scrawfor <scrawfor@users.noreply.github.com>
Co-authored-by: Robin Norgren <68205730+rjoelnorgren@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants