@@ -1067,36 +1067,46 @@ def property_sql(self: Generator, expression: exp.Property) -> str:
10671067 return f"{ self .property_name (expression , string_key = True )} ={ self .sql (expression , 'value' )} "
10681068
10691069
1070- def str_position_sql (
1070+ def strposition_sql (
10711071 self : Generator ,
10721072 expression : exp .StrPosition ,
1073- generate_instance : bool = False ,
1074- str_position_func_name : str = "STRPOS" ,
1073+ func_name : str = "STRPOS" ,
1074+ supports_position : bool = False ,
1075+ supports_occurrence : bool = False ,
1076+ use_ansi_position : bool = True ,
10751077) -> str :
1076- this = self .sql (expression , "this" )
1077- substr = self .sql (expression , "substr" )
1078- position = self .sql (expression , "position" )
1079- instance = expression .args .get ("instance" ) if generate_instance else None
1080- position_offset = ""
1081-
1082- if position :
1083- # Normalize third 'pos' argument into 'SUBSTR(..) + offset' across dialects
1084- this = self .func ("SUBSTR" , this , position )
1085- position_offset = f" + { position } - 1"
1086-
1087- strpos_sql = self .func (str_position_func_name , this , substr , instance )
1088-
1089- if position_offset :
1090- zero = exp .Literal .number (0 )
1091- # If match is not found (returns 0) the position offset should not be applied
1092- case = exp .If (
1093- this = exp .EQ (this = strpos_sql , expression = zero ),
1094- true = zero ,
1095- false = strpos_sql + position_offset ,
1096- )
1097- strpos_sql = self .sql (case )
1078+ string = expression .this
1079+ substr = expression .args .get ("substr" )
1080+ position = expression .args .get ("position" )
1081+ occurrence = expression .args .get ("occurrence" )
1082+ zero = exp .Literal .number (0 )
1083+ one = exp .Literal .number (1 )
1084+
1085+ if supports_occurrence and occurrence and supports_position and not position :
1086+ position = one
1087+
1088+ if position and not supports_position :
1089+ string = exp .Substring (this = string , start = position )
1090+
1091+ if func_name == "POSITION" and use_ansi_position :
1092+ func = exp .Anonymous (this = func_name , expressions = [exp .In (this = substr , field = string )])
1093+ else :
1094+ args = [substr , string ] if func_name in ("LOCATE" , "CHARINDEX" ) else [string , substr ]
1095+ if supports_position :
1096+ args .append (position )
1097+ if occurrence :
1098+ if supports_occurrence :
1099+ args .append (occurrence )
1100+ else :
1101+ self .unsupported (f"{ func_name } does not support the occurrence parameter." )
1102+ func = exp .Anonymous (this = func_name , expressions = args )
1103+
1104+ if position and not supports_position :
1105+ func_with_offset = exp .Sub (this = func + position , expression = one )
1106+ func_wrapped = exp .If (this = func .eq (zero ), true = zero , false = func_with_offset )
1107+ return self .sql (func_wrapped )
10981108
1099- return strpos_sql
1109+ return self . sql ( func )
11001110
11011111
11021112def struct_extract_sql (self : Generator , expression : exp .StructExtract ) -> str :
@@ -1269,18 +1279,6 @@ def no_datetime_sql(self: Generator, expression: exp.Datetime) -> str:
12691279 return self .sql (exp .cast (exp .Add (this = this , expression = expr ), exp .DataType .Type .TIMESTAMP ))
12701280
12711281
1272- def locate_to_strposition (args : t .List ) -> exp .Expression :
1273- return exp .StrPosition (
1274- this = seq_get (args , 1 ), substr = seq_get (args , 0 ), position = seq_get (args , 2 )
1275- )
1276-
1277-
1278- def strposition_to_locate_sql (self : Generator , expression : exp .StrPosition ) -> str :
1279- return self .func (
1280- "LOCATE" , expression .args .get ("substr" ), expression .this , expression .args .get ("position" )
1281- )
1282-
1283-
12841282def left_to_substring_sql (self : Generator , expression : exp .Left ) -> str :
12851283 return self .sql (
12861284 exp .Substring (
0 commit comments