sqlglot.generators.redshift
1from __future__ import annotations 2 3 4from sqlglot import exp, transforms 5from sqlglot.dialects.dialect import ( 6 array_concat_sql, 7 concat_to_dpipe_sql, 8 concat_ws_to_dpipe_sql, 9 date_delta_sql, 10 generatedasidentitycolumnconstraint_sql, 11 json_extract_segments, 12 no_tablesample_sql, 13 rename_func, 14) 15from sqlglot.generator import Generator 16from sqlglot.generators.postgres import PostgresGenerator 17from sqlglot.helper import seq_get 18 19 20class RedshiftGenerator(PostgresGenerator): 21 LOCKING_READS_SUPPORTED = False 22 QUERY_HINTS = False 23 CAST_TO_INT_ROUNDS = True 24 VALUES_AS_TABLE = False 25 TZ_TO_WITH_TIME_ZONE = True 26 NVL2_SUPPORTED = True 27 LAST_DAY_SUPPORTS_DATE_PART = False 28 CAN_IMPLEMENT_ARRAY_ANY = False 29 MULTI_ARG_DISTINCT = True 30 COPY_PARAMS_ARE_WRAPPED = False 31 HEX_FUNC = "TO_HEX" 32 PARSE_JSON_NAME: str | None = "JSON_PARSE" 33 ARRAY_CONCAT_IS_VAR_LEN = False 34 SUPPORTS_CONVERT_TIMEZONE = True 35 EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE = False 36 SUPPORTS_MEDIAN = True 37 ALTER_SET_TYPE = "TYPE" 38 SUPPORTS_DECODE_CASE = True 39 SUPPORTS_BETWEEN_FLAGS = False 40 LIMIT_FETCH = "LIMIT" 41 STAR_EXCEPT = "EXCLUDE" 42 STAR_EXCLUDE_REQUIRES_DERIVED_TABLE = False 43 44 # Redshift doesn't have `WITH` as part of their with_properties so we remove it 45 WITH_PROPERTIES_PREFIX = " " 46 47 TYPE_MAPPING = { 48 **PostgresGenerator.TYPE_MAPPING, 49 exp.DType.BINARY: "VARBYTE", 50 exp.DType.BLOB: "VARBYTE", 51 exp.DType.INT: "INTEGER", 52 exp.DType.TIMETZ: "TIME", 53 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 54 exp.DType.VARBINARY: "VARBYTE", 55 exp.DType.ROWVERSION: "VARBYTE", 56 } 57 58 TRANSFORMS = { 59 **{ 60 k: v 61 for k, v in PostgresGenerator.TRANSFORMS.items() 62 if k 63 not in { 64 exp.Pivot, 65 exp.ParseJSON, 66 exp.AnyValue, 67 exp.LastDay, 68 exp.SHA2, 69 exp.Getbit, 70 exp.IntDiv, 71 exp.Round, 72 exp.TryCast, 73 } 74 }, 75 exp.ArrayConcat: array_concat_sql("ARRAY_CONCAT"), 76 exp.Concat: concat_to_dpipe_sql, 77 exp.ConcatWs: concat_ws_to_dpipe_sql, 78 exp.ApproxDistinct: lambda self, e: f"APPROXIMATE COUNT(DISTINCT {self.sql(e, 'this')})", 79 exp.CurrentTimestamp: lambda self, e: "SYSDATE" if e.args.get("sysdate") else "GETDATE()", 80 exp.CurrentUserId: lambda *_: "CURRENT_USER_ID", 81 exp.DateAdd: date_delta_sql("DATEADD"), 82 exp.DateDiff: date_delta_sql("DATEDIFF"), 83 exp.DistKeyProperty: lambda self, e: self.func("DISTKEY", e.this), 84 exp.DistStyleProperty: lambda self, e: self.naked_property(e), 85 exp.Explode: lambda self, e: self.explode_sql(e), 86 exp.FarmFingerprint: rename_func("FARMFINGERPRINT64"), 87 exp.FromBase: rename_func("STRTOL"), 88 exp.GeneratedAsIdentityColumnConstraint: generatedasidentitycolumnconstraint_sql, 89 exp.JSONExtract: json_extract_segments("JSON_EXTRACT_PATH_TEXT"), 90 exp.JSONExtractScalar: json_extract_segments("JSON_EXTRACT_PATH_TEXT"), 91 exp.GroupConcat: rename_func("LISTAGG"), 92 exp.Hex: lambda self, e: self.func("UPPER", self.func("TO_HEX", self.sql(e, "this"))), 93 exp.RegexpExtract: rename_func("REGEXP_SUBSTR"), 94 exp.Select: transforms.preprocess( 95 [ 96 transforms.eliminate_window_clause, 97 transforms.eliminate_distinct_on, 98 transforms.eliminate_semi_and_anti_joins, 99 transforms.unqualify_unnest, 100 transforms.unnest_generate_date_array_using_recursive_cte, 101 ] 102 ), 103 exp.SortKeyProperty: lambda self, e: ( 104 f"{'COMPOUND ' if e.args['compound'] else ''}SORTKEY({self.format_args(*e.this)})" 105 ), 106 exp.StartsWith: lambda self, e: f"{self.sql(e.this)} LIKE {self.sql(e.expression)} || '%'", 107 exp.StringToArray: rename_func("SPLIT_TO_ARRAY"), 108 exp.TableSample: no_tablesample_sql, 109 exp.TsOrDsAdd: date_delta_sql("DATEADD"), 110 exp.TsOrDsDiff: date_delta_sql("DATEDIFF"), 111 exp.UnixToTime: lambda self, e: self._unix_to_time_sql(e), 112 exp.SHA2Digest: lambda self, e: self.func( 113 "SHA2", e.this, e.args.get("length") or exp.Literal.number(256) 114 ), 115 } 116 117 RESERVED_KEYWORDS = { 118 "aes128", 119 "aes256", 120 "all", 121 "allowoverwrite", 122 "analyse", 123 "analyze", 124 "and", 125 "any", 126 "array", 127 "as", 128 "asc", 129 "authorization", 130 "az64", 131 "backup", 132 "between", 133 "binary", 134 "blanksasnull", 135 "both", 136 "bytedict", 137 "bzip2", 138 "case", 139 "cast", 140 "check", 141 "collate", 142 "column", 143 "constraint", 144 "create", 145 "credentials", 146 "cross", 147 "current_date", 148 "current_time", 149 "current_timestamp", 150 "current_user", 151 "current_user_id", 152 "default", 153 "deferrable", 154 "deflate", 155 "defrag", 156 "delta", 157 "delta32k", 158 "desc", 159 "disable", 160 "distinct", 161 "do", 162 "else", 163 "emptyasnull", 164 "enable", 165 "encode", 166 "encrypt ", 167 "encryption", 168 "end", 169 "except", 170 "explicit", 171 "false", 172 "for", 173 "foreign", 174 "freeze", 175 "from", 176 "full", 177 "globaldict256", 178 "globaldict64k", 179 "grant", 180 "group", 181 "gzip", 182 "having", 183 "identity", 184 "ignore", 185 "ilike", 186 "in", 187 "initially", 188 "inner", 189 "intersect", 190 "interval", 191 "into", 192 "is", 193 "isnull", 194 "join", 195 "leading", 196 "left", 197 "like", 198 "limit", 199 "localtime", 200 "localtimestamp", 201 "lun", 202 "luns", 203 "lzo", 204 "lzop", 205 "minus", 206 "mostly16", 207 "mostly32", 208 "mostly8", 209 "natural", 210 "new", 211 "not", 212 "notnull", 213 "null", 214 "nulls", 215 "off", 216 "offline", 217 "offset", 218 "oid", 219 "old", 220 "on", 221 "only", 222 "open", 223 "or", 224 "order", 225 "outer", 226 "overlaps", 227 "parallel", 228 "partition", 229 "percent", 230 "permissions", 231 "pivot", 232 "placing", 233 "primary", 234 "raw", 235 "readratio", 236 "recover", 237 "references", 238 "rejectlog", 239 "resort", 240 "respect", 241 "restore", 242 "right", 243 "select", 244 "session_user", 245 "similar", 246 "snapshot", 247 "some", 248 "sysdate", 249 "system", 250 "table", 251 "tag", 252 "tdes", 253 "text255", 254 "text32k", 255 "then", 256 "timestamp", 257 "to", 258 "top", 259 "trailing", 260 "true", 261 "truncatecolumns", 262 "type", 263 "union", 264 "unique", 265 "unnest", 266 "unpivot", 267 "user", 268 "using", 269 "verbose", 270 "wallet", 271 "when", 272 "where", 273 "with", 274 "without", 275 } 276 277 def bytestring_sql(self, expression: exp.ByteString) -> str: 278 if not expression.args.get("is_bytes"): 279 return self.sql(exp.Literal.string(expression.this)) 280 281 return self.func("FROM_HEX", exp.Literal.string(expression.this.encode("latin-1").hex())) 282 283 def stpoint_sql(self, expression: exp.StPoint) -> str: 284 # ST_POINT only accepts 2 args in Redshift; use ST_MAKEPOINT for 3 or 4 args 285 if expression.args.get("z") or expression.args.get("m"): 286 return self.func( 287 "ST_MAKEPOINT", 288 expression.this, 289 expression.expression, 290 expression.args.get("z"), 291 expression.args.get("m"), 292 ) 293 return self.func("ST_POINT", expression.this, expression.expression) 294 295 def arraycontains_sql(self, expression: exp.ArrayContains) -> str: 296 return self.func( 297 "ARRAY_CONTAINS", 298 expression.this, 299 expression.expression, 300 expression.args.get("check_null"), 301 ) 302 303 def objecttransform_sql(self, expression: exp.ObjectTransform) -> str: 304 this = self.sql(expression, "this") 305 keep = self.expressions(expression, key="keep", flat=True) 306 set_ = self.expressions(expression, key="set_", flat=True) 307 keep_sql = " KEEP " + keep if keep else "" 308 set_sql = " SET " + set_ if set_ else "" 309 return f"OBJECT_TRANSFORM({this}{keep_sql}{set_sql})" 310 311 def approxquantile_sql(self, expression: exp.ApproxQuantile) -> str: 312 return "APPROXIMATE " + self.sql( 313 exp.WithinGroup( 314 this=exp.PercentileDisc(this=expression.args["quantile"]), 315 expression=exp.Order(expressions=[exp.Ordered(this=expression.this)]), 316 ) 317 ) 318 319 def unnest_sql(self, expression: exp.Unnest) -> str: 320 args = expression.expressions 321 num_args = len(args) 322 323 if num_args != 1: 324 self.unsupported(f"Unsupported number of arguments in UNNEST: {num_args}") 325 return "" 326 327 if isinstance(expression.find_ancestor(exp.From, exp.Join, exp.Select), exp.Select): 328 self.unsupported("Unsupported UNNEST when not used in FROM/JOIN clauses") 329 return "" 330 331 arg = self.sql(seq_get(args, 0)) 332 333 alias = self.expressions(expression.args.get("alias"), key="columns", flat=True) 334 return f"{arg} AS {alias}" if alias else arg 335 336 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 337 if expression.is_type(exp.DType.JSON): 338 # Redshift doesn't support a JSON type, so casting to it is treated as a noop 339 return self.sql(expression, "this") 340 341 return super().cast_sql(expression, safe_prefix=safe_prefix) 342 343 def datatype_sql(self, expression: exp.DataType) -> str: 344 """ 345 Redshift converts the `TEXT` data type to `VARCHAR(255)` by default when people more generally mean 346 VARCHAR of max length which is `VARCHAR(max)` in Redshift. Therefore if we get a `TEXT` data type 347 without precision we convert it to `VARCHAR(max)` and if it does have precision then we just convert 348 `TEXT` to `VARCHAR`. 349 """ 350 if expression.is_type("text"): 351 expression.set("this", exp.DType.VARCHAR) 352 precision = expression.args.get("expressions") 353 354 if not precision: 355 expression.append("expressions", exp.var("MAX")) 356 357 return super().datatype_sql(expression) 358 359 def alterset_sql(self, expression: exp.AlterSet) -> str: 360 exprs = self.expressions(expression, flat=True) 361 exprs = f" TABLE PROPERTIES ({exprs})" if exprs else "" 362 location = self.sql(expression, "location") 363 location = f" LOCATION {location}" if location else "" 364 file_format = self.expressions(expression, key="file_format", flat=True, sep=" ") 365 file_format = f" FILE FORMAT {file_format}" if file_format else "" 366 367 return f"SET{exprs}{location}{file_format}" 368 369 def array_sql(self, expression: exp.Array) -> str: 370 if expression.args.get("bracket_notation"): 371 return super().array_sql(expression) 372 373 return rename_func("ARRAY")(self, expression) 374 375 def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str: 376 return Generator.ignorenulls_sql(self, expression) 377 378 def respectnulls_sql(self, expression: exp.RespectNulls) -> str: 379 return Generator.respectnulls_sql(self, expression) 380 381 def explode_sql(self, expression: exp.Explode) -> str: 382 self.unsupported("Unsupported EXPLODE() function") 383 return "" 384 385 def _unix_to_time_sql(self, expression: exp.UnixToTime) -> str: 386 scale = expression.args.get("scale") 387 this = self.sql(expression.this) 388 389 if scale is not None and scale != exp.UnixToTime.SECONDS and scale.is_int: 390 this = f"({this} / POWER(10, {scale.to_py()}))" 391 392 return f"(TIMESTAMP 'epoch' + {this} * INTERVAL '1 SECOND')"
21class RedshiftGenerator(PostgresGenerator): 22 LOCKING_READS_SUPPORTED = False 23 QUERY_HINTS = False 24 CAST_TO_INT_ROUNDS = True 25 VALUES_AS_TABLE = False 26 TZ_TO_WITH_TIME_ZONE = True 27 NVL2_SUPPORTED = True 28 LAST_DAY_SUPPORTS_DATE_PART = False 29 CAN_IMPLEMENT_ARRAY_ANY = False 30 MULTI_ARG_DISTINCT = True 31 COPY_PARAMS_ARE_WRAPPED = False 32 HEX_FUNC = "TO_HEX" 33 PARSE_JSON_NAME: str | None = "JSON_PARSE" 34 ARRAY_CONCAT_IS_VAR_LEN = False 35 SUPPORTS_CONVERT_TIMEZONE = True 36 EXCEPT_INTERSECT_SUPPORT_ALL_CLAUSE = False 37 SUPPORTS_MEDIAN = True 38 ALTER_SET_TYPE = "TYPE" 39 SUPPORTS_DECODE_CASE = True 40 SUPPORTS_BETWEEN_FLAGS = False 41 LIMIT_FETCH = "LIMIT" 42 STAR_EXCEPT = "EXCLUDE" 43 STAR_EXCLUDE_REQUIRES_DERIVED_TABLE = False 44 45 # Redshift doesn't have `WITH` as part of their with_properties so we remove it 46 WITH_PROPERTIES_PREFIX = " " 47 48 TYPE_MAPPING = { 49 **PostgresGenerator.TYPE_MAPPING, 50 exp.DType.BINARY: "VARBYTE", 51 exp.DType.BLOB: "VARBYTE", 52 exp.DType.INT: "INTEGER", 53 exp.DType.TIMETZ: "TIME", 54 exp.DType.TIMESTAMPTZ: "TIMESTAMP", 55 exp.DType.VARBINARY: "VARBYTE", 56 exp.DType.ROWVERSION: "VARBYTE", 57 } 58 59 TRANSFORMS = { 60 **{ 61 k: v 62 for k, v in PostgresGenerator.TRANSFORMS.items() 63 if k 64 not in { 65 exp.Pivot, 66 exp.ParseJSON, 67 exp.AnyValue, 68 exp.LastDay, 69 exp.SHA2, 70 exp.Getbit, 71 exp.IntDiv, 72 exp.Round, 73 exp.TryCast, 74 } 75 }, 76 exp.ArrayConcat: array_concat_sql("ARRAY_CONCAT"), 77 exp.Concat: concat_to_dpipe_sql, 78 exp.ConcatWs: concat_ws_to_dpipe_sql, 79 exp.ApproxDistinct: lambda self, e: f"APPROXIMATE COUNT(DISTINCT {self.sql(e, 'this')})", 80 exp.CurrentTimestamp: lambda self, e: "SYSDATE" if e.args.get("sysdate") else "GETDATE()", 81 exp.CurrentUserId: lambda *_: "CURRENT_USER_ID", 82 exp.DateAdd: date_delta_sql("DATEADD"), 83 exp.DateDiff: date_delta_sql("DATEDIFF"), 84 exp.DistKeyProperty: lambda self, e: self.func("DISTKEY", e.this), 85 exp.DistStyleProperty: lambda self, e: self.naked_property(e), 86 exp.Explode: lambda self, e: self.explode_sql(e), 87 exp.FarmFingerprint: rename_func("FARMFINGERPRINT64"), 88 exp.FromBase: rename_func("STRTOL"), 89 exp.GeneratedAsIdentityColumnConstraint: generatedasidentitycolumnconstraint_sql, 90 exp.JSONExtract: json_extract_segments("JSON_EXTRACT_PATH_TEXT"), 91 exp.JSONExtractScalar: json_extract_segments("JSON_EXTRACT_PATH_TEXT"), 92 exp.GroupConcat: rename_func("LISTAGG"), 93 exp.Hex: lambda self, e: self.func("UPPER", self.func("TO_HEX", self.sql(e, "this"))), 94 exp.RegexpExtract: rename_func("REGEXP_SUBSTR"), 95 exp.Select: transforms.preprocess( 96 [ 97 transforms.eliminate_window_clause, 98 transforms.eliminate_distinct_on, 99 transforms.eliminate_semi_and_anti_joins, 100 transforms.unqualify_unnest, 101 transforms.unnest_generate_date_array_using_recursive_cte, 102 ] 103 ), 104 exp.SortKeyProperty: lambda self, e: ( 105 f"{'COMPOUND ' if e.args['compound'] else ''}SORTKEY({self.format_args(*e.this)})" 106 ), 107 exp.StartsWith: lambda self, e: f"{self.sql(e.this)} LIKE {self.sql(e.expression)} || '%'", 108 exp.StringToArray: rename_func("SPLIT_TO_ARRAY"), 109 exp.TableSample: no_tablesample_sql, 110 exp.TsOrDsAdd: date_delta_sql("DATEADD"), 111 exp.TsOrDsDiff: date_delta_sql("DATEDIFF"), 112 exp.UnixToTime: lambda self, e: self._unix_to_time_sql(e), 113 exp.SHA2Digest: lambda self, e: self.func( 114 "SHA2", e.this, e.args.get("length") or exp.Literal.number(256) 115 ), 116 } 117 118 RESERVED_KEYWORDS = { 119 "aes128", 120 "aes256", 121 "all", 122 "allowoverwrite", 123 "analyse", 124 "analyze", 125 "and", 126 "any", 127 "array", 128 "as", 129 "asc", 130 "authorization", 131 "az64", 132 "backup", 133 "between", 134 "binary", 135 "blanksasnull", 136 "both", 137 "bytedict", 138 "bzip2", 139 "case", 140 "cast", 141 "check", 142 "collate", 143 "column", 144 "constraint", 145 "create", 146 "credentials", 147 "cross", 148 "current_date", 149 "current_time", 150 "current_timestamp", 151 "current_user", 152 "current_user_id", 153 "default", 154 "deferrable", 155 "deflate", 156 "defrag", 157 "delta", 158 "delta32k", 159 "desc", 160 "disable", 161 "distinct", 162 "do", 163 "else", 164 "emptyasnull", 165 "enable", 166 "encode", 167 "encrypt ", 168 "encryption", 169 "end", 170 "except", 171 "explicit", 172 "false", 173 "for", 174 "foreign", 175 "freeze", 176 "from", 177 "full", 178 "globaldict256", 179 "globaldict64k", 180 "grant", 181 "group", 182 "gzip", 183 "having", 184 "identity", 185 "ignore", 186 "ilike", 187 "in", 188 "initially", 189 "inner", 190 "intersect", 191 "interval", 192 "into", 193 "is", 194 "isnull", 195 "join", 196 "leading", 197 "left", 198 "like", 199 "limit", 200 "localtime", 201 "localtimestamp", 202 "lun", 203 "luns", 204 "lzo", 205 "lzop", 206 "minus", 207 "mostly16", 208 "mostly32", 209 "mostly8", 210 "natural", 211 "new", 212 "not", 213 "notnull", 214 "null", 215 "nulls", 216 "off", 217 "offline", 218 "offset", 219 "oid", 220 "old", 221 "on", 222 "only", 223 "open", 224 "or", 225 "order", 226 "outer", 227 "overlaps", 228 "parallel", 229 "partition", 230 "percent", 231 "permissions", 232 "pivot", 233 "placing", 234 "primary", 235 "raw", 236 "readratio", 237 "recover", 238 "references", 239 "rejectlog", 240 "resort", 241 "respect", 242 "restore", 243 "right", 244 "select", 245 "session_user", 246 "similar", 247 "snapshot", 248 "some", 249 "sysdate", 250 "system", 251 "table", 252 "tag", 253 "tdes", 254 "text255", 255 "text32k", 256 "then", 257 "timestamp", 258 "to", 259 "top", 260 "trailing", 261 "true", 262 "truncatecolumns", 263 "type", 264 "union", 265 "unique", 266 "unnest", 267 "unpivot", 268 "user", 269 "using", 270 "verbose", 271 "wallet", 272 "when", 273 "where", 274 "with", 275 "without", 276 } 277 278 def bytestring_sql(self, expression: exp.ByteString) -> str: 279 if not expression.args.get("is_bytes"): 280 return self.sql(exp.Literal.string(expression.this)) 281 282 return self.func("FROM_HEX", exp.Literal.string(expression.this.encode("latin-1").hex())) 283 284 def stpoint_sql(self, expression: exp.StPoint) -> str: 285 # ST_POINT only accepts 2 args in Redshift; use ST_MAKEPOINT for 3 or 4 args 286 if expression.args.get("z") or expression.args.get("m"): 287 return self.func( 288 "ST_MAKEPOINT", 289 expression.this, 290 expression.expression, 291 expression.args.get("z"), 292 expression.args.get("m"), 293 ) 294 return self.func("ST_POINT", expression.this, expression.expression) 295 296 def arraycontains_sql(self, expression: exp.ArrayContains) -> str: 297 return self.func( 298 "ARRAY_CONTAINS", 299 expression.this, 300 expression.expression, 301 expression.args.get("check_null"), 302 ) 303 304 def objecttransform_sql(self, expression: exp.ObjectTransform) -> str: 305 this = self.sql(expression, "this") 306 keep = self.expressions(expression, key="keep", flat=True) 307 set_ = self.expressions(expression, key="set_", flat=True) 308 keep_sql = " KEEP " + keep if keep else "" 309 set_sql = " SET " + set_ if set_ else "" 310 return f"OBJECT_TRANSFORM({this}{keep_sql}{set_sql})" 311 312 def approxquantile_sql(self, expression: exp.ApproxQuantile) -> str: 313 return "APPROXIMATE " + self.sql( 314 exp.WithinGroup( 315 this=exp.PercentileDisc(this=expression.args["quantile"]), 316 expression=exp.Order(expressions=[exp.Ordered(this=expression.this)]), 317 ) 318 ) 319 320 def unnest_sql(self, expression: exp.Unnest) -> str: 321 args = expression.expressions 322 num_args = len(args) 323 324 if num_args != 1: 325 self.unsupported(f"Unsupported number of arguments in UNNEST: {num_args}") 326 return "" 327 328 if isinstance(expression.find_ancestor(exp.From, exp.Join, exp.Select), exp.Select): 329 self.unsupported("Unsupported UNNEST when not used in FROM/JOIN clauses") 330 return "" 331 332 arg = self.sql(seq_get(args, 0)) 333 334 alias = self.expressions(expression.args.get("alias"), key="columns", flat=True) 335 return f"{arg} AS {alias}" if alias else arg 336 337 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 338 if expression.is_type(exp.DType.JSON): 339 # Redshift doesn't support a JSON type, so casting to it is treated as a noop 340 return self.sql(expression, "this") 341 342 return super().cast_sql(expression, safe_prefix=safe_prefix) 343 344 def datatype_sql(self, expression: exp.DataType) -> str: 345 """ 346 Redshift converts the `TEXT` data type to `VARCHAR(255)` by default when people more generally mean 347 VARCHAR of max length which is `VARCHAR(max)` in Redshift. Therefore if we get a `TEXT` data type 348 without precision we convert it to `VARCHAR(max)` and if it does have precision then we just convert 349 `TEXT` to `VARCHAR`. 350 """ 351 if expression.is_type("text"): 352 expression.set("this", exp.DType.VARCHAR) 353 precision = expression.args.get("expressions") 354 355 if not precision: 356 expression.append("expressions", exp.var("MAX")) 357 358 return super().datatype_sql(expression) 359 360 def alterset_sql(self, expression: exp.AlterSet) -> str: 361 exprs = self.expressions(expression, flat=True) 362 exprs = f" TABLE PROPERTIES ({exprs})" if exprs else "" 363 location = self.sql(expression, "location") 364 location = f" LOCATION {location}" if location else "" 365 file_format = self.expressions(expression, key="file_format", flat=True, sep=" ") 366 file_format = f" FILE FORMAT {file_format}" if file_format else "" 367 368 return f"SET{exprs}{location}{file_format}" 369 370 def array_sql(self, expression: exp.Array) -> str: 371 if expression.args.get("bracket_notation"): 372 return super().array_sql(expression) 373 374 return rename_func("ARRAY")(self, expression) 375 376 def ignorenulls_sql(self, expression: exp.IgnoreNulls) -> str: 377 return Generator.ignorenulls_sql(self, expression) 378 379 def respectnulls_sql(self, expression: exp.RespectNulls) -> str: 380 return Generator.respectnulls_sql(self, expression) 381 382 def explode_sql(self, expression: exp.Explode) -> str: 383 self.unsupported("Unsupported EXPLODE() function") 384 return "" 385 386 def _unix_to_time_sql(self, expression: exp.UnixToTime) -> str: 387 scale = expression.args.get("scale") 388 this = self.sql(expression.this) 389 390 if scale is not None and scale != exp.UnixToTime.SECONDS and scale.is_int: 391 this = f"({this} / POWER(10, {scale.to_py()}))" 392 393 return f"(TIMESTAMP 'epoch' + {this} * INTERVAL '1 SECOND')"
Generator converts a given syntax tree to the corresponding SQL string.
Arguments:
- pretty: Whether to format the produced SQL string. Default: False.
- identify: Determines when an identifier should be quoted. Possible values are: False (default): Never quote, except in cases where it's mandatory by the dialect. True: Always quote except for specials cases. 'safe': Only quote identifiers that are case insensitive.
- normalize: Whether to normalize identifiers to lowercase. Default: False.
- pad: The pad size in a formatted string. For example, this affects the indentation of a projection in a query, relative to its nesting level. Default: 2.
- indent: The indentation size in a formatted string. For example, this affects the
indentation of subqueries and filters under a
WHEREclause. Default: 2. - normalize_functions: How to normalize function names. Possible values are: "upper" or True (default): Convert names to uppercase. "lower": Convert names to lowercase. False: Disables function name normalization.
- unsupported_level: Determines the generator's behavior when it encounters unsupported expressions. Default ErrorLevel.WARN.
- max_unsupported: Maximum number of unsupported messages to include in a raised UnsupportedError. This is only relevant if unsupported_level is ErrorLevel.RAISE. Default: 3
- leading_comma: Whether the comma is leading or trailing in select expressions. This is only relevant when generating in pretty mode. Default: False
- max_text_width: The max number of characters in a segment before creating new lines in pretty mode. The default is on the smaller end because the length only represents a segment and not the true line length. Default: 80
- comments: Whether to preserve comments in the output SQL code. Default: True
TYPE_MAPPING =
{<DType.DATETIME2: 'DATETIME2'>: 'TIMESTAMP', <DType.NCHAR: 'NCHAR'>: 'CHAR', <DType.NVARCHAR: 'NVARCHAR'>: 'VARCHAR', <DType.MEDIUMTEXT: 'MEDIUMTEXT'>: 'TEXT', <DType.LONGTEXT: 'LONGTEXT'>: 'TEXT', <DType.TINYTEXT: 'TINYTEXT'>: 'TEXT', <DType.BLOB: 'BLOB'>: 'VARBYTE', <DType.MEDIUMBLOB: 'MEDIUMBLOB'>: 'BLOB', <DType.LONGBLOB: 'LONGBLOB'>: 'BLOB', <DType.TINYBLOB: 'TINYBLOB'>: 'BLOB', <DType.INET: 'INET'>: 'INET', <DType.ROWVERSION: 'ROWVERSION'>: 'VARBYTE', <DType.SMALLDATETIME: 'SMALLDATETIME'>: 'TIMESTAMP', <DType.TINYINT: 'TINYINT'>: 'SMALLINT', <DType.FLOAT: 'FLOAT'>: 'REAL', <DType.DOUBLE: 'DOUBLE'>: 'DOUBLE PRECISION', <DType.BINARY: 'BINARY'>: 'VARBYTE', <DType.VARBINARY: 'VARBINARY'>: 'VARBYTE', <DType.DATETIME: 'DATETIME'>: 'TIMESTAMP', <DType.TIMESTAMPNTZ: 'TIMESTAMPNTZ'>: 'TIMESTAMP', <DType.INT: 'INT'>: 'INTEGER', <DType.TIMETZ: 'TIMETZ'>: 'TIME', <DType.TIMESTAMPTZ: 'TIMESTAMPTZ'>: 'TIMESTAMP'}
TRANSFORMS =
{<class 'sqlglot.expressions.query.JSONPathKey'>: <function json_path_key_only_name>, <class 'sqlglot.expressions.query.JSONPathRoot'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.query.JSONPathSubscript'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.core.Adjacent'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.AllowedValuesProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.AnalyzeColumns'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.AnalyzeWith'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayContainedBy'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayContainsAll'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayOverlaps'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.AssumeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.AutoRefreshProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.BackupProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.BinaryColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CaseSpecificColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CalledOnNullInputProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.math.Ceil'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CharacterSetColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CharacterSetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.CollateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.ConnectByRoot'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.string.ConvertToCharset'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CopyGrantsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CredentialsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.CurrentCatalog'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.SessionUser'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.DateFormatColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.DefaultColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ApiProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ApplicationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.CatalogProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ComputeProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.DatabaseProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.DynamicProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.EmptyProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.EncodeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.EndStatement'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.EnviromentProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.HandlerProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ParameterStyleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.EphemeralColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ExcludeColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ExecuteAsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Except'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ExternalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.math.Floor'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Get'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.GlobalProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.HeapProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.HybridProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.IcebergProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.InheritsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.InlineLengthColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.InputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Intersect'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.datatypes.IntervalSpan'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.Int64'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBContainsAnyTopKeys'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBContainsAllTopKeys'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBContainsTopKey'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBDeleteAtPath'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONBPathExists'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONObject'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.json.JSONObjectAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.properties.LanguageProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.LocationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.LogProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.MaskingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.MaterializedProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.functions.NetFunc'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.NetworkProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.NonClusteredColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.NoPrimaryIndexProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.NotForReplicationColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.OnCommitProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.OnProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.OnUpdateColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.Operator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.OutputModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.ExtendsLeft'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.ExtendsRight'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.PathColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.PartitionedByBucket'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.PartitionByTruncate'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.PivotAny'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.PositionalColumn'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ProjectionPolicyColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.InvisibleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.ZeroFillColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Put'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.RemoteWithConnectionModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ReturnsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.RowAccessProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.core.SafeFunc'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SampleProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SecureProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SecurityIntegrationProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SetConfigProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SetProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SettingsProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SharingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SqlReadWriteProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.SqlSecurityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.StabilityProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Stream'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.StreamingTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.StrictProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ddl.SwapTable'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.TableColumn'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.Tags'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.TemporaryProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.TitleColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ToMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ToTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.TransformModelProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.TransientProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.VirtualProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.ddl.TriggerExecute'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Union'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.UnloggedProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.UsingTemplateProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.UsingData'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.UppercaseColumnConstraint'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.temporal.UtcDate'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.temporal.UtcTime'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.temporal.UtcTimestamp'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.query.Variadic'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.VarMap'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ViewAttributeProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.VolatileProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.WithJournalTableProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.WithProcedureOptions'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.WithSchemaBindingProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.constraints.WithOperator'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.properties.ForceProperty'>: <function Generator.<lambda>>, <class 'sqlglot.expressions.array.ArrayConcat'>: <function array_concat_sql.<locals>._array_concat_sql>, <class 'sqlglot.expressions.array.ArrayFilter'>: <function filter_array_using_unnest>, <class 'sqlglot.expressions.array.ArrayAppend'>: <function array_append_sql.<locals>._array_append_sql>, <class 'sqlglot.expressions.array.ArrayPrepend'>: <function array_append_sql.<locals>._array_append_sql>, <class 'sqlglot.expressions.math.BitwiseAndAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.math.BitwiseOrAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.BitwiseXor'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.math.BitwiseXorAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.query.ColumnDef'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.temporal.CurrentDate'>: <function no_paren_current_date_sql>, <class 'sqlglot.expressions.temporal.CurrentTimestamp'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.functions.CurrentUser'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.functions.CurrentVersion'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.DateAdd'>: <function date_delta_sql.<locals>._delta_sql>, <class 'sqlglot.expressions.temporal.DateDiff'>: <function date_delta_sql.<locals>._delta_sql>, <class 'sqlglot.expressions.temporal.DateStrToDate'>: <function datestrtodate_sql>, <class 'sqlglot.expressions.temporal.DateSub'>: <function _date_add_sql.<locals>.func>, <class 'sqlglot.expressions.temporal.Day'>: <function _day_month_year_sql>, <class 'sqlglot.expressions.array.Explode'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.array.ExplodingGenerateSeries'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.array.GenerateSeries'>: <function generate_series_sql.<locals>._generate_series_sql>, <class 'sqlglot.expressions.aggregate.GroupConcat'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.json.JSONArrayAgg'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.json.JSONExtract'>: <function json_extract_segments.<locals>._json_extract_segments>, <class 'sqlglot.expressions.json.JSONExtractScalar'>: <function json_extract_segments.<locals>._json_extract_segments>, <class 'sqlglot.expressions.json.JSONBExtract'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.json.JSONBExtractScalar'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.aggregate.LogicalOr'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.LogicalAnd'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.Max'>: <function max_or_greatest>, <class 'sqlglot.expressions.array.MapFromEntries'>: <function no_map_from_entries_sql>, <class 'sqlglot.expressions.aggregate.Min'>: <function min_or_least>, <class 'sqlglot.expressions.dml.Merge'>: <function merge_without_target_sql>, <class 'sqlglot.expressions.temporal.Month'>: <function _day_month_year_sql>, <class 'sqlglot.expressions.properties.PartitionedByProperty'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.aggregate.PercentileCont'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.aggregate.PercentileDisc'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.functions.Rand'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.RegexpLike'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.string.RegexpILike'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.string.RegexpReplace'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.query.Select'>: <function preprocess.<locals>._to_sql>, <class 'sqlglot.expressions.string.SHA2Digest'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.string.StrPosition'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.StrToDate'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.StrToTime'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.array.StructExtract'>: <function struct_extract_sql>, <class 'sqlglot.expressions.string.Substring'>: <function _substring_sql>, <class 'sqlglot.expressions.temporal.TimeFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.TimestampFromParts'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.temporal.TimestampTrunc'>: <function timestamptrunc_sql.<locals>._timestamptrunc_sql>, <class 'sqlglot.expressions.temporal.TimeStrToTime'>: <function timestrtotime_sql>, <class 'sqlglot.expressions.temporal.TimeToStr'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.string.ToChar'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.string.Trim'>: <function trim_sql>, <class 'sqlglot.expressions.temporal.TsOrDsAdd'>: <function date_delta_sql.<locals>._delta_sql>, <class 'sqlglot.expressions.temporal.TsOrDsDiff'>: <function date_delta_sql.<locals>._delta_sql>, <class 'sqlglot.expressions.temporal.UnixToTime'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.functions.Uuid'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.temporal.TimeToUnix'>: <function PostgresGenerator.<lambda>>, <class 'sqlglot.expressions.aggregate.VariancePop'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.Variance'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.core.Xor'>: <function bool_xor_sql>, <class 'sqlglot.expressions.temporal.Year'>: <function _day_month_year_sql>, <class 'sqlglot.expressions.string.Unicode'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.string.Levenshtein'>: <function _levenshtein_sql>, <class 'sqlglot.expressions.json.JSONBObjectAgg'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.aggregate.CountIf'>: <function count_if_to_sum>, <class 'sqlglot.expressions.string.Concat'>: <function concat_to_dpipe_sql>, <class 'sqlglot.expressions.string.ConcatWs'>: <function concat_ws_to_dpipe_sql>, <class 'sqlglot.expressions.core.ApproxDistinct'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.functions.CurrentUserId'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.properties.DistKeyProperty'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.properties.DistStyleProperty'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.string.FarmFingerprint'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.string.FromBase'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.constraints.GeneratedAsIdentityColumnConstraint'>: <function generatedasidentitycolumnconstraint_sql>, <class 'sqlglot.expressions.string.Hex'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.string.RegexpExtract'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.properties.SortKeyProperty'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.string.StartsWith'>: <function RedshiftGenerator.<lambda>>, <class 'sqlglot.expressions.array.StringToArray'>: <function rename_func.<locals>.<lambda>>, <class 'sqlglot.expressions.query.TableSample'>: <function no_tablesample_sql>}
RESERVED_KEYWORDS =
{'outer', 'check', 'ignore', 'cast', 'emptyasnull', 'where', 'distinct', 'group', 'null', 'using', 'end', 'and', 'permissions', 'lzo', 'encryption', 'on', 'when', 'enable', 'foreign', 'initially', 'without', 'full', 'new', 'pivot', 'luns', 'tdes', 'union', 'trailing', 'as', 'except', 'defrag', 'between', 'to', 'bytedict', 'cross', 'session_user', 'natural', 'encode', 'only', 'aes128', 'array', 'overlaps', 'globaldict64k', 'constraint', 'not', 'interval', 'localtime', 'readratio', 'restore', 'deflate', 'lun', 'user', 'is', 'mostly16', 'open', 'bzip2', 'like', 'current_date', 'text255', 'isnull', 'partition', 'respect', 'table', 'column', 'text32k', 'then', 'current_user_id', 'top', 'delta32k', 'off', 'raw', 'parallel', 'in', 'with', 'credentials', 'sysdate', 'into', 'offline', 'some', 'az64', 'true', 'rejectlog', 'blanksasnull', 'backup', 'analyze', 'explicit', 'false', 'minus', 'binary', 'delta', 'freeze', 'inner', 'leading', 'authorization', 'primary', 'truncatecolumns', 'allowoverwrite', 'encrypt ', 'left', 'unpivot', 'verbose', 'analyse', 'current_time', 'disable', 'else', 'mostly32', 'type', 'ilike', 'case', 'collate', 'unique', 'wallet', 'desc', 'unnest', 'for', 'identity', 'intersect', 'all', 'similar', 'limit', 'both', 'from', 'placing', 'old', 'select', 'default', 'or', 'having', 'percent', 'create', 'aes256', 'gzip', 'current_timestamp', 'current_user', 'lzop', 'offset', 'order', 'right', 'localtimestamp', 'grant', 'mostly8', 'deferrable', 'globaldict256', 'timestamp', 'any', 'nulls', 'tag', 'asc', 'do', 'notnull', 'recover', 'references', 'resort', 'oid', 'snapshot', 'join', 'system'}
284 def stpoint_sql(self, expression: exp.StPoint) -> str: 285 # ST_POINT only accepts 2 args in Redshift; use ST_MAKEPOINT for 3 or 4 args 286 if expression.args.get("z") or expression.args.get("m"): 287 return self.func( 288 "ST_MAKEPOINT", 289 expression.this, 290 expression.expression, 291 expression.args.get("z"), 292 expression.args.get("m"), 293 ) 294 return self.func("ST_POINT", expression.this, expression.expression)
304 def objecttransform_sql(self, expression: exp.ObjectTransform) -> str: 305 this = self.sql(expression, "this") 306 keep = self.expressions(expression, key="keep", flat=True) 307 set_ = self.expressions(expression, key="set_", flat=True) 308 keep_sql = " KEEP " + keep if keep else "" 309 set_sql = " SET " + set_ if set_ else "" 310 return f"OBJECT_TRANSFORM({this}{keep_sql}{set_sql})"
320 def unnest_sql(self, expression: exp.Unnest) -> str: 321 args = expression.expressions 322 num_args = len(args) 323 324 if num_args != 1: 325 self.unsupported(f"Unsupported number of arguments in UNNEST: {num_args}") 326 return "" 327 328 if isinstance(expression.find_ancestor(exp.From, exp.Join, exp.Select), exp.Select): 329 self.unsupported("Unsupported UNNEST when not used in FROM/JOIN clauses") 330 return "" 331 332 arg = self.sql(seq_get(args, 0)) 333 334 alias = self.expressions(expression.args.get("alias"), key="columns", flat=True) 335 return f"{arg} AS {alias}" if alias else arg
def
cast_sql( self, expression: sqlglot.expressions.functions.Cast, safe_prefix: str | None = None) -> str:
337 def cast_sql(self, expression: exp.Cast, safe_prefix: str | None = None) -> str: 338 if expression.is_type(exp.DType.JSON): 339 # Redshift doesn't support a JSON type, so casting to it is treated as a noop 340 return self.sql(expression, "this") 341 342 return super().cast_sql(expression, safe_prefix=safe_prefix)
344 def datatype_sql(self, expression: exp.DataType) -> str: 345 """ 346 Redshift converts the `TEXT` data type to `VARCHAR(255)` by default when people more generally mean 347 VARCHAR of max length which is `VARCHAR(max)` in Redshift. Therefore if we get a `TEXT` data type 348 without precision we convert it to `VARCHAR(max)` and if it does have precision then we just convert 349 `TEXT` to `VARCHAR`. 350 """ 351 if expression.is_type("text"): 352 expression.set("this", exp.DType.VARCHAR) 353 precision = expression.args.get("expressions") 354 355 if not precision: 356 expression.append("expressions", exp.var("MAX")) 357 358 return super().datatype_sql(expression)
Redshift converts the TEXT data type to VARCHAR(255) by default when people more generally mean
VARCHAR of max length which is VARCHAR(max) in Redshift. Therefore if we get a TEXT data type
without precision we convert it to VARCHAR(max) and if it does have precision then we just convert
TEXT to VARCHAR.
360 def alterset_sql(self, expression: exp.AlterSet) -> str: 361 exprs = self.expressions(expression, flat=True) 362 exprs = f" TABLE PROPERTIES ({exprs})" if exprs else "" 363 location = self.sql(expression, "location") 364 location = f" LOCATION {location}" if location else "" 365 file_format = self.expressions(expression, key="file_format", flat=True, sep=" ") 366 file_format = f" FILE FORMAT {file_format}" if file_format else "" 367 368 return f"SET{exprs}{location}{file_format}"
Inherited Members
- sqlglot.generator.Generator
- Generator
- NULL_ORDERING_SUPPORTED
- WINDOW_FUNCS_WITH_NULL_ORDERING
- IGNORE_NULLS_IN_FUNC
- IGNORE_NULLS_BEFORE_ORDER
- WRAP_DERIVED_VALUES
- CREATE_FUNCTION_RETURN_AS
- MATCHED_BY_SOURCE
- SUPPORTS_MERGE_WHERE
- INTERVAL_ALLOWS_PLURAL_FORM
- AUTO_REFRESH_BARE_INTERVALS
- LIMIT_ONLY_LITERALS
- GROUPINGS_SEP
- SUPPORTS_GROUPING_SETS_AS_SUFFIX
- INDEX_ON
- DIRECTED_JOINS
- QUERY_HINT_SEP
- IS_BOOL_ALLOWED
- SAFE_INT_DIVISION
- DUPLICATE_KEY_UPDATE_WITH_SET
- LIMIT_IS_TOP
- RETURNING_END
- EXTRACT_ALLOWS_QUOTES
- ALTER_TABLE_INCLUDE_COLUMN_KEYWORD
- UNNEST_WITH_ORDINALITY
- SEMI_ANTI_JOIN_WITH_SIDE
- COMPUTED_COLUMN_WITH_TYPE
- SUPPORTS_TABLE_COPY
- TABLESAMPLE_REQUIRES_PARENS
- TABLESAMPLE_KEYWORDS
- TABLESAMPLE_WITH_METHOD
- HISTORICAL_DATA_POST_ALIAS
- COLLATE_IS_FUNC
- DATA_TYPE_SPECIFIERS_ALLOWED
- ENSURE_BOOLS
- CTE_RECURSIVE_KEYWORD_REQUIRED
- SUPPORTS_SINGLE_ARG_CONCAT
- SUPPORTS_TABLE_ALIAS_COLUMNS
- SUPPORTS_NAMED_CTE_COLUMNS
- UNPIVOT_ALIASES_ARE_IDENTIFIERS
- PIVOT_ALIAS_WITH_AS
- JSON_KEY_VALUE_PAIR_SEP
- INSERT_OVERWRITE
- SUPPORTS_CREATE_TABLE_LIKE
- SUPPORTS_MODIFY_COLUMN
- SUPPORTS_CHANGE_COLUMN
- SUPPORTS_ALTER_COLUMN_NULLABILITY
- SUPPORTS_ALTER_COLUMN_IF_EXISTS
- JSON_PATH_BRACKETED_KEY_SUPPORTED
- JSON_PATH_SINGLE_QUOTE_ESCAPE
- JSON_PATH_KEY_QUOTED_FORCES_BRACKETS
- SUPPORTS_TO_NUMBER
- SET_OP_MODIFIERS
- SET_OP_LIMITS
- SET_OP_PARENTHESIZED_OPERANDS
- COPY_PARAMS_EQ_REQUIRED
- SUPPORTS_UESCAPE
- UNICODE_SUBSTITUTE
- BYTE_STRING_FUNCTION
- QUOTE_JSON_PATH
- PAD_FILL_PATTERN_IS_REQUIRED
- SUPPORTS_EXPLODING_PROJECTIONS
- SUPPORTS_UNIX_SECONDS
- ALTER_SET_WRAPPED
- NORMALIZE_EXTRACT_DATE_PARTS
- ARRAY_SIZE_NAME
- SUPPORTS_LIKE_QUANTIFIERS
- MATCH_AGAINST_TABLE_PREFIX
- SET_ASSIGNMENT_REQUIRES_VARIABLE_KEYWORD
- DECLARE_DEFAULT_ASSIGNMENT
- UPDATE_STATEMENT_SUPPORTS_FROM
- SUPPORTS_DROP_ALTER_ICEBERG_PROPERTY
- UNSUPPORTED_TYPES
- TYPE_PARAM_SETTINGS
- TIME_PART_SINGULARS
- TOKEN_MAPPING
- STRUCT_DELIMITER
- EXPRESSION_PRECEDES_PROPERTIES_CREATABLES
- WITH_SEPARATED_COMMENTS
- EXCLUDE_COMMENTS
- UNWRAPPED_INTERVAL_VALUES
- PARAMETERIZABLE_TEXT_TYPES
- EXPRESSIONS_WITHOUT_NESTED_CTES
- RESPECT_IGNORE_NULLS_UNSUPPORTED_EXPRESSIONS
- MOD_OPERATOR
- MOD_PAREN_PARENT_TYPES
- ALTER_PARTITION_OPTIONS
- SAFE_JSON_PATH_KEY_RE
- SENTINEL_LINE_BREAK
- pretty
- identify
- normalize
- pad
- unsupported_level
- max_unsupported
- leading_comma
- max_text_width
- comments
- dialect
- normalize_functions
- unsupported_messages
- generate
- preprocess
- unsupported
- sep
- seg
- sanitize_comment
- maybe_comment
- wrap
- no_identify
- normalize_func
- indent
- sql
- uncache_sql
- cache_sql
- characterset_sql
- column_parts
- column_sql
- pseudocolumn_sql
- columnposition_sql
- columnconstraint_sql
- autoincrementcolumnconstraint_sql
- compresscolumnconstraint_sql
- generatedasidentitycolumnconstraint_sql
- generatedasrowcolumnconstraint_sql
- periodforsystemtimeconstraint_sql
- notnullcolumnconstraint_sql
- primarykeycolumnconstraint_sql
- uniquecolumnconstraint_sql
- inoutcolumnconstraint_sql
- createable_sql
- create_sql
- sequenceproperties_sql
- triggerproperties_sql
- triggerreferencing_sql
- triggerevent_sql
- clone_sql
- describe_sql
- heredoc_sql
- prepend_ctes
- with_sql
- cte_sql
- tablealias_sql
- bitstring_sql
- hexstring_sql
- unicodestring_sql
- rawstring_sql
- datatypeparam_sql
- datatype_param_bound_limiter
- directory_sql
- delete_sql
- drop_sql
- set_operation
- set_operations
- fetch_sql
- limitoptions_sql
- filter_sql
- hint_sql
- indexparameters_sql
- index_sql
- dynamicidentifier_sql
- identifier_sql
- hex_sql
- lowerhex_sql
- inputoutputformat_sql
- national_sql
- partition_sql
- properties_sql
- root_properties
- properties
- with_properties
- locate_properties
- property_name
- property_sql
- uuidproperty_sql
- likeproperty_sql
- fallbackproperty_sql
- journalproperty_sql
- freespaceproperty_sql
- checksumproperty_sql
- mergeblockratioproperty_sql
- moduleproperty_sql
- datablocksizeproperty_sql
- blockcompressionproperty_sql
- isolatedloadingproperty_sql
- partitionboundspec_sql
- partitionedofproperty_sql
- lockingproperty_sql
- lockingstatement_sql
- withdataproperty_sql
- withsystemversioningproperty_sql
- insert_sql
- introducer_sql
- kill_sql
- pseudotype_sql
- objectidentifier_sql
- onconflict_sql
- returning_sql
- rowformatdelimitedproperty_sql
- withtablehint_sql
- indextablehint_sql
- historicaldata_sql
- table_parts
- table_sql
- tablefromrows_sql
- tablesample_sql
- pivot_sql
- version_sql
- tuple_sql
- update_sql
- values_sql
- var_sql
- into_sql
- from_sql
- groupingsets_sql
- rollup_sql
- rollupindex_sql
- rollupproperty_sql
- cube_sql
- group_sql
- having_sql
- connect_sql
- prior_sql
- join_sql
- lambda_sql
- lateral_op
- limit_sql
- offset_sql
- setitem_sql
- set_sql
- queryband_sql
- pragma_sql
- lock_sql
- literal_sql
- escape_str
- loaddata_sql
- null_sql
- boolean_sql
- booland_sql
- boolor_sql
- order_sql
- withfill_sql
- cluster_sql
- clusterproperty_sql
- distribute_sql
- sort_sql
- ordered_sql
- matchrecognizemeasure_sql
- matchrecognize_sql
- query_modifiers
- options_modifier
- forclause_sql
- queryoption_sql
- offset_limit_modifiers
- after_limit_modifiers
- select_sql
- schema_sql
- schema_columns_sql
- star_sql
- parameter_sql
- sessionparameter_sql
- subquery_sql
- qualify_sql
- prewhere_sql
- where_sql
- window_sql
- partition_by_sql
- partitionbyexcluding_sql
- windowspec_sql
- withingroup_sql
- between_sql
- bracket_offset_expressions
- all_sql
- any_sql
- exists_sql
- case_sql
- constraint_sql
- nextvaluefor_sql
- extract_sql
- trim_sql
- convert_concat_args
- concat_sql
- concatws_sql
- check_sql
- foreignkey_sql
- primarykey_sql
- timeserieskey_sql
- if_sql
- jsonkeyvalue_sql
- jsonpath_sql
- json_path_part
- formatjson_sql
- formatphrase_sql
- jsonarray_sql
- jsonarrayagg_sql
- jsoncolumndef_sql
- jsonschema_sql
- jsontable_sql
- openjsoncolumndef_sql
- openjson_sql
- in_sql
- in_unnest_op
- return_sql
- reference_sql
- anonymous_sql
- paren_sql
- neg_sql
- not_sql
- alias_sql
- pivotalias_sql
- aliases_sql
- atindex_sql
- attimezone_sql
- fromtimezone_sql
- fromiso8601date_sql
- fromiso8601timestamp_sql
- fromiso8601timestampnanos_sql
- add_sql
- and_sql
- or_sql
- xor_sql
- connector_sql
- bitwiseand_sql
- bitwiseleftshift_sql
- bitwisenot_sql
- bitwiseor_sql
- bitwiserightshift_sql
- bitwisexor_sql
- strtotime_sql
- strtodate_sql
- parsedatetime_sql
- currentdate_sql
- collate_sql
- command_sql
- comment_sql
- mergetreettlaction_sql
- mergetreettl_sql
- transaction_sql
- commit_sql
- rollback_sql
- altercolumn_sql
- modifycolumn_sql
- alterindex_sql
- alterdiststyle_sql
- altersortkey_sql
- alterrename_sql
- renamecolumn_sql
- alter_sql
- altersession_sql
- add_column_sql
- droppartition_sql
- dropprimarykey_sql
- addconstraint_sql
- replacecolumns_sql
- addpartition_sql
- distinct_sql
- havingmax_sql
- intdiv_sql
- dpipe_sql
- div_sql
- safedivide_sql
- overlaps_sql
- distance_sql
- distancend_sql
- dot_sql
- eq_sql
- propertyeq_sql
- escape_sql
- glob_sql
- gt_sql
- gte_sql
- is_sql
- like_sql
- ilike_sql
- match_sql
- similarto_sql
- lt_sql
- lte_sql
- mod_sql
- mul_sql
- neq_sql
- nullsafeeq_sql
- nullsafeneq_sql
- sub_sql
- trycast_sql
- jsoncast_sql
- try_sql
- log_sql
- use_sql
- binary
- ceil_floor
- function_fallback_sql
- function_name
- func
- format_args
- too_wide
- format_time
- expressions
- op_expressions
- naked_property
- tag_sql
- token_sql
- userdefinedfunction_sql
- macrooverloads_sql
- macrooverload_sql
- joinhint_sql
- kwarg_sql
- when_sql
- whens_sql
- merge_sql
- tochar_sql
- tonumber_sql
- dictproperty_sql
- dictrange_sql
- dictsubproperty_sql
- aggregatekeyproperty_sql
- duplicatekeyproperty_sql
- uniquekeyproperty_sql
- distributedbyproperty_sql
- oncluster_sql
- clusteredbyproperty_sql
- anyvalue_sql
- querytransform_sql
- indexconstraintoption_sql
- checkcolumnconstraint_sql
- indexcolumnconstraint_sql
- nvl2_sql
- nthvalue_sql
- comprehension_sql
- columnprefix_sql
- opclass_sql
- predict_sql
- generateembedding_sql
- generatetext_sql
- generatetable_sql
- generatebool_sql
- generateint_sql
- generatedouble_sql
- mltranslate_sql
- mlforecast_sql
- aiforecast_sql
- featuresattime_sql
- vectorsearch_sql
- forin_sql
- refresh_sql
- toarray_sql
- tsordstotime_sql
- tsordstotimestamp_sql
- tsordstodatetime_sql
- tsordstodate_sql
- unixdate_sql
- lastday_sql
- dateadd_sql
- arrayinsert_sql
- arrayany_sql
- struct_sql
- partitionrange_sql
- truncatetable_sql
- convert_sql
- copyparameter_sql
- credentials_sql
- copy_sql
- semicolon_sql
- datadeletionproperty_sql
- maskingpolicycolumnconstraint_sql
- gapfill_sql
- scope_resolution
- scoperesolution_sql
- parsejson_sql
- rand_sql
- changes_sql
- pad_sql
- summarize_sql
- explodinggenerateseries_sql
- converttimezone_sql
- json_sql
- jsonvalue_sql
- skipjsoncolumn_sql
- conditionalinsert_sql
- multitableinserts_sql
- oncondition_sql
- jsonextractquote_sql
- jsonexists_sql
- arrayagg_sql
- slice_sql
- apply_sql
- grant_sql
- revoke_sql
- grantprivilege_sql
- grantprincipal_sql
- columns_sql
- overlay_sql
- todouble_sql
- string_sql
- median_sql
- overflowtruncatebehavior_sql
- unixseconds_sql
- arraysort_sql
- arraysize_sql
- attach_sql
- detach_sql
- attachoption_sql
- watermarkcolumnconstraint_sql
- encodeproperty_sql
- includeproperty_sql
- xmlelement_sql
- xmlkeyvalueoption_sql
- partitionbyrangeproperty_sql
- partitionbyrangepropertydynamic_sql
- unpivotcolumns_sql
- analyzesample_sql
- analyzestatistics_sql
- analyzehistogram_sql
- analyzedelete_sql
- analyzelistchainedrows_sql
- analyzevalidate_sql
- analyze_sql
- xmltable_sql
- xmlnamespace_sql
- export_sql
- declare_sql
- declareitem_sql
- recursivewithsearch_sql
- parameterizedagg_sql
- anonymousaggfunc_sql
- combinedaggfunc_sql
- combinedparameterizedagg_sql
- show_sql
- install_sql
- liststage_sql
- get_put_sql
- translatecharacters_sql
- decodecase_sql
- semanticview_sql
- getextract_sql
- datefromunixdate_sql
- space_sql
- buildproperty_sql
- refreshtriggerproperty_sql
- modelattribute_sql
- directorystage_sql
- uuid_sql
- initcap_sql
- localtime_sql
- localtimestamp_sql
- weekstart_name
- weekstart_sql
- chr_sql
- weightstring_sql
- block_sql
- functionspecification_sql
- storedprocedure_sql
- ifblock_sql
- casestatement_sql
- whileblock_sql
- loopblock_sql
- repeatblock_sql
- leave_sql
- iterate_sql
- execute_sql
- executesql_sql
- altermodifysqlsecurity_sql
- usingproperty_sql
- renameindex_sql
- sqlglot.generators.postgres.PostgresGenerator
- SELECT_KINDS
- TRY_SUPPORTED
- AFTER_HAVING_MODIFIER_TRANSFORMS
- SINGLE_STRING_INTERVAL
- RENAME_TABLE_WITH_DB
- JOIN_HINTS
- TABLE_HINTS
- PARAMETER_TOKEN
- NAMED_PLACEHOLDER_TOKEN
- TABLESAMPLE_SIZE_IS_ROWS
- TABLESAMPLE_SEED_KEYWORD
- SUPPORTS_SELECT_INTO
- JSON_TYPE_REQUIRED_FOR_EXTRACTION
- SUPPORTS_UNLOGGED_TABLES
- LIKE_PROPERTY_INSIDE_SCHEMA
- SUPPORTS_WINDOW_EXCLUDE
- COPY_HAS_INTO_KEYWORD
- ARRAY_SIZE_DIM_REQUIRED
- INOUT_SEPARATOR
- SUPPORTED_JSON_PATH_PARTS
- lateral_sql
- PROPERTIES_LOCATION
- schemacommentproperty_sql
- commentcolumnconstraint_sql
- columndef_sql
- bracket_sql
- matchagainst_sql
- computedcolumnconstraint_sql
- isascii_sql
- currentschema_sql
- interval_sql
- placeholder_sql