2020-12-21 19:20:56 +00:00
|
|
|
import pytest
|
|
|
|
import psycopg2
|
|
|
|
|
|
|
|
from helpers.cluster import ClickHouseCluster
|
|
|
|
from helpers.test_tools import assert_eq_with_retry
|
|
|
|
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
|
|
|
|
|
|
|
|
cluster = ClickHouseCluster(__file__)
|
2021-09-01 23:17:15 +00:00
|
|
|
node1 = cluster.add_instance('node1', main_configs=["configs/named_collections.xml"], with_postgres=True)
|
2020-12-21 19:20:56 +00:00
|
|
|
|
|
|
|
postgres_table_template = """
|
2022-01-21 17:03:48 +00:00
|
|
|
CREATE TABLE {} (
|
2020-12-21 19:20:56 +00:00
|
|
|
id Integer NOT NULL, value Integer, PRIMARY KEY (id))
|
|
|
|
"""
|
|
|
|
|
2022-01-21 17:03:48 +00:00
|
|
|
postgres_drop_table_template = """
|
|
|
|
DROP TABLE {}
|
|
|
|
"""
|
|
|
|
|
2021-03-19 16:44:08 +00:00
|
|
|
def get_postgres_conn(cluster, database=False):
|
2020-12-21 19:20:56 +00:00
|
|
|
if database == True:
|
2021-03-19 16:44:08 +00:00
|
|
|
conn_string = f"host={cluster.postgres_ip} port={cluster.postgres_port} dbname='test_database' user='postgres' password='mysecretpassword'"
|
2020-12-21 19:20:56 +00:00
|
|
|
else:
|
2021-03-19 16:44:08 +00:00
|
|
|
conn_string = f"host={cluster.postgres_ip} port={cluster.postgres_port} user='postgres' password='mysecretpassword'"
|
2020-12-21 19:20:56 +00:00
|
|
|
conn = psycopg2.connect(conn_string)
|
|
|
|
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
|
|
|
|
conn.autocommit = True
|
|
|
|
return conn
|
|
|
|
|
|
|
|
def create_postgres_db(cursor, name):
|
|
|
|
cursor.execute("CREATE DATABASE {}".format(name))
|
|
|
|
|
|
|
|
def create_postgres_table(cursor, table_name):
|
|
|
|
# database was specified in connection string
|
|
|
|
cursor.execute(postgres_table_template.format(table_name))
|
|
|
|
|
2022-01-21 17:03:48 +00:00
|
|
|
def drop_postgres_table(cursor, table_name):
|
|
|
|
# database was specified in connection string
|
|
|
|
cursor.execute(postgres_drop_table_template.format(table_name))
|
2020-12-21 19:20:56 +00:00
|
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
|
|
def started_cluster():
|
|
|
|
try:
|
|
|
|
cluster.start()
|
2021-03-19 16:44:08 +00:00
|
|
|
conn = get_postgres_conn(cluster)
|
2020-12-21 19:20:56 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
create_postgres_db(cursor, 'test_database')
|
|
|
|
yield cluster
|
|
|
|
|
|
|
|
finally:
|
|
|
|
cluster.shutdown()
|
|
|
|
|
|
|
|
|
|
|
|
def test_postgres_database_engine_with_postgres_ddl(started_cluster):
|
|
|
|
# connect to database as well
|
2021-03-19 16:44:08 +00:00
|
|
|
conn = get_postgres_conn(started_cluster, True)
|
2020-12-21 19:20:56 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
|
|
node1.query(
|
|
|
|
"CREATE DATABASE test_database ENGINE = PostgreSQL('postgres1:5432', 'test_database', 'postgres', 'mysecretpassword')")
|
|
|
|
assert 'test_database' in node1.query('SHOW DATABASES')
|
|
|
|
|
|
|
|
create_postgres_table(cursor, 'test_table')
|
|
|
|
assert 'test_table' in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
cursor.execute('ALTER TABLE test_table ADD COLUMN data Text')
|
|
|
|
assert 'data' in node1.query("SELECT name FROM system.columns WHERE table = 'test_table' AND database = 'test_database'")
|
|
|
|
|
|
|
|
cursor.execute('ALTER TABLE test_table DROP COLUMN data')
|
|
|
|
assert 'data' not in node1.query("SELECT name FROM system.columns WHERE table = 'test_table' AND database = 'test_database'")
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE test_database")
|
|
|
|
assert 'test_database' not in node1.query('SHOW DATABASES')
|
|
|
|
|
2022-01-21 17:03:48 +00:00
|
|
|
drop_postgres_table(cursor, 'test_table')
|
|
|
|
|
2020-12-21 19:20:56 +00:00
|
|
|
|
|
|
|
def test_postgresql_database_engine_with_clickhouse_ddl(started_cluster):
|
2021-03-19 16:44:08 +00:00
|
|
|
conn = get_postgres_conn(started_cluster, True)
|
2020-12-21 19:20:56 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
|
|
node1.query(
|
|
|
|
"CREATE DATABASE test_database ENGINE = PostgreSQL('postgres1:5432', 'test_database', 'postgres', 'mysecretpassword')")
|
|
|
|
|
|
|
|
create_postgres_table(cursor, 'test_table')
|
|
|
|
assert 'test_table' in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("DROP TABLE test_database.test_table")
|
|
|
|
assert 'test_table' not in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("ATTACH TABLE test_database.test_table")
|
|
|
|
assert 'test_table' in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("DETACH TABLE test_database.test_table")
|
|
|
|
assert 'test_table' not in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("ATTACH TABLE test_database.test_table")
|
|
|
|
assert 'test_table' in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE test_database")
|
|
|
|
assert 'test_database' not in node1.query('SHOW DATABASES')
|
|
|
|
|
2022-01-21 17:03:48 +00:00
|
|
|
drop_postgres_table(cursor, 'test_table')
|
|
|
|
|
2020-12-21 19:20:56 +00:00
|
|
|
|
|
|
|
def test_postgresql_database_engine_queries(started_cluster):
|
2021-03-19 16:44:08 +00:00
|
|
|
conn = get_postgres_conn(started_cluster, True)
|
2020-12-21 19:20:56 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
|
|
node1.query(
|
|
|
|
"CREATE DATABASE test_database ENGINE = PostgreSQL('postgres1:5432', 'test_database', 'postgres', 'mysecretpassword')")
|
|
|
|
|
|
|
|
create_postgres_table(cursor, 'test_table')
|
|
|
|
assert node1.query("SELECT count() FROM test_database.test_table").rstrip() == '0'
|
|
|
|
|
|
|
|
node1.query("INSERT INTO test_database.test_table SELECT number, number from numbers(10000)")
|
|
|
|
assert node1.query("SELECT count() FROM test_database.test_table").rstrip() == '10000'
|
|
|
|
|
2022-01-21 17:03:48 +00:00
|
|
|
drop_postgres_table(cursor, 'test_table')
|
2020-12-26 19:38:10 +00:00
|
|
|
assert 'test_table' not in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE test_database")
|
|
|
|
assert 'test_database' not in node1.query('SHOW DATABASES')
|
|
|
|
|
|
|
|
|
2021-01-10 09:00:35 +00:00
|
|
|
def test_get_create_table_query_with_multidim_arrays(started_cluster):
|
2021-03-19 16:44:08 +00:00
|
|
|
conn = get_postgres_conn(started_cluster, True)
|
2021-01-10 09:00:35 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
|
|
node1.query(
|
|
|
|
"CREATE DATABASE test_database ENGINE = PostgreSQL('postgres1:5432', 'test_database', 'postgres', 'mysecretpassword')")
|
|
|
|
|
|
|
|
cursor.execute("""
|
2022-01-21 17:03:48 +00:00
|
|
|
CREATE TABLE array_columns (
|
2021-01-10 09:00:35 +00:00
|
|
|
b Integer[][][] NOT NULL,
|
|
|
|
c Integer[][][]
|
|
|
|
)""")
|
|
|
|
|
|
|
|
node1.query("DETACH TABLE test_database.array_columns")
|
|
|
|
node1.query("ATTACH TABLE test_database.array_columns")
|
|
|
|
|
|
|
|
node1.query("INSERT INTO test_database.array_columns "
|
|
|
|
"VALUES ("
|
|
|
|
"[[[1, 1], [1, 1]], [[3, 3], [3, 3]], [[4, 4], [5, 5]]], "
|
|
|
|
"[[[1, NULL], [NULL, 1]], [[NULL, NULL], [NULL, NULL]], [[4, 4], [5, 5]]] "
|
|
|
|
")")
|
|
|
|
result = node1.query('''
|
|
|
|
SELECT * FROM test_database.array_columns''')
|
|
|
|
expected = (
|
|
|
|
"[[[1,1],[1,1]],[[3,3],[3,3]],[[4,4],[5,5]]]\t"
|
|
|
|
"[[[1,NULL],[NULL,1]],[[NULL,NULL],[NULL,NULL]],[[4,4],[5,5]]]\n"
|
|
|
|
)
|
|
|
|
assert(result == expected)
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE test_database")
|
|
|
|
assert 'test_database' not in node1.query('SHOW DATABASES')
|
2022-01-21 17:03:48 +00:00
|
|
|
drop_postgres_table(cursor, 'array_columns')
|
2021-01-10 09:00:35 +00:00
|
|
|
|
|
|
|
|
2020-12-26 19:38:10 +00:00
|
|
|
def test_postgresql_database_engine_table_cache(started_cluster):
|
2021-03-19 16:44:08 +00:00
|
|
|
conn = get_postgres_conn(started_cluster, True)
|
2020-12-26 19:38:10 +00:00
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
|
|
node1.query(
|
2021-08-05 07:25:47 +00:00
|
|
|
"CREATE DATABASE test_database ENGINE = PostgreSQL('postgres1:5432', 'test_database', 'postgres', 'mysecretpassword', '', 1)")
|
2020-12-26 19:38:10 +00:00
|
|
|
|
|
|
|
create_postgres_table(cursor, 'test_table')
|
|
|
|
assert node1.query('DESCRIBE TABLE test_database.test_table').rstrip() == 'id\tInt32\t\t\t\t\t\nvalue\tNullable(Int32)'
|
|
|
|
|
|
|
|
cursor.execute('ALTER TABLE test_table ADD COLUMN data Text')
|
|
|
|
assert node1.query('DESCRIBE TABLE test_database.test_table').rstrip() == 'id\tInt32\t\t\t\t\t\nvalue\tNullable(Int32)'
|
|
|
|
|
|
|
|
node1.query("DETACH TABLE test_database.test_table")
|
|
|
|
assert 'test_table' not in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("ATTACH TABLE test_database.test_table")
|
|
|
|
assert 'test_table' in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
assert node1.query('DESCRIBE TABLE test_database.test_table').rstrip() == 'id\tInt32\t\t\t\t\t\nvalue\tNullable(Int32)\t\t\t\t\t\ndata\tNullable(String)'
|
|
|
|
|
|
|
|
node1.query("DROP TABLE test_database.test_table")
|
|
|
|
assert 'test_table' not in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("ATTACH TABLE test_database.test_table")
|
|
|
|
assert 'test_table' in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
|
|
|
node1.query("INSERT INTO test_database.test_table SELECT number, number, toString(number) from numbers(10000)")
|
|
|
|
assert node1.query("SELECT count() FROM test_database.test_table").rstrip() == '10000'
|
|
|
|
|
|
|
|
cursor.execute('DROP TABLE test_table;')
|
|
|
|
assert 'test_table' not in node1.query('SHOW TABLES FROM test_database')
|
|
|
|
|
2020-12-21 19:20:56 +00:00
|
|
|
node1.query("DROP DATABASE test_database")
|
|
|
|
assert 'test_database' not in node1.query('SHOW DATABASES')
|
|
|
|
|
|
|
|
|
2021-08-04 20:42:29 +00:00
|
|
|
def test_postgresql_database_with_schema(started_cluster):
|
|
|
|
conn = get_postgres_conn(started_cluster, True)
|
|
|
|
cursor = conn.cursor()
|
|
|
|
|
|
|
|
cursor.execute('CREATE SCHEMA test_schema')
|
|
|
|
cursor.execute('CREATE TABLE test_schema.table1 (a integer)')
|
|
|
|
cursor.execute('CREATE TABLE test_schema.table2 (a integer)')
|
|
|
|
cursor.execute('CREATE TABLE table3 (a integer)')
|
|
|
|
|
|
|
|
node1.query(
|
|
|
|
"CREATE DATABASE test_database ENGINE = PostgreSQL('postgres1:5432', 'test_database', 'postgres', 'mysecretpassword', 'test_schema')")
|
|
|
|
|
|
|
|
assert(node1.query('SHOW TABLES FROM test_database') == 'table1\ntable2\n')
|
|
|
|
|
|
|
|
node1.query("INSERT INTO test_database.table1 SELECT number from numbers(10000)")
|
|
|
|
assert node1.query("SELECT count() FROM test_database.table1").rstrip() == '10000'
|
|
|
|
node1.query("DETACH TABLE test_database.table1")
|
|
|
|
node1.query("ATTACH TABLE test_database.table1")
|
|
|
|
assert node1.query("SELECT count() FROM test_database.table1").rstrip() == '10000'
|
|
|
|
node1.query("DROP DATABASE test_database")
|
|
|
|
|
2022-01-21 17:03:48 +00:00
|
|
|
cursor.execute('DROP SCHEMA test_schema CASCADE')
|
|
|
|
cursor.execute('DROP TABLE table3')
|
|
|
|
|
2021-08-04 20:42:29 +00:00
|
|
|
|
2021-09-01 23:17:15 +00:00
|
|
|
def test_predefined_connection_configuration(started_cluster):
|
|
|
|
cursor = started_cluster.postgres_conn.cursor()
|
|
|
|
cursor.execute(f'DROP TABLE IF EXISTS test_table')
|
|
|
|
cursor.execute(f'CREATE TABLE test_table (a integer PRIMARY KEY, b integer)')
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE IF EXISTS postgres_database")
|
|
|
|
node1.query("CREATE DATABASE postgres_database ENGINE = PostgreSQL(postgres1)")
|
|
|
|
node1.query("INSERT INTO postgres_database.test_table SELECT number, number from numbers(100)")
|
|
|
|
assert (node1.query(f"SELECT count() FROM postgres_database.test_table").rstrip() == '100')
|
|
|
|
|
|
|
|
cursor.execute('CREATE SCHEMA test_schema')
|
|
|
|
cursor.execute('CREATE TABLE test_schema.test_table (a integer)')
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE IF EXISTS postgres_database")
|
|
|
|
node1.query("CREATE DATABASE postgres_database ENGINE = PostgreSQL(postgres1, schema='test_schema')")
|
|
|
|
node1.query("INSERT INTO postgres_database.test_table SELECT number from numbers(200)")
|
|
|
|
assert (node1.query(f"SELECT count() FROM postgres_database.test_table").rstrip() == '200')
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE IF EXISTS postgres_database")
|
|
|
|
node1.query_and_get_error("CREATE DATABASE postgres_database ENGINE = PostgreSQL(postgres1, 'test_schema')")
|
|
|
|
node1.query_and_get_error("CREATE DATABASE postgres_database ENGINE = PostgreSQL(postgres2)")
|
|
|
|
node1.query_and_get_error("CREATE DATABASE postgres_database ENGINE = PostgreSQL(unknown_collection)")
|
|
|
|
node1.query("CREATE DATABASE postgres_database ENGINE = PostgreSQL(postgres3, port=5432)")
|
|
|
|
assert (node1.query(f"SELECT count() FROM postgres_database.test_table").rstrip() == '100')
|
|
|
|
|
|
|
|
node1.query("DROP DATABASE postgres_database")
|
|
|
|
cursor.execute(f'DROP TABLE test_table ')
|
2022-01-21 17:03:48 +00:00
|
|
|
cursor.execute('DROP SCHEMA IF EXISTS test_schema CASCADE')
|
|
|
|
|
2021-09-01 23:17:15 +00:00
|
|
|
|
|
|
|
|
2020-12-21 19:20:56 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
cluster.start()
|
|
|
|
input("Cluster created, press any key to destroy...")
|
|
|
|
cluster.shutdown()
|