diff options
Diffstat (limited to '')
-rw-r--r-- | sqlglot/generator.py | 80 |
1 files changed, 54 insertions, 26 deletions
diff --git a/sqlglot/generator.py b/sqlglot/generator.py index d264e59..9099307 100644 --- a/sqlglot/generator.py +++ b/sqlglot/generator.py @@ -46,18 +46,12 @@ class Generator: """ TRANSFORMS = { - exp.AnonymousProperty: lambda self, e: self.property_sql(e), - exp.AutoIncrementProperty: lambda self, e: f"AUTO_INCREMENT={self.sql(e, 'value')}", exp.CharacterSetProperty: lambda self, e: f"{'DEFAULT ' if e.args['default'] else ''}CHARACTER SET={self.sql(e, 'value')}", - exp.CollateProperty: lambda self, e: f"COLLATE={self.sql(e, 'value')}", exp.DateAdd: lambda self, e: f"DATE_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e, 'unit')})", exp.DateDiff: lambda self, e: f"DATE_DIFF({self.sql(e, 'this')}, {self.sql(e, 'expression')})", - exp.EngineProperty: lambda self, e: f"ENGINE={self.sql(e, 'value')}", - exp.FileFormatProperty: lambda self, e: f"FORMAT={self.sql(e, 'value')}", - exp.LocationProperty: lambda self, e: f"LOCATION {self.sql(e, 'value')}", - exp.PartitionedByProperty: lambda self, e: f"PARTITIONED_BY={self.sql(e.args['value'])}", - exp.SchemaCommentProperty: lambda self, e: f"COMMENT={self.sql(e, 'value')}", - exp.TableFormatProperty: lambda self, e: f"TABLE_FORMAT={self.sql(e, 'value')}", + exp.LanguageProperty: lambda self, e: self.naked_property(e), + exp.LocationProperty: lambda self, e: self.naked_property(e), + exp.ReturnsProperty: lambda self, e: self.naked_property(e), exp.TsOrDsAdd: lambda self, e: f"TS_OR_DS_ADD({self.sql(e, 'this')}, {self.sql(e, 'expression')}, {self.sql(e, 'unit')})", } @@ -72,19 +66,17 @@ class Generator: STRUCT_DELIMITER = ("<", ">") - ROOT_PROPERTIES = [ - exp.AutoIncrementProperty, - exp.CharacterSetProperty, - exp.CollateProperty, - exp.EngineProperty, - exp.SchemaCommentProperty, - ] - WITH_PROPERTIES = [ + ROOT_PROPERTIES = { + exp.ReturnsProperty, + exp.LanguageProperty, + } + + WITH_PROPERTIES = { exp.AnonymousProperty, exp.FileFormatProperty, exp.PartitionedByProperty, exp.TableFormatProperty, - ] + } __slots__ = ( "time_mapping", @@ -188,6 +180,7 @@ class Generator: return sql def unsupported(self, message): + if self.unsupported_level == ErrorLevel.IMMEDIATE: raise UnsupportedError(message) self.unsupported_messages.append(message) @@ -261,6 +254,9 @@ class Generator: if isinstance(expression, exp.Func): return self.function_fallback_sql(expression) + if isinstance(expression, exp.Property): + return self.property_sql(expression) + raise ValueError(f"Unsupported expression type {expression.__class__.__name__}") def annotation_sql(self, expression): @@ -352,9 +348,12 @@ class Generator: replace = " OR REPLACE" if expression.args.get("replace") else "" exists_sql = " IF NOT EXISTS" if expression.args.get("exists") else "" unique = " UNIQUE" if expression.args.get("unique") else "" + materialized = " MATERIALIZED" if expression.args.get("materialized") else "" properties = self.sql(expression, "properties") - expression_sql = f"CREATE{replace}{temporary}{unique} {kind}{exists_sql} {this}{properties} {expression_sql}" + expression_sql = ( + f"CREATE{replace}{temporary}{unique}{materialized} {kind}{exists_sql} {this}{properties} {expression_sql}" + ) return self.prepend_ctes(expression, expression_sql) def prepend_ctes(self, expression, sql): @@ -461,10 +460,10 @@ class Generator: for p in expression.expressions: p_class = p.__class__ - if p_class in self.ROOT_PROPERTIES: - root_properties.append(p) - elif p_class in self.WITH_PROPERTIES: + if p_class in self.WITH_PROPERTIES: with_properties.append(p) + elif p_class in self.ROOT_PROPERTIES: + root_properties.append(p) return self.root_properties(exp.Properties(expressions=root_properties)) + self.with_properties( exp.Properties(expressions=with_properties) @@ -496,9 +495,12 @@ class Generator: ) def property_sql(self, expression): - key = expression.name + if isinstance(expression.this, exp.Literal): + key = expression.this.this + else: + key = expression.name value = self.sql(expression, "value") - return f"{key} = {value}" + return f"{key}={value}" def insert_sql(self, expression): kind = "OVERWRITE TABLE" if expression.args.get("overwrite") else "INTO" @@ -535,7 +537,8 @@ class Generator: laterals = self.expressions(expression, key="laterals", sep="") joins = self.expressions(expression, key="joins", sep="") - return f"{table}{laterals}{joins}" + pivots = self.expressions(expression, key="pivots", sep="") + return f"{table}{laterals}{joins}{pivots}" def tablesample_sql(self, expression): if self.alias_post_tablesample and isinstance(expression.this, exp.Alias): @@ -556,7 +559,17 @@ class Generator: rows = self.sql(expression, "rows") rows = f"{rows} ROWS" if rows else "" size = self.sql(expression, "size") - return f"{this} TABLESAMPLE{method}({bucket}{percent}{rows}{size}){alias}" + seed = self.sql(expression, "seed") + seed = f" SEED ({seed})" if seed else "" + return f"{this} TABLESAMPLE{method}({bucket}{percent}{rows}{size}){seed}{alias}" + + def pivot_sql(self, expression): + this = self.sql(expression, "this") + unpivot = expression.args.get("unpivot") + direction = "UNPIVOT" if unpivot else "PIVOT" + expressions = self.expressions(expression, key="expressions") + field = self.sql(expression, "field") + return f"{this} {direction}({expressions} FOR {field})" def tuple_sql(self, expression): return f"({self.expressions(expression, flat=True)})" @@ -681,6 +694,7 @@ class Generator: def ordered_sql(self, expression): desc = expression.args.get("desc") asc = not desc + nulls_first = expression.args.get("nulls_first") nulls_last = not nulls_first nulls_are_large = self.null_ordering == "nulls_are_large" @@ -760,6 +774,7 @@ class Generator: return self.query_modifiers( expression, self.wrap(expression), + self.expressions(expression, key="pivots", sep=" "), f" AS {alias}" if alias else "", ) @@ -1129,6 +1144,9 @@ class Generator: return f"{op} {expressions_sql}" return f"{self.seg(op)}{self.sep() if expressions_sql else ''}{expressions_sql}" + def naked_property(self, expression): + return f"{expression.name} {self.sql(expression, 'value')}" + def set_operation(self, expression, op): this = self.sql(expression, "this") op = self.seg(op) @@ -1136,3 +1154,13 @@ class Generator: def token_sql(self, token_type): return self.TOKEN_MAPPING.get(token_type, token_type.name) + + def userdefinedfunction_sql(self, expression): + this = self.sql(expression, "this") + expressions = self.no_identify(lambda: self.expressions(expression)) + return f"{this}({expressions})" + + def userdefinedfunctionkwarg_sql(self, expression): + this = self.sql(expression, "this") + kind = self.sql(expression, "kind") + return f"{this} {kind}" |