12
12
#include < ydb/library/yql/parser/pg_wrapper/interface/utils.h>
13
13
14
14
#include < util/generic/set.h>
15
+ #include < util/generic/hash.h>
15
16
16
17
namespace NYql {
17
18
@@ -64,8 +65,8 @@ bool ValidateInputTypes(TExprNode& node, TExprContext& ctx) {
64
65
return true ;
65
66
}
66
67
67
- TExprNodePtr WrapWithPgCast (TExprNodePtr&& node, ui32 targetTypeId, TContext & ctx) {
68
- return ctx.Expr . Builder (node->Pos ())
68
+ TExprNodePtr WrapWithPgCast (TExprNodePtr&& node, ui32 targetTypeId, TExprContext & ctx) {
69
+ return ctx.Builder (node->Pos ())
69
70
.Callable (" PgCast" )
70
71
.Add (0 , std::move (node))
71
72
.Callable (1 , " PgType" )
@@ -75,6 +76,113 @@ TExprNodePtr WrapWithPgCast(TExprNodePtr&& node, ui32 targetTypeId, TContext& ct
75
76
.Build ();
76
77
};
77
78
79
+ TExprNodePtr FindLeftCombinatorOfNthSetItem (const TExprNode* setItems, const TExprNode* setOps, ui32 n) {
80
+ TVector<ui32> setItemsStack (setItems->ChildrenSize ());
81
+ i32 sp = -1 ;
82
+ ui32 itemIdx = 0 ;
83
+ for (const auto & op : setOps->Children ()) {
84
+ if (op->Content () == " push" ) {
85
+ setItemsStack[++sp] = itemIdx++;
86
+ } else {
87
+ if (setItemsStack[sp] == n) {
88
+ return op;
89
+ }
90
+ --sp;
91
+ Y_ENSURE (0 <= sp);
92
+ }
93
+ }
94
+ Y_UNREACHABLE ();
95
+ }
96
+
97
+ IGraphTransformer::TStatus InferPgCommonType (TPositionHandle pos, const TExprNode* setItems, const TExprNode* setOps,
98
+ TColumnOrder& resultColumnOrder, const TStructExprType*& resultStructType, TExtContext& ctx)
99
+ {
100
+ TVector<TVector<ui32>> pgTypes;
101
+ size_t fieldsCnt = 0 ;
102
+
103
+ for (size_t i = 0 ; i < setItems->ChildrenSize (); ++i) {
104
+ const auto * child = setItems->Child (i);
105
+
106
+ if (!EnsureListType (*child, ctx.Expr )) {
107
+ return IGraphTransformer::TStatus::Error;
108
+ }
109
+ auto itemType = child->GetTypeAnn ()->Cast <TListExprType>()->GetItemType ();
110
+ YQL_ENSURE (itemType);
111
+
112
+ if (!EnsureStructType (child->Pos (), *itemType, ctx.Expr )) {
113
+ return IGraphTransformer::TStatus::Error;
114
+ }
115
+
116
+ auto childColumnOrder = ctx.Types .LookupColumnOrder (*child);
117
+ if (!childColumnOrder) {
118
+ ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (child->Pos ()), TStringBuilder ()
119
+ << " Input #" << i << " does not have ordered columns. "
120
+ << " Consider making column order explicit by using SELECT with column names" ));
121
+ return IGraphTransformer::TStatus::Error;
122
+ }
123
+
124
+ if (0 == i) {
125
+ resultColumnOrder = *childColumnOrder;
126
+ fieldsCnt = resultColumnOrder.size ();
127
+
128
+ pgTypes.resize (fieldsCnt);
129
+ for (size_t j = 0 ; j < fieldsCnt; ++j) {
130
+ pgTypes[j].reserve (setItems->ChildrenSize ());
131
+ }
132
+ } else {
133
+ if ((*childColumnOrder).size () != fieldsCnt) {
134
+ TExprNodePtr combinator = FindLeftCombinatorOfNthSetItem (setItems, setOps, i);
135
+ Y_ENSURE (combinator);
136
+
137
+ TString op (combinator->Content ());
138
+ if (op.EndsWith (" _all" )) {
139
+ op.erase (op.length () - 4 );
140
+ }
141
+ op.to_upper ();
142
+
143
+ ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (child->Pos ()), TStringBuilder ()
144
+ << " each " << op << " query must have the same number of columns" ));
145
+
146
+ return IGraphTransformer::TStatus::Error;
147
+ }
148
+ }
149
+
150
+ const auto structType = itemType->Cast <TStructExprType>();
151
+ {
152
+ size_t j = 0 ;
153
+ for (const auto & col : *childColumnOrder) {
154
+ auto itemIdx = structType->FindItem (col);
155
+ YQL_ENSURE (itemIdx);
156
+ pgTypes[j].push_back (structType->GetItems ()[*itemIdx]->GetItemType ()->Cast <TPgExprType>()->GetId ());
157
+
158
+ ++j;
159
+ }
160
+ }
161
+ }
162
+
163
+ TVector<const TItemExprType*> structItems;
164
+ for (size_t j = 0 ; j < fieldsCnt; ++j) {
165
+ const NPg::TTypeDesc* commonType;
166
+ if (const auto issue = NPg::LookupCommonType (pgTypes[j],
167
+ [j, &setItems, &ctx](size_t i) {
168
+ return ctx.Expr .GetPosition (setItems->Child (i)->Child (j)->Pos ());
169
+ }, commonType))
170
+ {
171
+ ctx.Expr .AddError (*issue);
172
+ return IGraphTransformer::TStatus::Error;
173
+ }
174
+ structItems.push_back (ctx.Expr .MakeType <TItemExprType>(resultColumnOrder[j],
175
+ ctx.Expr .MakeType <TPgExprType>(commonType->TypeId )));
176
+ }
177
+
178
+ resultStructType = ctx.Expr .MakeType <TStructExprType>(structItems);
179
+ if (!resultStructType->Validate (pos, ctx.Expr )) {
180
+ return IGraphTransformer::TStatus::Error;
181
+ }
182
+
183
+ return IGraphTransformer::TStatus::Ok;
184
+ }
185
+
78
186
IGraphTransformer::TStatus PgStarWrapper (const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
79
187
Y_UNUSED (output);
80
188
if (!EnsureArgsCount (*input, 0 , ctx.Expr )) {
@@ -212,12 +320,12 @@ IGraphTransformer::TStatus PgCallWrapper(const TExprNode::TPtr& input, TExprNode
212
320
const auto & fargTypes = (*procPtr)->ArgTypes ;
213
321
for (size_t i = 0 ; i < argTypes.size (); ++i) {
214
322
if (IsCastRequired (argTypes[i], fargTypes[i])) {
215
- children[i+3 ] = WrapWithPgCast (std::move (children[i+3 ]), fargTypes[i], ctx);
323
+ children[i+3 ] = WrapWithPgCast (std::move (children[i+3 ]), fargTypes[i], ctx. Expr );
216
324
}
217
325
}
218
326
output = ctx.Expr .NewCallable (input->Pos (), " PgResolvedCall" , std::move (children));
219
327
} else if (const auto * typePtr = std::get_if<const NPg::TTypeDesc*>(&procOrType)) {
220
- output = WrapWithPgCast (std::move (children[2 ]), (*typePtr)->TypeId , ctx);
328
+ output = WrapWithPgCast (std::move (children[2 ]), (*typePtr)->TypeId , ctx. Expr );
221
329
} else {
222
330
Y_UNREACHABLE ();
223
331
}
@@ -454,16 +562,16 @@ IGraphTransformer::TStatus PgOpWrapper(const TExprNode::TPtr& input, TExprNode::
454
562
switch (oper.Kind ) {
455
563
case NPg::EOperKind::LeftUnary:
456
564
if (IsCastRequired (argTypes[0 ], oper.RightType )) {
457
- children[1 ] = WrapWithPgCast (std::move (children[1 ]), oper.RightType , ctx);
565
+ children[1 ] = WrapWithPgCast (std::move (children[1 ]), oper.RightType , ctx. Expr );
458
566
}
459
567
break ;
460
568
461
569
case NYql::NPg::EOperKind::Binary:
462
570
if (IsCastRequired (argTypes[0 ], oper.LeftType )) {
463
- children[1 ] = WrapWithPgCast (std::move (children[1 ]), oper.LeftType , ctx);
571
+ children[1 ] = WrapWithPgCast (std::move (children[1 ]), oper.LeftType , ctx. Expr );
464
572
}
465
573
if (IsCastRequired (argTypes[1 ], oper.RightType )) {
466
- children[2 ] = WrapWithPgCast (std::move (children[2 ]), oper.RightType , ctx);
574
+ children[2 ] = WrapWithPgCast (std::move (children[2 ]), oper.RightType , ctx. Expr );
467
575
}
468
576
break ;
469
577
@@ -648,7 +756,7 @@ IGraphTransformer::TStatus PgAggWrapper(const TExprNode::TPtr& input, TExprNode:
648
756
for (ui32 i = 0 ; i < argTypes.size (); ++i, ++argIdx) {
649
757
if (IsCastRequired (argTypes[i], aggDesc.ArgTypes [i])) {
650
758
auto & argNode = input->ChildRef (argIdx);
651
- argNode = WrapWithPgCast (std::move (argNode), aggDesc.ArgTypes [i], ctx);
759
+ argNode = WrapWithPgCast (std::move (argNode), aggDesc.ArgTypes [i], ctx. Expr );
652
760
needRetype = true ;
653
761
}
654
762
}
@@ -4155,7 +4263,7 @@ IGraphTransformer::TStatus PgValuesListWrapper(const TExprNode::TPtr& input, TEx
4155
4263
if (item->GetTypeAnn ()->Cast <TPgExprType>()->GetId () == commonTypes[j]) {
4156
4264
rowValues.push_back (item);
4157
4265
} else {
4158
- rowValues.push_back (WrapWithPgCast (std::move (item), commonTypes[j], ctx));
4266
+ rowValues.push_back (WrapWithPgCast (std::move (item), commonTypes[j], ctx. Expr ));
4159
4267
}
4160
4268
}
4161
4269
resultValues.push_back (ctx.Expr .NewList (value->Pos (), std::move (rowValues)));
@@ -4338,7 +4446,11 @@ IGraphTransformer::TStatus PgSelectWrapper(const TExprNode::TPtr& input, TExprNo
4338
4446
4339
4447
TColumnOrder resultColumnOrder;
4340
4448
const TStructExprType* resultStructType = nullptr ;
4341
- auto status = InferPositionalUnionType (input->Pos (), setItems->ChildrenList (), resultColumnOrder, resultStructType, ctx);
4449
+
4450
+ auto status = (1 == setItems->ChildrenSize () && HasSetting (*setItems->Child (0 )->Child (0 ), " unknowns_allowed" ))
4451
+ ? InferPositionalUnionType (input->Pos (), setItems->ChildrenList (), resultColumnOrder, resultStructType, ctx)
4452
+ : InferPgCommonType (input->Pos (), setItems, setOps, resultColumnOrder, resultStructType, ctx);
4453
+
4342
4454
if (status != IGraphTransformer::TStatus::Ok) {
4343
4455
return status;
4344
4456
}
@@ -4471,7 +4583,7 @@ IGraphTransformer::TStatus PgArrayWrapper(const TExprNode::TPtr& input, TExprNod
4471
4583
if (argTypes[i] == elemType) {
4472
4584
castArrayElems.push_back (child);
4473
4585
} else {
4474
- castArrayElems.push_back (WrapWithPgCast (std::move (child), elemType, ctx));
4586
+ castArrayElems.push_back (WrapWithPgCast (std::move (child), elemType, ctx. Expr ));
4475
4587
}
4476
4588
}
4477
4589
output = ctx.Expr .NewCallable (input->Pos (), " PgArray" , std::move (castArrayElems));
@@ -4587,7 +4699,7 @@ IGraphTransformer::TStatus PgLikeWrapper(const TExprNode::TPtr& input, TExprNode
4587
4699
if (argTypes[i] != textTypeId) {
4588
4700
if (argTypes[i] == NPg::UnknownOid) {
4589
4701
auto & argNode = input->ChildRef (i);
4590
- argNode = WrapWithPgCast (std::move (argNode), textTypeId, ctx);
4702
+ argNode = WrapWithPgCast (std::move (argNode), textTypeId, ctx. Expr );
4591
4703
return IGraphTransformer::TStatus::Repeat;
4592
4704
}
4593
4705
ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (input->Pos ()),
@@ -4656,7 +4768,7 @@ IGraphTransformer::TStatus PgInWrapper(const TExprNode::TPtr& input, TExprNode::
4656
4768
if (itemTypePg && inputTypePg && itemTypePg != inputTypePg) {
4657
4769
if (inputTypePg == NPg::UnknownOid) {
4658
4770
4659
- input->ChildRef (0 ) = WrapWithPgCast (std::move (input->Child (0 )), itemTypePg, ctx);
4771
+ input->ChildRef (0 ) = WrapWithPgCast (std::move (input->Child (0 )), itemTypePg, ctx. Expr );
4660
4772
return IGraphTransformer::TStatus::Repeat;
4661
4773
}
4662
4774
if (itemTypePg == NPg::UnknownOid) {
0 commit comments