1
+ import re
2
+ # from clickhouse_driver import Client
3
+
4
+ # Mapping of PostgreSQL data types to ClickHouse data types
5
+ TYPE_MAPPING = {
6
+ "smallint" : "Int16" ,
7
+ "integer" : "Int32" ,
8
+ "bigint" : "Int64" ,
9
+ "serial" : "UInt32" ,
10
+ "bigserial" : "UInt64" ,
11
+ "real" : "Float32" ,
12
+ "double precision" : "Float64" ,
13
+ "numeric" : "Decimal" ,
14
+ "decimal" : "Decimal" ,
15
+ "boolean" : "UInt8" ,
16
+ "varchar" : "String" ,
17
+ "char" : "String" ,
18
+ "text" : "String" ,
19
+ "date" : "Date" ,
20
+ "timestamp" : "DateTime" ,
21
+ "timestamptz" : "DateTime" ,
22
+ "json" : "String" ,
23
+ "jsonb" : "String" ,
24
+ "uuid" : "UUID" ,
25
+ "bytea" : "String" ,
26
+ }
27
+
28
+ # Function to parse PostgreSQL CREATE TABLE statement
29
+ def parse_postgres_create_table (psql_statement ):
30
+ # Extract table name
31
+ table_name_match = re .search (r"CREATE TABLE (\w+)" , psql_statement , re .IGNORECASE )
32
+ if not table_name_match :
33
+ raise ValueError ("Table name not found in the CREATE TABLE statement." )
34
+ table_name = table_name_match .group (1 )
35
+
36
+ # Extract column definitions
37
+ column_definitions = re .findall (r"(\w+)\s+([\w\(\)\s,]+)(?:,|\))" , psql_statement )
38
+
39
+ # Extract constraints (if any)
40
+ constraints = re .findall (r"CONSTRAINT\s+(\w+)\s+(.*?)(?:,|\))" , psql_statement )
41
+
42
+ return table_name , column_definitions , constraints
43
+
44
+ # Function to convert PostgreSQL column definitions to ClickHouse
45
+ def convert_column_definitions (column_definitions ):
46
+ clickhouse_columns = []
47
+ for col_name , col_type in column_definitions :
48
+ # Extract base type (e.g., "numeric(10, 2)" -> "numeric")
49
+ base_type = re .sub (r"\(.*\)" , "" , col_type ).lower ()
50
+
51
+ # Map PostgreSQL type to ClickHouse type
52
+ if base_type in TYPE_MAPPING :
53
+ clickhouse_type = TYPE_MAPPING [base_type ]
54
+ # Handle precision/scale for numeric/decimal
55
+ if base_type in ["numeric" , "decimal" ]:
56
+ precision_scale = re .search (r"\((\d+),\s*(\d+)\)" , col_type )
57
+ if precision_scale :
58
+ clickhouse_type = f"Decimal({ precision_scale .group (1 )} , { precision_scale .group (2 )} )"
59
+ clickhouse_columns .append (f"{ col_name } { clickhouse_type } " )
60
+ else :
61
+ raise ValueError (f"Unsupported PostgreSQL data type: { base_type } " )
62
+
63
+ return clickhouse_columns
64
+
65
+ # Function to generate ClickHouse CREATE TABLE statement
66
+ def generate_clickhouse_create_table (table_name , clickhouse_columns ):
67
+ columns_str = ",\n " .join (clickhouse_columns )
68
+ return f"CREATE TABLE { table_name } (\n { columns_str } \n ) ENGINE = MergeTree() ORDER BY tuple()"
69
+
70
+ # Function to dynamically convert and execute
71
+ def convert_and_execute (psql_statement ):
72
+ # Parse PostgreSQL statement
73
+ table_name , column_definitions , constraints = parse_postgres_create_table (psql_statement )
74
+
75
+ # Convert column definitions
76
+ clickhouse_columns = convert_column_definitions (column_definitions )
77
+
78
+ # Generate ClickHouse CREATE TABLE statement
79
+ clickhouse_statement = generate_clickhouse_create_table (table_name , clickhouse_columns )
80
+ print ("Generated ClickHouse CREATE TABLE Statement:" )
81
+ print (clickhouse_statement )
82
+
83
+ # Execute in ClickHouse
84
+ # client = Client(host='localhost')
85
+ # client.execute(clickhouse_statement)
86
+ # print(f"Table '{table_name}' created successfully in ClickHouse!")
87
+
88
+ # Example PostgreSQL CREATE TABLE statement
89
+ psql_create_table = """
90
+ CREATE TABLE example_table (
91
+ id SERIAL PRIMARY KEY,
92
+ name VARCHAR(255) NOT NULL,
93
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
94
+ price NUMERIC(10, 2),
95
+ is_active BOOLEAN DEFAULT TRUE,
96
+ metadata JSONB
97
+ );
98
+ """
99
+
100
+ # Convert and execute
101
+ convert_and_execute (psql_create_table )
0 commit comments