13
13
from cryptography .hazmat .primitives import serialization
14
14
from singer_sdk import typing as th
15
15
from singer_sdk .connectors import SQLConnector
16
- from singer_sdk .connectors .sql import FullyQualifiedName
16
+ from singer_sdk .connectors .sql import FullyQualifiedName , JSONSchemaToSQL
17
17
from singer_sdk .exceptions import ConfigValidationError
18
18
from snowflake .sqlalchemy import URL
19
19
from snowflake .sqlalchemy .base import SnowflakeIdentifierPreparer
27
27
28
28
from sqlalchemy .engine import Engine
29
29
30
+ # TODO: Remove this when when JSON schema to SQL is stable
30
31
SNOWFLAKE_MAX_STRING_LENGTH = 16777216
31
32
32
33
@@ -89,6 +90,8 @@ class SnowflakeConnector(SQLConnector):
89
90
allow_merge_upsert : bool = False # Whether MERGE UPSERT is supported.
90
91
allow_temp_tables : bool = True # Whether temp tables are supported.
91
92
93
+ max_varchar_length = 16_777_216
94
+
92
95
def __init__ (self , * args : Any , ** kwargs : Any ) -> None :
93
96
self .table_cache : dict = {}
94
97
self .schema_cache : dict = {}
@@ -317,6 +320,16 @@ def _conform_max_length(jsonschema_type): # noqa: ANN205, ANN001
317
320
jsonschema_type ["maxLength" ] = SNOWFLAKE_MAX_STRING_LENGTH
318
321
return jsonschema_type
319
322
323
+ @cached_property
324
+ def jsonschema_to_sql (self ) -> JSONSchemaToSQL :
325
+ to_sql = super ().jsonschema_to_sql
326
+ to_sql .register_type_handler ("integer" , NUMBER )
327
+ to_sql .register_type_handler ("object" , VARIANT )
328
+ to_sql .register_type_handler ("array" , VARIANT )
329
+ to_sql .register_type_handler ("number" , sct .DOUBLE )
330
+ to_sql .register_format_handler ("date-time" , TIMESTAMP_NTZ )
331
+ return to_sql
332
+
320
333
def to_sql_type (self , jsonschema_type : dict ) -> sqlalchemy .types .TypeEngine :
321
334
"""Return a JSON Schema representation of the provided type.
322
335
@@ -336,23 +349,14 @@ def to_sql_type(self, jsonschema_type: dict) -> sqlalchemy.types.TypeEngine:
336
349
maxlength = jsonschema_type .get ("maxLength" , SNOWFLAKE_MAX_STRING_LENGTH )
337
350
# define type maps
338
351
string_submaps = [
339
- TypeMap (eq , TIMESTAMP_NTZ (), "date-time" ),
340
352
TypeMap (contains , sqlalchemy .types .TIME (), "time" ),
341
353
TypeMap (eq , sqlalchemy .types .DATE (), "date" ),
342
354
TypeMap (eq , sqlalchemy .types .VARCHAR (maxlength ), None ),
343
355
]
344
- type_maps = [
345
- TypeMap (th ._jsonschema_type_check , NUMBER (), ("integer" ,)), # noqa: SLF001
346
- TypeMap (th ._jsonschema_type_check , VARIANT (), ("object" ,)), # noqa: SLF001
347
- TypeMap (th ._jsonschema_type_check , VARIANT (), ("array" ,)), # noqa: SLF001
348
- TypeMap (th ._jsonschema_type_check , sct .DOUBLE (), ("number" ,)), # noqa: SLF001
349
- ]
350
356
# apply type maps
351
357
if th ._jsonschema_type_check (jsonschema_type , ("string" ,)): # noqa: SLF001
352
358
datelike_type = th .get_datelike_property_type (jsonschema_type )
353
359
target_type = evaluate_typemaps (string_submaps , datelike_type , target_type )
354
- else :
355
- target_type = evaluate_typemaps (type_maps , jsonschema_type , target_type )
356
360
357
361
return cast (sqlalchemy .types .TypeEngine , target_type )
358
362
0 commit comments