143143 MISSING_RELATION_ERROR_FRAGMENT ,
144144 SCHEMA_REGISTRY_TABLE ,
145145 SQLITE_TABLE_TYPE ,
146+ TEMPORAL_TYPE_PATTERN ,
146147 UNSUPPORTED_FEATURE_CODE ,
147148 VERSION_TOO_OLD_CODE ,
148149)
156157_INFERRED_COLUMN_TYPES : ContextVar [Mapping [str , str ]] = ContextVar (
157158 "sqlite_inferred_column_types" , default = MappingProxyType ({})
158159)
160+ _TEMPORAL_TYPE : re .Pattern [str ] = re .compile (TEMPORAL_TYPE_PATTERN , re .IGNORECASE )
159161_TRUE_SEED_VALUES : frozenset [str ] = frozenset ({"true" , "t" , "yes" , "y" , "1" })
160162_FALSE_SEED_VALUES : frozenset [str ] = frozenset ({"false" , "f" , "no" , "n" , "0" })
161163
@@ -2237,7 +2239,9 @@ def render_loader_value_literal(
22372239 return "1" if value else "0"
22382240 if isinstance (value , int | float | Decimal ):
22392241 return str (value )
2240- if isinstance (value , datetime | date ):
2242+ if isinstance (value , datetime ):
2243+ return _quote_sql_string (canonical_timestamp_text (value .isoformat ()))
2244+ if isinstance (value , date ):
22412245 return _quote_sql_string (value .isoformat ())
22422246 return _quote_sql_string (str (value ))
22432247
@@ -2249,13 +2253,12 @@ def render_loader_rows_select(
22492253 column_sql_types : dict [str , str ],
22502254 inferred_types : dict [str , LoaderLogicalType ],
22512255 ) -> str :
2252- """Render rows as one multi-row VALUES; SQLite names VALUES columns column1, column2 ."""
2256+ """Render uncast rows as one VALUES; staging declares the types and affinity converts ."""
22532257
2258+ del column_sql_types
22542259 if not rows :
22552260 projections : str = ", " .join (
2256- f"CAST(NULL AS { column_sql_types .get (column_name , 'TEXT' )} ) AS "
2257- f"{ self .render_identifier (column_name )} "
2258- for column_name in column_names
2261+ f"NULL AS { self .render_identifier (column_name )} " for column_name in column_names
22592262 )
22602263 return f"SELECT { projections } WHERE 1 = 0"
22612264 value_rows : list [str ] = []
@@ -2270,21 +2273,18 @@ def render_loader_rows_select(
22702273 value_rows .append (f"({ literals } )" )
22712274 values_sql : str = ", " .join (value_rows )
22722275 select_sql : str = ", " .join (
2273- (
2274- f"column{ index } AS { self .render_identifier (column_name )} "
2275- if column_name not in column_sql_types
2276- else f"CAST(column{ index } AS { column_sql_types [column_name ]} ) "
2277- f"AS { self .render_identifier (column_name )} "
2278- )
2276+ f"column{ index } AS { self .render_identifier (column_name )} "
22792277 for index , column_name in enumerate (column_names , start = 1 )
22802278 )
22812279 return f"SELECT { select_sql } FROM (VALUES { values_sql } ) AS __loader_rows"
22822280
22832281 def render_source_expression_cast (
22842282 self , * , expression : str , target_type : str , alias : str
22852283 ) -> str :
2286- """Cast, rendering exact decimals as canonical fixed-scale text."""
2284+ """Cast, keeping date and time text and rendering exact decimals as fixed-scale text."""
22872285
2286+ if _TEMPORAL_TYPE .match (target_type ) is not None :
2287+ return f"{ expression } AS { alias } "
22882288 scale : int | None = decimal_scale (target_type )
22892289 if scale is None :
22902290 return f"CAST({ expression } AS { target_type } ) AS { alias } "
0 commit comments