sqlglot.dialects.drill
1from __future__ import annotations 2 3import typing as t 4 5from sqlglot import exp, generator, parser, tokens 6from sqlglot.dialects.dialect import ( 7 Dialect, 8 create_with_partitions_sql, 9 datestrtodate_sql, 10 format_time_lambda, 11 no_trycast_sql, 12 rename_func, 13 str_position_sql, 14 timestrtotime_sql, 15 ts_or_ds_to_date_sql, 16) 17 18 19def _str_to_time_sql(self: generator.Generator, expression: exp.TsOrDsToDate) -> str: 20 return f"STRPTIME({self.sql(expression, 'this')}, {self.format_time(expression)})" 21 22 23def _ts_or_ds_to_date_sql(self: generator.Generator, expression: exp.TsOrDsToDate) -> str: 24 time_format = self.format_time(expression) 25 if time_format and time_format not in (Drill.time_format, Drill.date_format): 26 return f"CAST({_str_to_time_sql(self, expression)} AS DATE)" 27 return f"CAST({self.sql(expression, 'this')} AS DATE)" 28 29 30def _date_add_sql(kind: str) -> t.Callable[[generator.Generator, exp.DateAdd | exp.DateSub], str]: 31 def func(self: generator.Generator, expression: exp.DateAdd | exp.DateSub) -> str: 32 this = self.sql(expression, "this") 33 unit = exp.Var(this=expression.text("unit").upper() or "DAY") 34 return ( 35 f"DATE_{kind}({this}, {self.sql(exp.Interval(this=expression.expression, unit=unit))})" 36 ) 37 38 return func 39 40 41def _str_to_date(self: generator.Generator, expression: exp.StrToDate) -> str: 42 this = self.sql(expression, "this") 43 time_format = self.format_time(expression) 44 if time_format == Drill.date_format: 45 return f"CAST({this} AS DATE)" 46 return f"TO_DATE({this}, {time_format})" 47 48 49class Drill(Dialect): 50 normalize_functions = None 51 null_ordering = "nulls_are_last" 52 date_format = "'yyyy-MM-dd'" 53 dateint_format = "'yyyyMMdd'" 54 time_format = "'yyyy-MM-dd HH:mm:ss'" 55 56 time_mapping = { 57 "y": "%Y", 58 "Y": "%Y", 59 "YYYY": "%Y", 60 "yyyy": "%Y", 61 "YY": "%y", 62 "yy": "%y", 63 "MMMM": "%B", 64 "MMM": "%b", 65 "MM": "%m", 66 "M": "%-m", 67 "dd": "%d", 68 "d": "%-d", 69 "HH": "%H", 70 "H": "%-H", 71 "hh": "%I", 72 "h": "%-I", 73 "mm": "%M", 74 "m": "%-M", 75 "ss": "%S", 76 "s": "%-S", 77 "SSSSSS": "%f", 78 "a": "%p", 79 "DD": "%j", 80 "D": "%-j", 81 "E": "%a", 82 "EE": "%a", 83 "EEE": "%a", 84 "EEEE": "%A", 85 "''T''": "T", 86 } 87 88 class Tokenizer(tokens.Tokenizer): 89 QUOTES = ["'"] 90 IDENTIFIERS = ["`"] 91 STRING_ESCAPES = ["\\"] 92 ENCODE = "utf-8" 93 94 class Parser(parser.Parser): 95 STRICT_CAST = False 96 97 FUNCTIONS = { 98 **parser.Parser.FUNCTIONS, # type: ignore 99 "DATE_FORMAT": format_time_lambda(exp.TimeToStr, "drill"), 100 "TO_TIMESTAMP": exp.TimeStrToTime.from_arg_list, 101 "TO_CHAR": format_time_lambda(exp.TimeToStr, "drill"), 102 } 103 104 class Generator(generator.Generator): 105 TYPE_MAPPING = { 106 **generator.Generator.TYPE_MAPPING, # type: ignore 107 exp.DataType.Type.INT: "INTEGER", 108 exp.DataType.Type.SMALLINT: "INTEGER", 109 exp.DataType.Type.TINYINT: "INTEGER", 110 exp.DataType.Type.BINARY: "VARBINARY", 111 exp.DataType.Type.TEXT: "VARCHAR", 112 exp.DataType.Type.NCHAR: "VARCHAR", 113 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 114 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 115 exp.DataType.Type.DATETIME: "TIMESTAMP", 116 } 117 118 PROPERTIES_LOCATION = { 119 **generator.Generator.PROPERTIES_LOCATION, # type: ignore 120 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 121 } 122 123 TRANSFORMS = { 124 **generator.Generator.TRANSFORMS, # type: ignore 125 exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP", 126 exp.ArrayContains: rename_func("REPEATED_CONTAINS"), 127 exp.ArraySize: rename_func("REPEATED_COUNT"), 128 exp.Create: create_with_partitions_sql, 129 exp.DateAdd: _date_add_sql("ADD"), 130 exp.DateStrToDate: datestrtodate_sql, 131 exp.DateSub: _date_add_sql("SUB"), 132 exp.DateToDi: lambda self, e: f"CAST(TO_DATE({self.sql(e, 'this')}, {Drill.dateint_format}) AS INT)", 133 exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS VARCHAR), {Drill.dateint_format})", 134 exp.If: lambda self, e: f"`IF`({self.format_args(e.this, e.args.get('true'), e.args.get('false'))})", 135 exp.ILike: lambda self, e: f" {self.sql(e, 'this')} `ILIKE` {self.sql(e, 'expression')}", 136 exp.Levenshtein: rename_func("LEVENSHTEIN_DISTANCE"), 137 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 138 exp.RegexpLike: rename_func("REGEXP_MATCHES"), 139 exp.StrPosition: str_position_sql, 140 exp.StrToDate: _str_to_date, 141 exp.Pow: rename_func("POW"), 142 exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})", 143 exp.TimeStrToDate: lambda self, e: f"CAST({self.sql(e, 'this')} AS DATE)", 144 exp.TimeStrToTime: timestrtotime_sql, 145 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 146 exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})", 147 exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"), 148 exp.ToChar: lambda self, e: self.function_fallback_sql(e), 149 exp.TryCast: no_trycast_sql, 150 exp.TsOrDsAdd: lambda self, e: f"DATE_ADD(CAST({self.sql(e, 'this')} AS DATE), {self.sql(exp.Interval(this=e.expression, unit=exp.Var(this='DAY')))})", 151 exp.TsOrDsToDate: ts_or_ds_to_date_sql("drill"), 152 exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)", 153 } 154 155 def normalize_func(self, name: str) -> str: 156 return name if exp.SAFE_IDENTIFIER_RE.match(name) else f"`{name}`"
50class Drill(Dialect): 51 normalize_functions = None 52 null_ordering = "nulls_are_last" 53 date_format = "'yyyy-MM-dd'" 54 dateint_format = "'yyyyMMdd'" 55 time_format = "'yyyy-MM-dd HH:mm:ss'" 56 57 time_mapping = { 58 "y": "%Y", 59 "Y": "%Y", 60 "YYYY": "%Y", 61 "yyyy": "%Y", 62 "YY": "%y", 63 "yy": "%y", 64 "MMMM": "%B", 65 "MMM": "%b", 66 "MM": "%m", 67 "M": "%-m", 68 "dd": "%d", 69 "d": "%-d", 70 "HH": "%H", 71 "H": "%-H", 72 "hh": "%I", 73 "h": "%-I", 74 "mm": "%M", 75 "m": "%-M", 76 "ss": "%S", 77 "s": "%-S", 78 "SSSSSS": "%f", 79 "a": "%p", 80 "DD": "%j", 81 "D": "%-j", 82 "E": "%a", 83 "EE": "%a", 84 "EEE": "%a", 85 "EEEE": "%A", 86 "''T''": "T", 87 } 88 89 class Tokenizer(tokens.Tokenizer): 90 QUOTES = ["'"] 91 IDENTIFIERS = ["`"] 92 STRING_ESCAPES = ["\\"] 93 ENCODE = "utf-8" 94 95 class Parser(parser.Parser): 96 STRICT_CAST = False 97 98 FUNCTIONS = { 99 **parser.Parser.FUNCTIONS, # type: ignore 100 "DATE_FORMAT": format_time_lambda(exp.TimeToStr, "drill"), 101 "TO_TIMESTAMP": exp.TimeStrToTime.from_arg_list, 102 "TO_CHAR": format_time_lambda(exp.TimeToStr, "drill"), 103 } 104 105 class Generator(generator.Generator): 106 TYPE_MAPPING = { 107 **generator.Generator.TYPE_MAPPING, # type: ignore 108 exp.DataType.Type.INT: "INTEGER", 109 exp.DataType.Type.SMALLINT: "INTEGER", 110 exp.DataType.Type.TINYINT: "INTEGER", 111 exp.DataType.Type.BINARY: "VARBINARY", 112 exp.DataType.Type.TEXT: "VARCHAR", 113 exp.DataType.Type.NCHAR: "VARCHAR", 114 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 115 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 116 exp.DataType.Type.DATETIME: "TIMESTAMP", 117 } 118 119 PROPERTIES_LOCATION = { 120 **generator.Generator.PROPERTIES_LOCATION, # type: ignore 121 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 122 } 123 124 TRANSFORMS = { 125 **generator.Generator.TRANSFORMS, # type: ignore 126 exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP", 127 exp.ArrayContains: rename_func("REPEATED_CONTAINS"), 128 exp.ArraySize: rename_func("REPEATED_COUNT"), 129 exp.Create: create_with_partitions_sql, 130 exp.DateAdd: _date_add_sql("ADD"), 131 exp.DateStrToDate: datestrtodate_sql, 132 exp.DateSub: _date_add_sql("SUB"), 133 exp.DateToDi: lambda self, e: f"CAST(TO_DATE({self.sql(e, 'this')}, {Drill.dateint_format}) AS INT)", 134 exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS VARCHAR), {Drill.dateint_format})", 135 exp.If: lambda self, e: f"`IF`({self.format_args(e.this, e.args.get('true'), e.args.get('false'))})", 136 exp.ILike: lambda self, e: f" {self.sql(e, 'this')} `ILIKE` {self.sql(e, 'expression')}", 137 exp.Levenshtein: rename_func("LEVENSHTEIN_DISTANCE"), 138 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 139 exp.RegexpLike: rename_func("REGEXP_MATCHES"), 140 exp.StrPosition: str_position_sql, 141 exp.StrToDate: _str_to_date, 142 exp.Pow: rename_func("POW"), 143 exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})", 144 exp.TimeStrToDate: lambda self, e: f"CAST({self.sql(e, 'this')} AS DATE)", 145 exp.TimeStrToTime: timestrtotime_sql, 146 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 147 exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})", 148 exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"), 149 exp.ToChar: lambda self, e: self.function_fallback_sql(e), 150 exp.TryCast: no_trycast_sql, 151 exp.TsOrDsAdd: lambda self, e: f"DATE_ADD(CAST({self.sql(e, 'this')} AS DATE), {self.sql(exp.Interval(this=e.expression, unit=exp.Var(this='DAY')))})", 152 exp.TsOrDsToDate: ts_or_ds_to_date_sql("drill"), 153 exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)", 154 } 155 156 def normalize_func(self, name: str) -> str: 157 return name if exp.SAFE_IDENTIFIER_RE.match(name) else f"`{name}`"
89 class Tokenizer(tokens.Tokenizer): 90 QUOTES = ["'"] 91 IDENTIFIERS = ["`"] 92 STRING_ESCAPES = ["\\"] 93 ENCODE = "utf-8"
Inherited Members
95 class Parser(parser.Parser): 96 STRICT_CAST = False 97 98 FUNCTIONS = { 99 **parser.Parser.FUNCTIONS, # type: ignore 100 "DATE_FORMAT": format_time_lambda(exp.TimeToStr, "drill"), 101 "TO_TIMESTAMP": exp.TimeStrToTime.from_arg_list, 102 "TO_CHAR": format_time_lambda(exp.TimeToStr, "drill"), 103 }
Parser consumes a list of tokens produced by the sqlglot.tokens.Tokenizer
and produces
a parsed syntax tree.
Arguments:
- error_level: the desired error level. Default: ErrorLevel.RAISE
- error_message_context: determines the amount of context to capture from a query string when displaying the error message (in number of characters). Default: 50.
- index_offset: Index offset for arrays eg ARRAY[0] vs ARRAY[1] as the head of a list. Default: 0
- alias_post_tablesample: If the table alias comes after tablesample. Default: False
- max_errors: Maximum number of error messages to include in a raised ParseError. This is only relevant if error_level is ErrorLevel.RAISE. Default: 3
- null_ordering: Indicates the default null ordering method to use if not explicitly set. Options are "nulls_are_small", "nulls_are_large", "nulls_are_last". Default: "nulls_are_small"
Inherited Members
105 class Generator(generator.Generator): 106 TYPE_MAPPING = { 107 **generator.Generator.TYPE_MAPPING, # type: ignore 108 exp.DataType.Type.INT: "INTEGER", 109 exp.DataType.Type.SMALLINT: "INTEGER", 110 exp.DataType.Type.TINYINT: "INTEGER", 111 exp.DataType.Type.BINARY: "VARBINARY", 112 exp.DataType.Type.TEXT: "VARCHAR", 113 exp.DataType.Type.NCHAR: "VARCHAR", 114 exp.DataType.Type.TIMESTAMPLTZ: "TIMESTAMP", 115 exp.DataType.Type.TIMESTAMPTZ: "TIMESTAMP", 116 exp.DataType.Type.DATETIME: "TIMESTAMP", 117 } 118 119 PROPERTIES_LOCATION = { 120 **generator.Generator.PROPERTIES_LOCATION, # type: ignore 121 exp.PartitionedByProperty: exp.Properties.Location.POST_SCHEMA, 122 } 123 124 TRANSFORMS = { 125 **generator.Generator.TRANSFORMS, # type: ignore 126 exp.CurrentTimestamp: lambda *_: "CURRENT_TIMESTAMP", 127 exp.ArrayContains: rename_func("REPEATED_CONTAINS"), 128 exp.ArraySize: rename_func("REPEATED_COUNT"), 129 exp.Create: create_with_partitions_sql, 130 exp.DateAdd: _date_add_sql("ADD"), 131 exp.DateStrToDate: datestrtodate_sql, 132 exp.DateSub: _date_add_sql("SUB"), 133 exp.DateToDi: lambda self, e: f"CAST(TO_DATE({self.sql(e, 'this')}, {Drill.dateint_format}) AS INT)", 134 exp.DiToDate: lambda self, e: f"TO_DATE(CAST({self.sql(e, 'this')} AS VARCHAR), {Drill.dateint_format})", 135 exp.If: lambda self, e: f"`IF`({self.format_args(e.this, e.args.get('true'), e.args.get('false'))})", 136 exp.ILike: lambda self, e: f" {self.sql(e, 'this')} `ILIKE` {self.sql(e, 'expression')}", 137 exp.Levenshtein: rename_func("LEVENSHTEIN_DISTANCE"), 138 exp.PartitionedByProperty: lambda self, e: f"PARTITION BY {self.sql(e, 'this')}", 139 exp.RegexpLike: rename_func("REGEXP_MATCHES"), 140 exp.StrPosition: str_position_sql, 141 exp.StrToDate: _str_to_date, 142 exp.Pow: rename_func("POW"), 143 exp.StrToTime: lambda self, e: f"TO_TIMESTAMP({self.sql(e, 'this')}, {self.format_time(e)})", 144 exp.TimeStrToDate: lambda self, e: f"CAST({self.sql(e, 'this')} AS DATE)", 145 exp.TimeStrToTime: timestrtotime_sql, 146 exp.TimeStrToUnix: rename_func("UNIX_TIMESTAMP"), 147 exp.TimeToStr: lambda self, e: f"TO_CHAR({self.sql(e, 'this')}, {self.format_time(e)})", 148 exp.TimeToUnix: rename_func("UNIX_TIMESTAMP"), 149 exp.ToChar: lambda self, e: self.function_fallback_sql(e), 150 exp.TryCast: no_trycast_sql, 151 exp.TsOrDsAdd: lambda self, e: f"DATE_ADD(CAST({self.sql(e, 'this')} AS DATE), {self.sql(exp.Interval(this=e.expression, unit=exp.Var(this='DAY')))})", 152 exp.TsOrDsToDate: ts_or_ds_to_date_sql("drill"), 153 exp.TsOrDiToDi: lambda self, e: f"CAST(SUBSTR(REPLACE(CAST({self.sql(e, 'this')} AS VARCHAR), '-', ''), 1, 8) AS INT)", 154 } 155 156 def normalize_func(self, name: str) -> str: 157 return name if exp.SAFE_IDENTIFIER_RE.match(name) else f"`{name}`"
Generator interprets the given syntax tree and produces a SQL string as an output.
Arguments:
- time_mapping (dict): the dictionary of custom time mappings in which the key represents a python time format and the output the target time format
- time_trie (trie): a trie of the time_mapping keys
- pretty (bool): if set to True the returned string will be formatted. Default: False.
- quote_start (str): specifies which starting character to use to delimit quotes. Default: '.
- quote_end (str): specifies which ending character to use to delimit quotes. Default: '.
- identifier_start (str): specifies which starting character to use to delimit identifiers. Default: ".
- identifier_end (str): specifies which ending character to use to delimit identifiers. Default: ".
- identify (bool | str): 'always': always quote, 'safe': quote identifiers if they don't contain an upcase, True defaults to always.
- normalize (bool): if set to True all identifiers will lower cased
- string_escape (str): specifies a string escape character. Default: '.
- identifier_escape (str): specifies an identifier escape character. Default: ".
- pad (int): determines padding in a formatted string. Default: 2.
- indent (int): determines the size of indentation in a formatted string. Default: 4.
- unnest_column_only (bool): if true unnest table aliases are considered only as column aliases
- normalize_functions (str): normalize function names, "upper", "lower", or None Default: "upper"
- alias_post_tablesample (bool): if the table alias comes after tablesample Default: False
- unsupported_level (ErrorLevel): determines the generator's behavior when it encounters unsupported expressions. Default ErrorLevel.WARN.
- null_ordering (str): Indicates the default null ordering method to use if not explicitly set. Options are "nulls_are_small", "nulls_are_large", "nulls_are_last". Default: "nulls_are_small"
- max_unsupported (int): 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 (bool): if the the comma is leading or trailing in select statements 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 or not to preserve comments in the output SQL code. Default: True
Inherited Members
- sqlglot.generator.Generator
- Generator
- generate
- unsupported
- sep
- seg
- pad_comment
- maybe_comment
- wrap
- no_identify
- indent
- sql
- uncache_sql
- cache_sql
- characterset_sql
- column_sql
- columndef_sql
- columnconstraint_sql
- autoincrementcolumnconstraint_sql
- compresscolumnconstraint_sql
- generatedasidentitycolumnconstraint_sql
- notnullcolumnconstraint_sql
- primarykeycolumnconstraint_sql
- uniquecolumnconstraint_sql
- create_sql
- describe_sql
- prepend_ctes
- with_sql
- cte_sql
- tablealias_sql
- bitstring_sql
- hexstring_sql
- datatype_sql
- directory_sql
- delete_sql
- drop_sql
- except_sql
- except_op
- fetch_sql
- filter_sql
- hint_sql
- index_sql
- identifier_sql
- national_sql
- partition_sql
- properties_sql
- root_properties
- properties
- with_properties
- locate_properties
- property_sql
- likeproperty_sql
- fallbackproperty_sql
- journalproperty_sql
- freespaceproperty_sql
- afterjournalproperty_sql
- checksumproperty_sql
- mergeblockratioproperty_sql
- datablocksizeproperty_sql
- blockcompressionproperty_sql
- isolatedloadingproperty_sql
- lockingproperty_sql
- withdataproperty_sql
- insert_sql
- intersect_sql
- intersect_op
- introducer_sql
- pseudotype_sql
- returning_sql
- rowformatdelimitedproperty_sql
- table_sql
- tablesample_sql
- pivot_sql
- tuple_sql
- update_sql
- values_sql
- var_sql
- into_sql
- from_sql
- group_sql
- having_sql
- join_sql
- lambda_sql
- lateral_sql
- limit_sql
- offset_sql
- setitem_sql
- set_sql
- pragma_sql
- lock_sql
- literal_sql
- loaddata_sql
- null_sql
- boolean_sql
- order_sql
- cluster_sql
- distribute_sql
- sort_sql
- ordered_sql
- matchrecognize_sql
- query_modifiers
- select_sql
- schema_sql
- star_sql
- structkwarg_sql
- parameter_sql
- sessionparameter_sql
- placeholder_sql
- subquery_sql
- qualify_sql
- union_sql
- union_op
- unnest_sql
- where_sql
- window_sql
- partition_by_sql
- window_spec_sql
- withingroup_sql
- between_sql
- bracket_sql
- all_sql
- any_sql
- exists_sql
- case_sql
- constraint_sql
- extract_sql
- trim_sql
- concat_sql
- check_sql
- foreignkey_sql
- primarykey_sql
- unique_sql
- if_sql
- jsonkeyvalue_sql
- jsonobject_sql
- in_sql
- in_unnest_op
- interval_sql
- return_sql
- reference_sql
- anonymous_sql
- paren_sql
- neg_sql
- not_sql
- alias_sql
- aliases_sql
- attimezone_sql
- add_sql
- and_sql
- connector_sql
- bitwiseand_sql
- bitwiseleftshift_sql
- bitwisenot_sql
- bitwiseor_sql
- bitwiserightshift_sql
- bitwisexor_sql
- cast_sql
- currentdate_sql
- collate_sql
- command_sql
- comment_sql
- transaction_sql
- commit_sql
- rollback_sql
- altercolumn_sql
- renametable_sql
- altertable_sql
- droppartition_sql
- addconstraint_sql
- distinct_sql
- ignorenulls_sql
- respectnulls_sql
- intdiv_sql
- dpipe_sql
- div_sql
- overlaps_sql
- distance_sql
- dot_sql
- eq_sql
- escape_sql
- glob_sql
- gt_sql
- gte_sql
- ilike_sql
- is_sql
- like_sql
- similarto_sql
- lt_sql
- lte_sql
- mod_sql
- mul_sql
- neq_sql
- nullsafeeq_sql
- nullsafeneq_sql
- or_sql
- slice_sql
- sub_sql
- trycast_sql
- use_sql
- binary
- function_fallback_sql
- func
- format_args
- text_width
- format_time
- expressions
- op_expressions
- naked_property
- set_operation
- tag_sql
- token_sql
- userdefinedfunction_sql
- joinhint_sql
- kwarg_sql
- when_sql
- merge_sql
- tochar_sql