1
+ import logging
2
+ import typing
3
+ import re
4
+
5
+
6
+ from redshift_connector .utils .oids import RedshiftOID
7
+ from redshift_connector .utils .sql_types import SQLType
8
+
9
+ from redshift_connector .error import (
10
+ MISSING_MODULE_ERROR_MSG ,
11
+ InterfaceError ,
12
+ ProgrammingError ,
13
+ )
14
+
15
+ _logger : logging .Logger = logging .getLogger (__name__ )
16
+
17
+
18
+ class MetadataAPIHelper :
19
+ def __init__ (self : "MetadataAPIHelper" ) -> None :
20
+ self ._CatalogsColNum : int = 1
21
+ self ._get_catalogs_col : typing .Dict = {"TABLE_CAT" : int (RedshiftOID .VARCHAR )}
22
+
23
+ self ._SchemasColNum : int = 2
24
+ self ._get_schemas_col : typing .Dict = {"TABLE_SCHEM" : int (RedshiftOID .VARCHAR ),
25
+ "TABLE_CATALOG" : int (RedshiftOID .VARCHAR )}
26
+
27
+ self ._TablesColNum : int = 10
28
+ self ._get_tables_col : typing .Dict = {"TABLE_CAT" : int (RedshiftOID .VARCHAR ),
29
+ "TABLE_SCHEM" : int (RedshiftOID .VARCHAR ),
30
+ "TABLE_NAME" : int (RedshiftOID .VARCHAR ),
31
+ "TABLE_TYPE" : int (RedshiftOID .VARCHAR ),
32
+ "REMARKS" : int (RedshiftOID .VARCHAR ),
33
+ "TYPE_CAT" : int (RedshiftOID .VARCHAR ),
34
+ "TYPE_SCHEM" : int (RedshiftOID .VARCHAR ),
35
+ "TYPE_NAME" : int (RedshiftOID .VARCHAR ),
36
+ "SELF_REFERENCING_COL_NAME" : int (RedshiftOID .VARCHAR ),
37
+ "REF_GENERATION" : int (RedshiftOID .VARCHAR )}
38
+
39
+ self ._ColumnsColNum : int = 24
40
+ self ._get_columns_col : typing .Dict = {"TABLE_CAT" : int (RedshiftOID .VARCHAR ),
41
+ "TABLE_SCHEM" : int (RedshiftOID .VARCHAR ),
42
+ "TABLE_NAME" : int (RedshiftOID .VARCHAR ),
43
+ "COLUMN_NAME" : int (RedshiftOID .VARCHAR ),
44
+ "DATA_TYPE" : int (RedshiftOID .INTEGER ),
45
+ "TYPE_NAME" : int (RedshiftOID .VARCHAR ),
46
+ "COLUMN_SIZE" : int (RedshiftOID .INTEGER ),
47
+ "BUFFER_LENGTH" : int (RedshiftOID .INTEGER ),
48
+ "DECIMAL_DIGITS" : int (RedshiftOID .INTEGER ),
49
+ "NUM_PREC_RADIX" : int (RedshiftOID .INTEGER ),
50
+ "NULLABLE" : int (RedshiftOID .INTEGER ),
51
+ "REMARKS" : int (RedshiftOID .VARCHAR ),
52
+ "COLUMN_DEF" : int (RedshiftOID .VARCHAR ),
53
+ "SQL_DATA_TYPE" : int (RedshiftOID .INTEGER ),
54
+ "SQL_DATETIME_SUB" : int (RedshiftOID .INTEGER ),
55
+ "CHAR_OCTET_LENGTH" : int (RedshiftOID .INTEGER ),
56
+ "ORDINAL_POSITION" : int (RedshiftOID .INTEGER ),
57
+ "IS_NULLABLE" : int (RedshiftOID .VARCHAR ),
58
+ "SCOPE_CATALOG" : int (RedshiftOID .VARCHAR ),
59
+ "SCOPE_SCHEMA" : int (RedshiftOID .VARCHAR ),
60
+ "SCOPE_TABLE" : int (RedshiftOID .VARCHAR ),
61
+ "SOURCE_DATA_TYPE" : int (RedshiftOID .SMALLINT ),
62
+ "IS_AUTOINCREMENT" : int (RedshiftOID .VARCHAR ),
63
+ "IS_GENERATEDCOLUMN" : int (RedshiftOID .VARCHAR )}
64
+
65
+ self ._SHOW_DATABASES_database_name : str = 'database_name'
66
+
67
+ self ._SHOW_SCHEMA_database_name : str = 'database_name'
68
+ self ._SHOW_SCHEMA_schema_name : str = 'schema_name'
69
+
70
+ self ._SHOW_TABLES_database_name : str = 'database_name'
71
+ self ._SHOW_TABLES_schema_name : str = 'schema_name'
72
+ self ._SHOW_TABLES_table_name : str = 'table_name'
73
+ self ._SHOW_TABLES_table_type : str = 'table_type'
74
+ self ._SHOW_TABLES_remarks : str = 'remarks'
75
+
76
+ self ._SHOW_COLUMNS_database_name : str = "database_name"
77
+ self ._SHOW_COLUMNS_schema_name : str = "schema_name"
78
+ self ._SHOW_COLUMNS_table_name : str = "table_name"
79
+ self ._SHOW_COLUMNS_column_name : str = "column_name"
80
+ self ._SHOW_COLUMNS_ordinal_position : str = "ordinal_position"
81
+ self ._SHOW_COLUMNS_column_default : str = "column_default"
82
+ self ._SHOW_COLUMNS_is_nullable : str = "is_nullable"
83
+ self ._SHOW_COLUMNS_data_type : str = "data_type"
84
+ self ._SHOW_COLUMNS_character_maximum_length : str = "character_maximum_length"
85
+ self ._SHOW_COLUMNS_numeric_precision : str = "numeric_precision"
86
+ self ._SHOW_COLUMNS_numeric_scale : str = "numeric_scale"
87
+ self ._SHOW_COLUMNS_remarks : str = "remarks"
88
+
89
+
90
+ self ._sql_show_databases : str = "SHOW DATABASES;"
91
+ self ._sql_show_databases_like : str = "SHOW DATABASES LIKE '{0}';"
92
+ self ._sql_show_schemas : str = "SHOW SCHEMAS FROM DATABASE {0};"
93
+ self ._sql_show_schemas_like : str = "SHOW SCHEMAS FROM DATABASE {0} LIKE '{1}';"
94
+ self ._sql_show_tables : str = "SHOW TABLES FROM SCHEMA {0}.{1};"
95
+ self ._sql_show_tables_like : str = "SHOW TABLES FROM SCHEMA {0}.{1} LIKE '{2}';"
96
+ self ._sql_show_columns : str = "SHOW COLUMNS FROM TABLE {0}.{1}.{2};"
97
+ self ._sql_show_columns_like : str = "SHOW COLUMNS FROM TABLE {0}.{1}.{2} LIKE '{3}';"
98
+
99
+ self .__rs_type_map = {
100
+ "character varying" : "varchar" ,
101
+ "\" char\" " : "char" ,
102
+ "character" : "char" ,
103
+ "smallint" : "int2" ,
104
+ "integer" : "int4" ,
105
+ "bigint" : "int8" ,
106
+ "real" : "float4" ,
107
+ "double precision" : "float8" ,
108
+ "boolean" : "bool" ,
109
+ "time without time zone" : "time" ,
110
+ "time with time zone" : "timetz" ,
111
+ "timestamp without time zone" : "timestamp" ,
112
+ "timestamp with time zone" : "timestamptz" ,
113
+ "interval year to month" : "intervaly2m" ,
114
+ "interval year" : "intervaly2m" ,
115
+ "interval month" : "intervaly2m" ,
116
+ "interval day to second" : "intervald2s" ,
117
+ "interval day" : "intervald2s" ,
118
+ "interval second" : "intervald2s" ,
119
+ "binary varying" : "varbyte"
120
+ }
121
+
122
+ self .__sql_type_mapping = {
123
+ "varchar" : int (SQLType .SQL_VARCHAR ),
124
+ "char" : int (SQLType .SQL_CHAR ),
125
+ "int2" : int (SQLType .SQL_SMALLINT ),
126
+ "int4" : int (SQLType .SQL_INTEGER ),
127
+ "int8" : int (SQLType .SQL_BIGINT ),
128
+ "float4" : int (SQLType .SQL_REAL ),
129
+ "float8" : int (SQLType .SQL_DOUBLE ),
130
+ "numeric" : int (SQLType .SQL_NUMERIC ),
131
+ "bool" : int (SQLType .SQL_BIT ),
132
+ "date" : int (SQLType .SQL_DATE ),
133
+ "time" : int (SQLType .SQL_TIME ),
134
+ "timetz" : int (SQLType .SQL_TIME_WITH_TIMEZONE ),
135
+ "timestamp" : int (SQLType .SQL_TIMESTAMP ),
136
+ "timestamptz" : int (SQLType .SQL_TIMESTAMP_WITH_TIMEZONE ),
137
+ "intervaly2m" : int (SQLType .SQL_OTHER ),
138
+ "intervald2s" : int (SQLType .SQL_OTHER ),
139
+ "super" : int (SQLType .SQL_LONGVARCHAR ),
140
+ "geometry" : int (SQLType .SQL_LONGVARBINARY ),
141
+ "geography" : int (SQLType .SQL_LONGVARBINARY ),
142
+ "varbyte" : int (SQLType .SQL_LONGVARBINARY )
143
+ }
144
+
145
+ self .__data_type_length = {
146
+ "bool" : 1 ,
147
+ "bit" : 1 ,
148
+ "boolean" : 1 ,
149
+ "int2" : 5 ,
150
+ "smallint" : 5 ,
151
+ "int4" : 10 ,
152
+ "integer" : 10 ,
153
+ "int" : 10 ,
154
+ "int8" : 19 ,
155
+ "bigint" : 19 ,
156
+ "float4" : 8 ,
157
+ "real" : 8 ,
158
+ "float8" : 17 ,
159
+ "double precision" : 17 ,
160
+ "date" : 13 ,
161
+ "time" : 15 ,
162
+ "timetz" : 21 ,
163
+ "timestamp" : 29 ,
164
+ "timestamptz" : 35 ,
165
+ "intervaly2m" : 32 ,
166
+ "intervald2s" : 64
167
+ }
168
+
169
+ def get_second_fraction (self , data_type : str = None ) -> (str , bool ):
170
+ date_time_customize_precision : bool = False
171
+ precisions : int = 6
172
+ if re .match (r"(time|timetz|timestamp|timestamptz).*\(\d+\)" , data_type ) or re .match (r"interval.*\(\d+\)" , data_type ):
173
+ rs_type = self .get_rs_type (str (re .sub (r"\(\d+\)" , "" , data_type ).rstrip ()))
174
+ precisions = int (re .search (r"\(\d+\)" , data_type ).group (0 )[1 :- 1 ])
175
+ date_time_customize_precision = True
176
+ else :
177
+ rs_type = self .get_rs_type (data_type )
178
+
179
+ return rs_type , date_time_customize_precision , precisions
180
+
181
+ def get_rs_type (self , rs_type : str ) -> str :
182
+ return self .__rs_type_map .get (rs_type , rs_type )
183
+
184
+ def get_sql_type (self ,rs_type : str ) -> int :
185
+ return self .__sql_type_mapping .get (rs_type , int (SQLType .SQL_OTHER ))
186
+
187
+
188
+ def get_column_size (self , rs_type : str , numeric_precision : int , character_maximum_length : int ) -> int :
189
+ if rs_type == "numeric" or rs_type == "decimal" :
190
+ return int (numeric_precision )
191
+ elif rs_type == "varchar" or rs_type == "character varying" or rs_type == "char" or rs_type == "character" or rs_type == "bpchar" :
192
+ return int (character_maximum_length )
193
+ elif rs_type == "super" or rs_type == "geometry" or rs_type == "geography" or rs_type == "varbyte" :
194
+ return None
195
+ else :
196
+ return self .__data_type_length .get (rs_type , 2147483647 )
197
+
198
+ @staticmethod
199
+ def get_decimal_digits (rs_type : str , numeric_scale : int , precision : int , customizePrecision : bool ) -> int :
200
+ if rs_type == "float4" or rs_type == "real" :
201
+ return 8
202
+ elif rs_type == "float8" or rs_type == "double precision" :
203
+ return 17
204
+ elif rs_type == "numeric" or rs_type == "decimal" :
205
+ return int (numeric_scale )
206
+ elif rs_type == "time" or rs_type == "timetz" or rs_type == "timestamp" or rs_type == "timestamptz" or rs_type == "intervald2s" :
207
+ return precision if customizePrecision else 6
208
+ elif rs_type == "super" or rs_type == "geometry" or rs_type == "geography" or rs_type == "varbyte" :
209
+ return None
210
+ else :
211
+ return 0
212
+
213
+ @staticmethod
214
+ def get_num_prefix_radix (rs_type : str ) -> int :
215
+ if rs_type == "geography" or rs_type == "varbyte" :
216
+ return 2
217
+ else :
218
+ return 10
219
+
220
+ @staticmethod
221
+ def get_nullable (nullable : str ) -> int :
222
+ if nullable == "YES" :
223
+ return 1
224
+ elif nullable == "NO" :
225
+ return 0
226
+ else :
227
+ return 2
228
+
229
+ @staticmethod
230
+ def get_auto_increment (col_def : str ) -> str :
231
+ if col_def is not None and ("\" identity\" " in col_def or "default_identity" in col_def ):
232
+ return "YES"
233
+ else :
234
+ return "NO"
235
+
236
+ @staticmethod
237
+ def check_name_is_not_pattern (name : str ) -> bool :
238
+ return name is None or not name or name == "%"
239
+
240
+ @staticmethod
241
+ def check_name_is_exact_name (name : str ) -> bool :
242
+ if name is not None and len (name ) != 0 and ("%" not in name ):
243
+ return True
244
+ return False
0 commit comments