@@ -1520,12 +1520,9 @@ class TConverter : public IPGParseEvents {
1520
1520
}
1521
1521
} else if (NodeTag (r->val ) == T_FuncCall) {
1522
1522
auto func = CAST_NODE (FuncCall, r->val );
1523
- TVector<TString> names;
1524
- if (!ExtractFuncName (func, names)) {
1523
+ if (!ExtractFuncName (func, name, nullptr )) {
1525
1524
return nullptr ;
1526
1525
}
1527
-
1528
- name = names.back ();
1529
1526
}
1530
1527
}
1531
1528
@@ -3427,12 +3424,13 @@ class TConverter : public IPGParseEvents {
3427
3424
return {};
3428
3425
}
3429
3426
3430
- auto func = ParseFuncCall (CAST_NODE (FuncCall, node), settings, true );
3427
+ bool injectRead = false ;
3428
+ auto func = ParseFuncCall (CAST_NODE (FuncCall, node), settings, true , injectRead);
3431
3429
if (!func) {
3432
3430
return {};
3433
3431
}
3434
3432
3435
- return TFromDesc{ func, alias, colnames, false };
3433
+ return TFromDesc{ func, alias, colnames, injectRead };
3436
3434
}
3437
3435
3438
3436
TMaybe<TFromDesc> ParseRangeSubselect (const RangeSubselect* value) {
@@ -3723,7 +3721,8 @@ class TConverter : public IPGParseEvents {
3723
3721
return ParseNullTestExpr (CAST_NODE (NullTest, node), settings);
3724
3722
}
3725
3723
case T_FuncCall: {
3726
- return ParseFuncCall (CAST_NODE (FuncCall, node), settings, false );
3724
+ bool injectRead;
3725
+ return ParseFuncCall (CAST_NODE (FuncCall, node), settings, false , injectRead);
3727
3726
}
3728
3727
case T_A_ArrayExpr: {
3729
3728
return ParseAArrayExpr (CAST_NODE (A_ArrayExpr, node), settings);
@@ -4009,7 +4008,124 @@ class TConverter : public IPGParseEvents {
4009
4008
return L (A (" PgSubLink" ), QA (linkType), L (A (" Void" )), L (A (" Void" )), rowTest, L (A (" lambda" ), QL (), select));
4010
4009
}
4011
4010
4012
- TAstNode* ParseFuncCall (const FuncCall* value, const TExprSettings& settings, bool rangeFunction) {
4011
+ TAstNode* ParseTableRangeFunction (const TString& name, const TString& schema, List* args) {
4012
+ auto source = BuildClusterSinkOrSourceExpression (false , schema);
4013
+ if (!source) {
4014
+ return nullptr ;
4015
+ }
4016
+
4017
+ TVector<TString> argStrs;
4018
+ for (int i = 0 ; i < ListLength (args); ++i) {
4019
+ auto arg = ListNodeNth (args, i);
4020
+ if (NodeTag (arg) == T_A_Const && (NodeTag (CAST_NODE (A_Const, arg)->val ) == T_String)) {
4021
+ TString rawStr = StrVal (CAST_NODE (A_Const, arg)->val );
4022
+ argStrs.push_back (rawStr);
4023
+ } else {
4024
+ AddError (" Expected String argument for table function" );
4025
+ return nullptr ;
4026
+ }
4027
+ }
4028
+
4029
+ if (argStrs.empty ()) {
4030
+ AddError (" Expected at least one argument for table function" );
4031
+ return nullptr ;
4032
+ }
4033
+
4034
+ TAstNode* key;
4035
+ auto lowerName = to_lower (name);
4036
+ auto options = QL ();
4037
+ if (lowerName == " concat" ) {
4038
+ TVector<TAstNode*> concatArgs;
4039
+ concatArgs.push_back (A (" MrTableConcat" ));
4040
+ for (const auto & s : argStrs) {
4041
+ concatArgs.push_back (L (A (" Key" ), QL (QA (" table" ),L (A (" String" ), QAX (s)))));
4042
+ }
4043
+
4044
+ key = VL (concatArgs);
4045
+ } else if (lowerName == " concat_view" ) {
4046
+ if (argStrs.size () % 2 != 0 ) {
4047
+ AddError (" Expected sequence of pairs of table and view for concat_view" );
4048
+ return nullptr ;
4049
+ }
4050
+
4051
+ TVector<TAstNode*> concatArgs;
4052
+ concatArgs.push_back (A (" MrTableConcat" ));
4053
+ for (ui32 i = 0 ; i < argStrs.size (); i += 2 ) {
4054
+ concatArgs.push_back (L (A (" Key" ),
4055
+ QL (QA (" table" ),L (A (" String" ), QAX (argStrs[i]))),
4056
+ QL (QA (" view" ),L (A (" String" ), QAX (argStrs[i + 1 ])))));
4057
+ }
4058
+
4059
+ key = VL (concatArgs);
4060
+ } else if (lowerName == " range" ) {
4061
+ if (argStrs.size () > 5 ) {
4062
+ AddError (" Too many arguments" );
4063
+ return nullptr ;
4064
+ }
4065
+
4066
+ options = QL (QL (QA (" ignorenonexisting" )));
4067
+ TAstNode* expr;
4068
+ if (argStrs.size () == 1 ) {
4069
+ expr = L (A (" Bool" ),QA (" true" ));
4070
+ } else if (argStrs.size () == 2 ) {
4071
+ expr = L (A (" >=" ),A (" item" ),L (A (" String" ),QAX (argStrs[1 ])));
4072
+ } else {
4073
+ expr = L (A (" And" ),
4074
+ L (A (" >=" ),A (" item" ),L (A (" String" ),QAX (argStrs[1 ]))),
4075
+ L (A (" <=" ),A (" item" ),L (A (" String" ),QAX (argStrs[2 ])))
4076
+ );
4077
+ }
4078
+
4079
+ auto lambda = L (A (" lambda" ), QL (A (" item" )), expr);
4080
+ auto range = L (A (" MrTableRange" ), QAX (argStrs[0 ]), lambda, QAX (argStrs.size () < 4 ? " " : argStrs[3 ]));
4081
+ if (argStrs.size () < 5 ) {
4082
+ key = L (A (" Key" ), QL (QA (" table" ),range));
4083
+ } else {
4084
+ key = L (A (" Key" ), QL (QA (" table" ),range), QL (QA (" view" ),L (A (" String" ), QAX (argStrs[4 ]))));
4085
+ }
4086
+ } else if (lowerName == " regexp" || lowerName == " like" ) {
4087
+ if (argStrs.size () < 2 || argStrs.size () > 4 ) {
4088
+ AddError (" Expected from 2 to 4 arguments" );
4089
+ return nullptr ;
4090
+ }
4091
+
4092
+ options = QL (QL (QA (" ignorenonexisting" )));
4093
+ TAstNode* expr;
4094
+ if (lowerName == " regexp" ) {
4095
+ expr = L (A (" Apply" ),L (A (" Udf" ),QA (" Re2.Grep" ),
4096
+ QL (L (A (" String" ),QAX (argStrs[1 ])),L (A (" Null" )))),
4097
+ A (" item" ));
4098
+ } else {
4099
+ expr = L (A (" Apply" ),L (A (" Udf" ),QA (" Re2.Match" ),
4100
+ QL (L (A (" Apply" ),
4101
+ L (A (" Udf" ), QA (" Re2.PatternFromLike" )),
4102
+ L (A (" String" ),QAX (argStrs[1 ]))),L (A (" Null" )))),
4103
+ A (" item" ));
4104
+ }
4105
+
4106
+ auto lambda = L (A (" lambda" ), QL (A (" item" )), expr);
4107
+ auto range = L (A (" MrTableRange" ), QAX (argStrs[0 ]), lambda, QAX (argStrs.size () < 3 ? " " : argStrs[2 ]));
4108
+ if (argStrs.size () < 4 ) {
4109
+ key = L (A (" Key" ), QL (QA (" table" ),range));
4110
+ } else {
4111
+ key = L (A (" Key" ), QL (QA (" table" ),range), QL (QA (" view" ),L (A (" String" ), QAX (argStrs[3 ]))));
4112
+ }
4113
+ } else {
4114
+ AddError (TStringBuilder () << " Unknown table function: " << name);
4115
+ return nullptr ;
4116
+ }
4117
+
4118
+ return L (
4119
+ A (" Read!" ),
4120
+ A (" world" ),
4121
+ source,
4122
+ key,
4123
+ L (A (" Void" )),
4124
+ options
4125
+ );
4126
+ }
4127
+
4128
+ TAstNode* ParseFuncCall (const FuncCall* value, const TExprSettings& settings, bool rangeFunction, bool & injectRead) {
4013
4129
AT_LOCATION (value);
4014
4130
if (ListLength (value->agg_order ) > 0 ) {
4015
4131
AddError (" FuncCall: unsupported agg_order" );
@@ -4052,12 +4168,17 @@ class TConverter : public IPGParseEvents {
4052
4168
}
4053
4169
}
4054
4170
4055
- TVector<TString> names;
4056
- if (!ExtractFuncName (value, names)) {
4171
+ TString name;
4172
+ TString schema;
4173
+ if (!ExtractFuncName (value, name, rangeFunction ? &schema : nullptr )) {
4057
4174
return nullptr ;
4058
4175
}
4059
4176
4060
- auto name = names.back ();
4177
+ if (rangeFunction && !schema.empty () && schema != " pg_catalog" ) {
4178
+ injectRead = true ;
4179
+ return ParseTableRangeFunction (name, schema, value->args );
4180
+ }
4181
+
4061
4182
if (name == " shobj_description" || name == " obj_description" ) {
4062
4183
AddWarning (TIssuesIds::PG_COMPAT, name + " function forced to NULL" );
4063
4184
return L (A (" Null" ));
@@ -4159,7 +4280,8 @@ class TConverter : public IPGParseEvents {
4159
4280
return VL (args.data (), args.size ());
4160
4281
}
4161
4282
4162
- bool ExtractFuncName (const FuncCall* value, TVector<TString>& names) {
4283
+ bool ExtractFuncName (const FuncCall* value, TString& name, TString* schemaName) {
4284
+ TVector<TString> names;
4163
4285
for (int i = 0 ; i < ListLength (value->funcname ); ++i) {
4164
4286
auto x = ListNodeNth (value->funcname , i);
4165
4287
if (NodeTag (x) != T_String) {
@@ -4180,11 +4302,18 @@ class TConverter : public IPGParseEvents {
4180
4302
return false ;
4181
4303
}
4182
4304
4183
- if (names.size () == 2 && names[0 ] != " pg_catalog" ) {
4184
- AddError (TStringBuilder () << " FuncCall: expected pg_catalog, but got: " << names[0 ]);
4185
- return false ;
4305
+ if (names.size () == 2 ) {
4306
+ if (!schemaName && names[0 ] != " pg_catalog" ) {
4307
+ AddError (TStringBuilder () << " FuncCall: expected pg_catalog, but got: " << names[0 ]);
4308
+ return false ;
4309
+ }
4310
+
4311
+ if (schemaName) {
4312
+ *schemaName = names[0 ];
4313
+ }
4186
4314
}
4187
4315
4316
+ name = names.back ();
4188
4317
return true ;
4189
4318
}
4190
4319
0 commit comments