typesql-cli 0.18.3 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/code-generator2.d.ts.map +1 -1
- package/code-generator2.js +12 -1
- package/code-generator2.js.map +1 -1
- package/dialects/postgres.d.ts.map +1 -1
- package/dialects/postgres.js +5 -0
- package/dialects/postgres.js.map +1 -1
- package/drivers/postgres.d.ts +2 -0
- package/drivers/postgres.d.ts.map +1 -1
- package/drivers/postgres.js +21 -0
- package/drivers/postgres.js.map +1 -1
- package/drivers/types.d.ts +2 -0
- package/drivers/types.d.ts.map +1 -1
- package/mysql-query-analyzer/select-columns.d.ts +1 -0
- package/mysql-query-analyzer/select-columns.d.ts.map +1 -1
- package/mysql-query-analyzer/select-columns.js +13 -0
- package/mysql-query-analyzer/select-columns.js.map +1 -1
- package/package.json +1 -1
- package/postgres-query-analyzer/describe.d.ts.map +1 -1
- package/postgres-query-analyzer/describe.js +5 -4
- package/postgres-query-analyzer/describe.js.map +1 -1
- package/postgres-query-analyzer/parser.d.ts +3 -2
- package/postgres-query-analyzer/parser.d.ts.map +1 -1
- package/postgres-query-analyzer/parser.js +19 -5
- package/postgres-query-analyzer/parser.js.map +1 -1
- package/postgres-query-analyzer/traverse.d.ts +17 -6
- package/postgres-query-analyzer/traverse.d.ts.map +1 -1
- package/postgres-query-analyzer/traverse.js +290 -129
- package/postgres-query-analyzer/traverse.js.map +1 -1
- package/postgres-query-analyzer/types.d.ts +8 -0
- package/postgres-query-analyzer/types.d.ts.map +1 -1
- package/sqlite-query-analyzer/types.d.ts +6 -2
- package/sqlite-query-analyzer/types.d.ts.map +1 -1
@@ -2,21 +2,22 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.defaultOptions = defaultOptions;
|
4
4
|
exports.traverseSmt = traverseSmt;
|
5
|
+
exports.parseReturnType = parseReturnType;
|
5
6
|
const PostgreSQLParser_1 = require("@wsporto/typesql-parser/postgres/PostgreSQLParser");
|
6
7
|
const typesql_parser_1 = require("@wsporto/typesql-parser");
|
7
8
|
const select_columns_1 = require("../mysql-query-analyzer/select-columns");
|
9
|
+
const postgres_1 = require("@wsporto/typesql-parser/postgres");
|
8
10
|
function defaultOptions() {
|
9
11
|
return {
|
10
12
|
collectNestedInfo: false,
|
11
13
|
collectDynamicQueryInfo: false
|
12
14
|
};
|
13
15
|
}
|
14
|
-
function traverseSmt(stmt, dbSchema, checkConstraints, options) {
|
16
|
+
function traverseSmt(stmt, dbSchema, checkConstraints, userFunctions, options) {
|
15
17
|
const { collectNestedInfo = false, collectDynamicQueryInfo = false } = options;
|
16
18
|
const traverseResult = {
|
17
19
|
columnsNullability: [],
|
18
|
-
parameters: []
|
19
|
-
singleRow: false
|
20
|
+
parameters: []
|
20
21
|
};
|
21
22
|
if (collectNestedInfo) {
|
22
23
|
traverseResult.relations = [];
|
@@ -35,7 +36,10 @@ function traverseSmt(stmt, dbSchema, checkConstraints, options) {
|
|
35
36
|
collectNestedInfo,
|
36
37
|
collectDynamicQueryInfo,
|
37
38
|
fromColumns: [],
|
38
|
-
|
39
|
+
parentColumns: [],
|
40
|
+
withColumns: [],
|
41
|
+
checkConstraints,
|
42
|
+
userFunctions
|
39
43
|
};
|
40
44
|
const selectstmt = stmt.selectstmt();
|
41
45
|
if (selectstmt) {
|
@@ -82,15 +86,15 @@ function getInParameterList(ctx) {
|
|
82
86
|
}
|
83
87
|
function traverseSelectstmt(selectstmt, context, traverseResult) {
|
84
88
|
const paramIsListResult = getInParameterList(selectstmt);
|
85
|
-
const
|
89
|
+
const selectResult = traverse_selectstmt(selectstmt, context, traverseResult);
|
86
90
|
//select parameters are collected after from paramters
|
87
91
|
traverseResult.parameters.sort((param1, param2) => param1.paramIndex - param2.paramIndex);
|
88
|
-
const multipleRowsResult = !isSingleRowResult(selectstmt,
|
92
|
+
const multipleRowsResult = !(selectResult.singleRow || isSingleRowResult(selectstmt, selectResult.columns));
|
89
93
|
const limit = checkLimit(selectstmt);
|
90
94
|
const postgresTraverseResult = {
|
91
95
|
queryType: 'Select',
|
92
96
|
multipleRowsResult,
|
93
|
-
columns,
|
97
|
+
columns: selectResult.columns,
|
94
98
|
parametersNullability: traverseResult.parameters.map(param => (Object.assign({ isNotNull: param.isNotNull }, addConstraintIfNotNull(param.checkConstraint)))),
|
95
99
|
parameterList: paramIsListResult,
|
96
100
|
limit
|
@@ -108,22 +112,23 @@ function traverse_selectstmt(selectstmt, context, traverseResult) {
|
|
108
112
|
if (select_no_parens) {
|
109
113
|
return traverse_select_no_parens(select_no_parens, context, traverseResult);
|
110
114
|
}
|
111
|
-
|
115
|
+
//select_with_parens
|
116
|
+
return {
|
117
|
+
columns: [],
|
118
|
+
singleRow: true
|
119
|
+
};
|
112
120
|
}
|
113
121
|
function traverse_select_no_parens(select_no_parens, context, traverseResult) {
|
114
|
-
let withColumns = [];
|
115
122
|
const with_clause = select_no_parens.with_clause();
|
116
123
|
if (with_clause) {
|
117
124
|
with_clause.cte_list().common_table_expr_list()
|
118
125
|
.forEach(common_table_expr => {
|
119
|
-
const
|
120
|
-
|
121
|
-
withColumns.push(...withResult);
|
126
|
+
const withResult = traverse_common_table_expr(common_table_expr, context, traverseResult);
|
127
|
+
context.withColumns.push(...withResult);
|
122
128
|
});
|
123
129
|
}
|
124
130
|
const select_clause = select_no_parens.select_clause();
|
125
|
-
const
|
126
|
-
const selectResult = traverse_select_clause(select_clause, newContext, traverseResult);
|
131
|
+
const selectResult = traverse_select_clause(select_clause, context, traverseResult);
|
127
132
|
const select_limit = select_no_parens.select_limit();
|
128
133
|
if (select_limit) {
|
129
134
|
const numParamsBefore = traverseResult.parameters.length;
|
@@ -159,8 +164,8 @@ function traverse_common_table_expr(common_table_expr, context, traverseResult)
|
|
159
164
|
const tableName = common_table_expr.name().getText();
|
160
165
|
const select_stmt = common_table_expr.preparablestmt().selectstmt();
|
161
166
|
const numParamsBefore = traverseResult.parameters.length;
|
162
|
-
const
|
163
|
-
const columnsWithTalbeName = columns.map(col => (Object.assign(Object.assign({}, col), { table_name: tableName })));
|
167
|
+
const selectResult = traverse_selectstmt(select_stmt, Object.assign(Object.assign({}, context), { collectDynamicQueryInfo: false }), traverseResult);
|
168
|
+
const columnsWithTalbeName = selectResult.columns.map(col => (Object.assign(Object.assign({}, col), { table_name: tableName })));
|
164
169
|
if (context.collectDynamicQueryInfo) {
|
165
170
|
const parameters = traverseResult.parameters.slice(numParamsBefore).map((_, index) => index + numParamsBefore);
|
166
171
|
(_a = traverseResult.dynamicQueryInfo) === null || _a === void 0 ? void 0 : _a.with.push({
|
@@ -173,45 +178,55 @@ function traverse_common_table_expr(common_table_expr, context, traverseResult)
|
|
173
178
|
}
|
174
179
|
function traverse_select_clause(select_clause, context, traverseResult) {
|
175
180
|
const simple_select_intersect_list = select_clause.simple_select_intersect_list();
|
176
|
-
|
177
|
-
|
178
|
-
selectColumns = traverse_simple_select_intersect(simple_select_intersect_list[0], context, traverseResult);
|
179
|
-
}
|
181
|
+
const mainSelectResult = traverse_simple_select_intersect(simple_select_intersect_list[0], context, traverseResult);
|
182
|
+
let columns = mainSelectResult.columns;
|
180
183
|
//union
|
181
184
|
for (let index = 1; index < simple_select_intersect_list.length; index++) {
|
182
|
-
const
|
183
|
-
|
184
|
-
const col = Object.assign({ column_name: value.column_name, is_nullable: value.is_nullable ||
|
185
|
+
const unionResult = traverse_simple_select_intersect(simple_select_intersect_list[index], context, traverseResult);
|
186
|
+
columns = columns.map((value, columnIndex) => {
|
187
|
+
const col = Object.assign({ column_name: value.column_name, is_nullable: value.is_nullable || unionResult.columns[columnIndex].is_nullable, table_name: '', table_schema: '', type: value.type }, (value.column_default && { column_default: value.column_default }));
|
185
188
|
return col;
|
186
189
|
});
|
187
190
|
}
|
188
|
-
return
|
191
|
+
return {
|
192
|
+
columns,
|
193
|
+
singleRow: simple_select_intersect_list.length == 1 ? mainSelectResult.singleRow : false
|
194
|
+
};
|
189
195
|
}
|
190
196
|
function traverse_simple_select_intersect(simple_select_intersect, context, traverseResult) {
|
191
197
|
const simple_select_pramary = simple_select_intersect.simple_select_pramary_list()[0];
|
192
198
|
if (simple_select_pramary) {
|
193
199
|
return traverse_simple_select_pramary(simple_select_pramary, context, traverseResult);
|
194
200
|
}
|
195
|
-
return
|
201
|
+
return {
|
202
|
+
columns: [],
|
203
|
+
singleRow: true
|
204
|
+
};
|
196
205
|
}
|
197
206
|
function traverse_simple_select_pramary(simple_select_pramary, context, traverseResult) {
|
198
207
|
var _a, _b, _c, _d, _e;
|
199
|
-
|
208
|
+
let fromResult = {
|
209
|
+
columns: [],
|
210
|
+
singleRow: false
|
211
|
+
};
|
200
212
|
const from_clause = simple_select_pramary.from_clause();
|
201
213
|
if (from_clause) {
|
202
214
|
const where_clause = simple_select_pramary.where_clause();
|
203
|
-
|
204
|
-
|
205
|
-
fromColumns.push(...fieldsNotNull);
|
215
|
+
fromResult = traverse_from_clause(from_clause, context, traverseResult);
|
216
|
+
fromResult.columns = where_clause != null ? fromResult.columns.map(field => checkIsNullable(where_clause, field)) : fromResult.columns;
|
206
217
|
}
|
207
218
|
const values_clause = simple_select_pramary.values_clause();
|
208
219
|
if (values_clause) {
|
209
220
|
const valuesColumns = traverse_values_clause(values_clause, context, traverseResult);
|
210
|
-
return
|
221
|
+
return {
|
222
|
+
columns: valuesColumns,
|
223
|
+
singleRow: false
|
224
|
+
};
|
211
225
|
}
|
212
226
|
const where_a_expr = (_a = simple_select_pramary.where_clause()) === null || _a === void 0 ? void 0 : _a.a_expr();
|
213
227
|
//fromColumns has precedence
|
214
|
-
|
228
|
+
//context.fromColumns only becase of insert. update
|
229
|
+
const newContext = Object.assign(Object.assign({}, context), { fromColumns: [...context.fromColumns, ...fromResult.columns, ...context.parentColumns] });
|
215
230
|
if (where_a_expr) {
|
216
231
|
const numParamsBefore = traverseResult.parameters.length;
|
217
232
|
traverse_a_expr(where_a_expr, newContext, traverseResult);
|
@@ -236,7 +251,10 @@ function traverse_simple_select_pramary(simple_select_pramary, context, traverse
|
|
236
251
|
traverse_a_expr(having_expr, newContext, traverseResult);
|
237
252
|
}
|
238
253
|
const filteredColumns = filterColumns_simple_select_pramary(simple_select_pramary, newContext, traverseResult);
|
239
|
-
return
|
254
|
+
return {
|
255
|
+
columns: filteredColumns,
|
256
|
+
singleRow: fromResult.singleRow
|
257
|
+
};
|
240
258
|
}
|
241
259
|
function extractRelations(a_expr) {
|
242
260
|
const columnsRef = collectContextsOfType(a_expr, PostgreSQLParser_1.ColumnrefContext);
|
@@ -340,7 +358,7 @@ function traverse_target_el(target_el, context, traverseResult) {
|
|
340
358
|
parameters
|
341
359
|
});
|
342
360
|
}
|
343
|
-
return Object.assign({ column_name: alias || exprResult.column_name, is_nullable: exprResult.is_nullable && exprResult.column_default !== true, table_name: exprResult.table_name, table_schema: exprResult.table_schema, type: exprResult.type }, (exprResult.jsonType != null && { jsonType: exprResult.jsonType }));
|
361
|
+
return Object.assign(Object.assign({ column_name: alias || exprResult.column_name, is_nullable: exprResult.is_nullable && exprResult.column_default !== true, table_name: exprResult.table_name, table_schema: exprResult.table_schema, type: exprResult.type }, (exprResult.column_key != null && { column_key: exprResult.column_key })), (exprResult.jsonType != null && { jsonType: exprResult.jsonType }));
|
344
362
|
}
|
345
363
|
throw Error('Column not found');
|
346
364
|
}
|
@@ -470,6 +488,7 @@ function traverse_expr_is_not(a_expr_is_not, context, traverseResult) {
|
|
470
488
|
const result = traverse_expr_compare(a_expr_compare, context, traverseResult);
|
471
489
|
if (a_expr_is_not.IS() && a_expr_is_not.NULL_P()) {
|
472
490
|
checkParamterNullability(result, traverseResult);
|
491
|
+
return Object.assign(Object.assign({}, result), { is_nullable: false });
|
473
492
|
}
|
474
493
|
return result;
|
475
494
|
}
|
@@ -518,10 +537,10 @@ function traverse_expr_compare(a_expr_compare, context, traverseResult) {
|
|
518
537
|
const result = traverse_select_with_parens(select_with_parens, context, traverseResult);
|
519
538
|
return {
|
520
539
|
column_name: '?column?',
|
521
|
-
is_nullable: result.some(col => col.is_nullable),
|
540
|
+
is_nullable: result.columns.some(col => col.is_nullable),
|
522
541
|
table_name: '',
|
523
542
|
table_schema: '',
|
524
|
-
type: result[0].type
|
543
|
+
type: result.columns[0].type
|
525
544
|
};
|
526
545
|
}
|
527
546
|
const a_expr = a_expr_compare.a_expr();
|
@@ -710,7 +729,7 @@ function getNameAndTypeIdFromAExprConst(a_expr_const) {
|
|
710
729
|
if (a_expr_const.NULL_P()) {
|
711
730
|
return {
|
712
731
|
name: a_expr_const.getText(),
|
713
|
-
type: '
|
732
|
+
type: 'null'
|
714
733
|
};
|
715
734
|
}
|
716
735
|
return {
|
@@ -742,12 +761,15 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
742
761
|
const columnref = c_expr.columnref();
|
743
762
|
if (columnref) {
|
744
763
|
if (context.columnRefIsRecord) {
|
764
|
+
const table = (0, select_columns_1.splitTableName)(columnref.getText());
|
765
|
+
const columns = filterColumns(context.fromColumns, table);
|
745
766
|
return {
|
746
767
|
column_name: columnref.getText(),
|
747
768
|
is_nullable: false,
|
748
769
|
table_name: '',
|
749
770
|
table_schema: '',
|
750
|
-
type: '
|
771
|
+
type: 'record',
|
772
|
+
recordTypes: columns
|
751
773
|
};
|
752
774
|
}
|
753
775
|
else {
|
@@ -782,6 +804,7 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
782
804
|
}
|
783
805
|
const fun_expr = c_expr.func_expr();
|
784
806
|
if (fun_expr) {
|
807
|
+
context.columnRefIsRecord = undefined;
|
785
808
|
const func_application = fun_expr.func_application();
|
786
809
|
if (func_application) {
|
787
810
|
if (is_json_build_object_func(func_application)) {
|
@@ -807,14 +830,14 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
807
830
|
}
|
808
831
|
const select_with_parens = c_expr.select_with_parens();
|
809
832
|
if (select_with_parens) {
|
810
|
-
const result = traverse_select_with_parens(select_with_parens, context, traverseResult);
|
833
|
+
const result = traverse_select_with_parens(select_with_parens, Object.assign(Object.assign({}, context), { parentColumns: context.fromColumns, fromColumns: [] }), traverseResult);
|
811
834
|
return {
|
812
835
|
column_name: '?column?',
|
813
|
-
is_nullable: true,
|
836
|
+
is_nullable: result.columns[0].jsonType ? result.columns[0].is_nullable : true,
|
814
837
|
table_name: '',
|
815
838
|
table_schema: '',
|
816
|
-
type: result[0].type,
|
817
|
-
jsonType: result[0].jsonType
|
839
|
+
type: result.columns[0].type,
|
840
|
+
jsonType: result.columns[0].jsonType
|
818
841
|
};
|
819
842
|
}
|
820
843
|
const a_expr_in_parens = c_expr._a_expr_in_parens;
|
@@ -830,8 +853,8 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
830
853
|
is_nullable: expr_list.some(col => col.is_nullable),
|
831
854
|
table_name: '',
|
832
855
|
table_schema: '',
|
833
|
-
type: '
|
834
|
-
recordTypes: expr_list.map(
|
856
|
+
type: 'record',
|
857
|
+
recordTypes: expr_list.map(expr => (Object.assign(Object.assign({}, expr), { column_name: '' })))
|
835
858
|
};
|
836
859
|
}
|
837
860
|
const implicit_row = c_expr.implicit_row();
|
@@ -867,7 +890,7 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
867
890
|
function filterColumns(fromColumns, fieldName) {
|
868
891
|
return fromColumns.filter(col => (fieldName.prefix === '' || col.table_name === fieldName.prefix)
|
869
892
|
&& (fieldName.name === '*' || col.column_name === fieldName.name)).map(col => {
|
870
|
-
const result = Object.assign({ column_name: col.column_name, is_nullable: col.is_nullable, table_name: col.table_name, table_schema: col.table_schema, type: col.type }, (col.original_is_nullable !== undefined && { original_is_nullable: col.original_is_nullable }));
|
893
|
+
const result = Object.assign(Object.assign(Object.assign({ column_name: col.column_name, is_nullable: col.is_nullable, table_name: col.table_name, table_schema: col.table_schema, type: col.type }, (col.column_key !== undefined) && { column_key: col.column_key }), (col.jsonType !== undefined) && { jsonType: col.jsonType }), (col.original_is_nullable !== undefined && { original_is_nullable: col.original_is_nullable }));
|
871
894
|
return result;
|
872
895
|
});
|
873
896
|
}
|
@@ -884,22 +907,33 @@ function traversec_expr_case(c_expr_case, context, traverseResult) {
|
|
884
907
|
const whenResult = case_expr.when_clause_list().when_clause_list().map(when_clause => traversewhen_clause(when_clause, context, traverseResult));
|
885
908
|
const whenIsNotNull = whenResult.every(when => when);
|
886
909
|
const elseExpr = (_a = case_expr.case_default()) === null || _a === void 0 ? void 0 : _a.a_expr();
|
887
|
-
const
|
910
|
+
const elseResult = elseExpr ? traverse_a_expr(elseExpr, Object.assign({}, context), traverseResult) : null;
|
911
|
+
const elseIsNotNull = (elseResult === null || elseResult === void 0 ? void 0 : elseResult.is_nullable) === false || false;
|
888
912
|
const notNull = elseIsNotNull && whenIsNotNull;
|
889
913
|
return {
|
890
914
|
column_name: '?column?',
|
891
915
|
is_nullable: !notNull,
|
892
916
|
table_name: '',
|
893
917
|
table_schema: '',
|
894
|
-
type: (_b = whenResult[0].type) !== null && _b !== void 0 ? _b : 'unknown'
|
918
|
+
type: (_b = whenResult[0].type) !== null && _b !== void 0 ? _b : 'unknown',
|
919
|
+
jsonType: allJsonTypesMatch(whenResult, elseResult) ? whenResult[0].jsonType : undefined
|
895
920
|
};
|
896
921
|
}
|
922
|
+
function allJsonTypesMatch(whenResultList, elseResult) {
|
923
|
+
var _a;
|
924
|
+
const firstType = (_a = whenResultList[0]) === null || _a === void 0 ? void 0 : _a.jsonType;
|
925
|
+
const allMatch = whenResultList.every(res => {
|
926
|
+
const match = res.jsonType == firstType;
|
927
|
+
return match;
|
928
|
+
}) && ((elseResult === null || elseResult === void 0 ? void 0 : elseResult.type) === 'null' || (elseResult === null || elseResult === void 0 ? void 0 : elseResult.jsonType) == firstType);
|
929
|
+
return allMatch;
|
930
|
+
}
|
897
931
|
function traversewhen_clause(when_clause, context, traverseResult) {
|
898
932
|
const a_expr_list = when_clause.a_expr_list();
|
899
933
|
const [whenExprList, thenExprList] = partition(a_expr_list, (index) => index % 2 === 0);
|
900
934
|
const whenExprResult = thenExprList.map((thenExpr, index) => {
|
901
935
|
traverse_a_expr(whenExprList[index], context, traverseResult);
|
902
|
-
const thenExprResult = traverse_a_expr(thenExpr, context, traverseResult);
|
936
|
+
const thenExprResult = traverse_a_expr(thenExpr, Object.assign(Object.assign({}, context), { filter_expr: whenExprList[index] }), traverseResult);
|
903
937
|
return thenExprResult;
|
904
938
|
});
|
905
939
|
const notNull = whenExprResult.every(res => res);
|
@@ -908,7 +942,8 @@ function traversewhen_clause(when_clause, context, traverseResult) {
|
|
908
942
|
is_nullable: !notNull,
|
909
943
|
table_name: '',
|
910
944
|
table_schema: '',
|
911
|
-
type: whenExprResult[0].type
|
945
|
+
type: whenExprResult[0].type,
|
946
|
+
jsonType: whenExprResult[0].jsonType
|
912
947
|
};
|
913
948
|
}
|
914
949
|
function partition(array, predicate) {
|
@@ -952,14 +987,9 @@ function mapJsonBuildArgsToJsonProperty(args, filterExpr) {
|
|
952
987
|
return properties;
|
953
988
|
}
|
954
989
|
function inferJsonNullability(columns, filterExpr) {
|
955
|
-
const
|
990
|
+
const tables = columns.filter(col => filterExpr && col.original_is_nullable === false && isNotNull_a_expr(col, filterExpr)).map(col => col.table_name);
|
956
991
|
const fields = columns.map(col => {
|
957
|
-
|
958
|
-
return col.original_is_nullable != null ? !col.original_is_nullable : Boolean(filterExpr && isNotNull_a_expr(col, filterExpr));
|
959
|
-
}
|
960
|
-
else {
|
961
|
-
return !col.is_nullable || Boolean(filterExpr && isNotNull_a_expr(col, filterExpr));
|
962
|
-
}
|
992
|
+
return col.original_is_nullable != null && tables.includes(col.table_name) ? !col.original_is_nullable : !col.is_nullable;
|
963
993
|
});
|
964
994
|
return fields;
|
965
995
|
}
|
@@ -986,9 +1016,9 @@ function traverse_json_build_obj_func(func_application, context, traverseResult)
|
|
986
1016
|
const columnName = ((_a = func_application.func_name()) === null || _a === void 0 ? void 0 : _a.getText()) || func_application.getText();
|
987
1017
|
const func_arg_expr_list = ((_b = func_application.func_arg_list()) === null || _b === void 0 ? void 0 : _b.func_arg_expr_list()) || [];
|
988
1018
|
const argsResult = func_arg_expr_list.map(func_arg_expr => traversefunc_arg_expr(func_arg_expr, context, traverseResult));
|
989
|
-
|
1019
|
+
const result = {
|
990
1020
|
column_name: columnName,
|
991
|
-
is_nullable:
|
1021
|
+
is_nullable: false,
|
992
1022
|
table_name: '',
|
993
1023
|
table_schema: '',
|
994
1024
|
type: 'json',
|
@@ -997,12 +1027,13 @@ function traverse_json_build_obj_func(func_application, context, traverseResult)
|
|
997
1027
|
properties: mapJsonBuildArgsToJsonProperty(argsResult, context.filter_expr),
|
998
1028
|
}
|
999
1029
|
};
|
1030
|
+
return result;
|
1000
1031
|
}
|
1001
1032
|
function traverse_json_agg(func_application, context, traverseResult) {
|
1002
1033
|
var _a, _b;
|
1003
1034
|
const columnName = ((_a = func_application.func_name()) === null || _a === void 0 ? void 0 : _a.getText()) || func_application.getText();
|
1004
1035
|
const func_arg_expr_list = ((_b = func_application.func_arg_list()) === null || _b === void 0 ? void 0 : _b.func_arg_expr_list()) || [];
|
1005
|
-
const argsResult = func_arg_expr_list.map(func_arg_expr => traversefunc_arg_expr(func_arg_expr, context, traverseResult));
|
1036
|
+
const argsResult = func_arg_expr_list.map(func_arg_expr => traversefunc_arg_expr(func_arg_expr, Object.assign(Object.assign({}, context), { columnRefIsRecord: true }), traverseResult));
|
1006
1037
|
const result = {
|
1007
1038
|
column_name: columnName,
|
1008
1039
|
is_nullable: context.filter_expr != null,
|
@@ -1011,11 +1042,24 @@ function traverse_json_agg(func_application, context, traverseResult) {
|
|
1011
1042
|
type: 'json[]',
|
1012
1043
|
jsonType: {
|
1013
1044
|
name: 'json[]',
|
1014
|
-
properties: argsResult
|
1045
|
+
properties: createJsonTypeForJsonAgg(argsResult[0], context.filter_expr)
|
1015
1046
|
}
|
1016
1047
|
};
|
1017
1048
|
return result;
|
1018
1049
|
}
|
1050
|
+
function createJsonTypeForJsonAgg(arg, filter_expr) {
|
1051
|
+
if (arg.recordTypes) {
|
1052
|
+
const jsonType = mapRecordsToJsonType(arg.recordTypes, filter_expr);
|
1053
|
+
return [jsonType];
|
1054
|
+
}
|
1055
|
+
return [arg.jsonType || { name: 'json_field', type: arg.type, notNull: !arg.is_nullable }];
|
1056
|
+
}
|
1057
|
+
function mapRecordsToJsonType(recordTypes, filterExpr) {
|
1058
|
+
const jsonNullability = inferJsonNullability(recordTypes, filterExpr);
|
1059
|
+
const fields = recordTypes.map((col, index) => ({ name: col.column_name ? col.column_name : `f${index + 1}`, type: col.type, notNull: jsonNullability[index] }));
|
1060
|
+
const jsonType = transformFieldsToJsonObjType(fields);
|
1061
|
+
return jsonType;
|
1062
|
+
}
|
1019
1063
|
function traversefunc_application(func_application, context, traverseResult) {
|
1020
1064
|
var _a;
|
1021
1065
|
const functionName = getFunctionName(func_application);
|
@@ -1023,22 +1067,7 @@ function traversefunc_application(func_application, context, traverseResult) {
|
|
1023
1067
|
if (functionName === 'row_to_json') {
|
1024
1068
|
const argResult = traversefunc_arg_expr(func_arg_expr_list[0], Object.assign(Object.assign({}, context), { columnRefIsRecord: true }), traverseResult);
|
1025
1069
|
if (argResult.recordTypes) {
|
1026
|
-
const
|
1027
|
-
const jsonType = transformFieldsToJsonObjType(fields);
|
1028
|
-
return {
|
1029
|
-
column_name: functionName,
|
1030
|
-
is_nullable: false,
|
1031
|
-
table_name: '',
|
1032
|
-
table_schema: '',
|
1033
|
-
type: 'json',
|
1034
|
-
jsonType
|
1035
|
-
};
|
1036
|
-
}
|
1037
|
-
else {
|
1038
|
-
const columns = filterColumns(context.fromColumns, { name: '*', prefix: argResult.column_name });
|
1039
|
-
const jsonNullability = inferJsonNullability(columns, context.filter_expr);
|
1040
|
-
const fields = columns.map((col, index) => ({ name: col.column_name, type: col.type, notNull: jsonNullability[index] }));
|
1041
|
-
const jsonType = transformFieldsToJsonObjType(fields);
|
1070
|
+
const jsonType = mapRecordsToJsonType(argResult.recordTypes, context.filter_expr);
|
1042
1071
|
return {
|
1043
1072
|
column_name: functionName,
|
1044
1073
|
is_nullable: false,
|
@@ -1170,6 +1199,19 @@ function traversefunc_application(func_application, context, traverseResult) {
|
|
1170
1199
|
if (functionName === 'sum') {
|
1171
1200
|
return Object.assign(Object.assign({}, argsResult[0]), { column_name: functionName, is_nullable: true, type: argsResult[0].type ? mapSumType(argsResult[0].type) : 'unknown' });
|
1172
1201
|
}
|
1202
|
+
if (functionName === 'json_object_agg') {
|
1203
|
+
return {
|
1204
|
+
column_name: functionName,
|
1205
|
+
is_nullable: false,
|
1206
|
+
table_name: '',
|
1207
|
+
table_schema: '',
|
1208
|
+
type: 'json',
|
1209
|
+
jsonType: {
|
1210
|
+
name: 'json_map',
|
1211
|
+
type: argsResult[1].jsonType || { name: 'json_field', type: argsResult[1].type, notNull: !argsResult[1].is_nullable }
|
1212
|
+
}
|
1213
|
+
};
|
1214
|
+
}
|
1173
1215
|
return {
|
1174
1216
|
column_name: functionName,
|
1175
1217
|
is_nullable: true,
|
@@ -1268,27 +1310,40 @@ function checkIsNullable(where_clause, field) {
|
|
1268
1310
|
function traverse_from_clause(from_clause, context, traverseResult) {
|
1269
1311
|
const from_list = from_clause.from_list();
|
1270
1312
|
if (from_list) {
|
1271
|
-
|
1313
|
+
const fromListResult = traverse_from_list(from_list, context, traverseResult);
|
1314
|
+
return fromListResult;
|
1272
1315
|
}
|
1273
|
-
return
|
1316
|
+
return {
|
1317
|
+
columns: [],
|
1318
|
+
singleRow: false
|
1319
|
+
};
|
1274
1320
|
}
|
1275
1321
|
function traverse_from_list(from_list, context, traverseResult) {
|
1276
|
-
const
|
1277
|
-
|
1322
|
+
const fromListResult = from_list.table_ref_list().map(table_ref => traverse_table_ref(table_ref, context, traverseResult));
|
1323
|
+
const columns = fromListResult.flatMap(tableRes => tableRes.columns);
|
1324
|
+
return {
|
1325
|
+
columns: columns,
|
1326
|
+
singleRow: fromListResult.length === 1 ? fromListResult[0].singleRow : false
|
1327
|
+
};
|
1328
|
+
}
|
1329
|
+
function getFromColumns(tableName, withColumns, dbSchema) {
|
1330
|
+
const filteredWithColumns = withColumns.filter(col => col.table_name.toLowerCase() === tableName.name.toLowerCase());
|
1331
|
+
const filteredSchema = filteredWithColumns.length > 0 ? filteredWithColumns : dbSchema.filter(col => col.table_name.toLowerCase() === tableName.name.toLowerCase());
|
1332
|
+
return filteredSchema;
|
1278
1333
|
}
|
1279
1334
|
function traverse_table_ref(table_ref, context, traverseResult) {
|
1280
|
-
var _a, _b, _c, _d;
|
1281
|
-
const { fromColumns, dbSchema } = context;
|
1335
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
1282
1336
|
const allColumns = [];
|
1283
1337
|
const relation_expr = table_ref.relation_expr();
|
1284
1338
|
const aliasClause = table_ref.alias_clause();
|
1285
1339
|
const aliasNameList = (_b = (_a = aliasClause === null || aliasClause === void 0 ? void 0 : aliasClause.name_list()) === null || _a === void 0 ? void 0 : _a.name_list()) === null || _b === void 0 ? void 0 : _b.map(name => name.getText());
|
1286
1340
|
const alias = aliasClause ? aliasClause.colid().getText() : '';
|
1287
1341
|
if (relation_expr) {
|
1288
|
-
const tableName = traverse_relation_expr(relation_expr
|
1342
|
+
const tableName = traverse_relation_expr(relation_expr);
|
1343
|
+
const fromColumns = getFromColumns(tableName, context.withColumns, context.dbSchema);
|
1289
1344
|
const tableNameWithAlias = alias ? alias : tableName.name;
|
1290
|
-
const
|
1291
|
-
|
1345
|
+
const columnsWithAlias = fromColumns.map(col => (Object.assign(Object.assign({}, col), { table_name: tableNameWithAlias.toLowerCase() })));
|
1346
|
+
const fromColumnsResult = columnsWithAlias.concat(context.parentColumns);
|
1292
1347
|
allColumns.push(...fromColumnsResult);
|
1293
1348
|
if (context.collectNestedInfo) {
|
1294
1349
|
const key = fromColumnsResult.filter(col => col.column_key === 'PRI');
|
@@ -1304,47 +1359,78 @@ function traverse_table_ref(table_ref, context, traverseResult) {
|
|
1304
1359
|
};
|
1305
1360
|
(_d = traverseResult.relations) === null || _d === void 0 ? void 0 : _d.push(relation);
|
1306
1361
|
}
|
1307
|
-
const table_ref_list = table_ref.table_ref_list();
|
1308
|
-
const join_type_list = table_ref.join_type_list();
|
1309
|
-
const join_qual_list = table_ref.join_qual_list();
|
1310
1362
|
if (context.collectDynamicQueryInfo && traverseResult.dynamicQueryInfo.from.length == 0) {
|
1311
1363
|
collectDynamicQueryInfoTableRef(table_ref, null, null, fromColumnsResult, [], traverseResult);
|
1312
1364
|
}
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1365
|
+
const joinList = extractJoins(table_ref);
|
1366
|
+
const joinColumns = joinList.flatMap((join) => {
|
1367
|
+
const joinType = join.joinType; //INNER, LEFT
|
1368
|
+
const joinQual = join.joinQual;
|
1369
|
+
const numParamsBefore = traverseResult.parameters.length;
|
1370
|
+
const joinTableRefResult = traverse_table_ref(join.tableRef, context, traverseResult);
|
1371
|
+
const isLeftJoin = joinType === null || joinType === void 0 ? void 0 : joinType.LEFT();
|
1372
|
+
const filteredColumns = joinQual && (joinQual === null || joinQual === void 0 ? void 0 : joinQual.USING()) ? filterUsingColumns(joinTableRefResult.columns, joinQual) : joinTableRefResult.columns;
|
1373
|
+
const resultColumns = isLeftJoin ? filteredColumns.map(col => (Object.assign(Object.assign({}, col), { is_nullable: true, original_is_nullable: col.is_nullable }))) : filteredColumns;
|
1374
|
+
if (context.collectNestedInfo && joinQual) {
|
1375
|
+
collectNestedInfo(joinQual, resultColumns, traverseResult);
|
1376
|
+
}
|
1377
|
+
if (context.collectDynamicQueryInfo) {
|
1378
|
+
const parameters = traverseResult.parameters.slice(numParamsBefore).map((_, index) => index + numParamsBefore);
|
1379
|
+
collectDynamicQueryInfoTableRef(join.tableRef, joinType, joinQual, resultColumns, parameters, traverseResult);
|
1380
|
+
}
|
1381
|
+
return resultColumns;
|
1382
|
+
});
|
1383
|
+
allColumns.push(...joinColumns);
|
1384
|
+
}
|
1385
|
+
const func_table = table_ref.func_table();
|
1386
|
+
if (func_table) {
|
1387
|
+
const funcAlias = ((_g = (_f = (_e = table_ref.func_alias_clause()) === null || _e === void 0 ? void 0 : _e.alias_clause()) === null || _f === void 0 ? void 0 : _f.colid()) === null || _g === void 0 ? void 0 : _g.getText()) || '';
|
1388
|
+
const result = traverse_func_table(func_table, context, traverseResult);
|
1389
|
+
const resultWithAlias = result.columns.map(col => (Object.assign(Object.assign({}, col), { table_name: funcAlias || col.table_name })));
|
1390
|
+
return {
|
1391
|
+
columns: resultWithAlias,
|
1392
|
+
singleRow: result.singleRow
|
1393
|
+
};
|
1334
1394
|
}
|
1335
1395
|
const select_with_parens = table_ref.select_with_parens();
|
1336
1396
|
if (select_with_parens) {
|
1337
1397
|
const columns = traverse_select_with_parens(select_with_parens, Object.assign(Object.assign({}, context), { collectDynamicQueryInfo: false }), traverseResult);
|
1338
|
-
const withAlias = columns.map((col, i) => ({
|
1398
|
+
const withAlias = columns.columns.map((col, i) => ({
|
1339
1399
|
column_name: (aliasNameList === null || aliasNameList === void 0 ? void 0 : aliasNameList[i]) || col.column_name,
|
1340
1400
|
is_nullable: col.is_nullable,
|
1341
1401
|
table_name: alias || col.table_name,
|
1342
1402
|
table_schema: col.table_schema,
|
1343
1403
|
type: col.type
|
1344
1404
|
}));
|
1345
|
-
return
|
1405
|
+
return {
|
1406
|
+
columns: withAlias,
|
1407
|
+
singleRow: false
|
1408
|
+
};
|
1346
1409
|
}
|
1347
|
-
return
|
1410
|
+
return {
|
1411
|
+
columns: allColumns,
|
1412
|
+
singleRow: false
|
1413
|
+
};
|
1414
|
+
}
|
1415
|
+
function extractJoins(table_ref) {
|
1416
|
+
const joinList = [];
|
1417
|
+
let currentJoinType = null;
|
1418
|
+
for (const child of table_ref.children || []) {
|
1419
|
+
if (child instanceof PostgreSQLParser_1.Join_typeContext) {
|
1420
|
+
currentJoinType = child;
|
1421
|
+
}
|
1422
|
+
if (child instanceof PostgreSQLParser_1.Table_refContext) {
|
1423
|
+
joinList.push({ joinQual: null, joinType: currentJoinType, tableRef: child });
|
1424
|
+
currentJoinType = null;
|
1425
|
+
}
|
1426
|
+
if (child instanceof PostgreSQLParser_1.Join_qualContext) {
|
1427
|
+
const lastJoin = joinList.at(-1);
|
1428
|
+
if (lastJoin) {
|
1429
|
+
lastJoin.joinQual = child;
|
1430
|
+
}
|
1431
|
+
}
|
1432
|
+
}
|
1433
|
+
return joinList;
|
1348
1434
|
}
|
1349
1435
|
function collectDynamicQueryInfoTableRef(table_ref, joinType, joinQual, columns, parameters, traverseResult) {
|
1350
1436
|
var _a, _b;
|
@@ -1414,16 +1500,88 @@ function traverse_select_with_parens(select_with_parens, context, traverseResult
|
|
1414
1500
|
if (select_no_parens) {
|
1415
1501
|
return traverse_select_no_parens(select_no_parens, context, traverseResult);
|
1416
1502
|
}
|
1417
|
-
return
|
1503
|
+
return {
|
1504
|
+
columns: [],
|
1505
|
+
singleRow: false
|
1506
|
+
};
|
1507
|
+
}
|
1508
|
+
function traverse_func_table(func_table, context, traverseResult) {
|
1509
|
+
const func_expr_windowless = func_table.func_expr_windowless();
|
1510
|
+
if (func_expr_windowless) {
|
1511
|
+
const result = traverse_func_expr_windowless(func_expr_windowless, context, traverseResult);
|
1512
|
+
return result;
|
1513
|
+
}
|
1514
|
+
throw Error('Stmt not supported: ' + func_table.getText());
|
1515
|
+
}
|
1516
|
+
function parseReturnType(returnType) {
|
1517
|
+
const trimmed = returnType.trim();
|
1518
|
+
// Handle TABLE(...)
|
1519
|
+
if (trimmed.toLowerCase().startsWith('table(') && trimmed.endsWith(')')) {
|
1520
|
+
const inside = trimmed.slice(6, -1); // remove "TABLE(" and final ")"
|
1521
|
+
const columns = [];
|
1522
|
+
const parts = inside.split(',').map(part => part.trim());
|
1523
|
+
for (const part of parts) {
|
1524
|
+
const match = part.match(/^(\w+)\s+(.+)$/);
|
1525
|
+
if (!match) {
|
1526
|
+
throw new Error(`Invalid column definition: ${part}`);
|
1527
|
+
}
|
1528
|
+
const [, name, type] = match;
|
1529
|
+
columns.push({ name, type });
|
1530
|
+
}
|
1531
|
+
return { kind: 'table', columns };
|
1532
|
+
}
|
1533
|
+
// Handle SETOF typename
|
1534
|
+
const setofMatch = trimmed.match(/^SETOF\s+(\w+)$/i);
|
1535
|
+
if (setofMatch) {
|
1536
|
+
return { kind: 'setof', table: setofMatch[1] };
|
1537
|
+
}
|
1538
|
+
throw new Error(`Unsupported return type format: ${returnType}`);
|
1539
|
+
}
|
1540
|
+
function traverse_func_expr_windowless(func_expr_windowless, context, traverseResult) {
|
1541
|
+
const func_application = func_expr_windowless.func_application();
|
1542
|
+
if (func_application) {
|
1543
|
+
const func_name = func_application.func_name().getText().toLowerCase();
|
1544
|
+
const funcSchema = context.userFunctions.find(func => func.function_name.toLowerCase() === func_name);
|
1545
|
+
if (funcSchema) {
|
1546
|
+
const definition = funcSchema.definition;
|
1547
|
+
const returnType = parseReturnType(funcSchema.return_type);
|
1548
|
+
const functionColumns = returnType.kind === 'table' ? returnType.columns.map(col => {
|
1549
|
+
const columnInfo = {
|
1550
|
+
column_name: col.name,
|
1551
|
+
type: col.type,
|
1552
|
+
is_nullable: true,
|
1553
|
+
table_name: '',
|
1554
|
+
table_schema: ''
|
1555
|
+
};
|
1556
|
+
return columnInfo;
|
1557
|
+
}) : context.dbSchema.filter(col => col.table_name.toLowerCase() === returnType.table);
|
1558
|
+
if (funcSchema.language.toLowerCase() === 'sql') {
|
1559
|
+
const parser = (0, postgres_1.parseSql)(definition);
|
1560
|
+
const selectstmt = parser.stmt().selectstmt();
|
1561
|
+
const { columns, multipleRowsResult } = traverseSelectstmt(selectstmt, context, traverseResult);
|
1562
|
+
return {
|
1563
|
+
columns: columns.map((c) => (Object.assign(Object.assign({}, c), { table_name: funcSchema.function_name }))),
|
1564
|
+
singleRow: !multipleRowsResult
|
1565
|
+
};
|
1566
|
+
}
|
1567
|
+
else {
|
1568
|
+
return {
|
1569
|
+
columns: functionColumns,
|
1570
|
+
singleRow: false
|
1571
|
+
};
|
1572
|
+
}
|
1573
|
+
}
|
1574
|
+
}
|
1575
|
+
throw Error('Stmt not supported: ' + func_expr_windowless.getText());
|
1418
1576
|
}
|
1419
|
-
function traverse_relation_expr(relation_expr
|
1577
|
+
function traverse_relation_expr(relation_expr) {
|
1420
1578
|
const qualified_name = relation_expr.qualified_name();
|
1421
|
-
const name = traverse_qualified_name(qualified_name
|
1579
|
+
const name = traverse_qualified_name(qualified_name);
|
1422
1580
|
return name;
|
1423
1581
|
}
|
1424
|
-
function traverse_qualified_name(qualified_name
|
1582
|
+
function traverse_qualified_name(qualified_name) {
|
1425
1583
|
var _a, _b;
|
1426
|
-
const colid_name = qualified_name.colid() ? get_colid_text(qualified_name.colid()
|
1584
|
+
const colid_name = qualified_name.colid() ? get_colid_text(qualified_name.colid()) : '';
|
1427
1585
|
const indirection_el_list = (_a = qualified_name.indirection()) === null || _a === void 0 ? void 0 : _a.indirection_el_list();
|
1428
1586
|
if (indirection_el_list && indirection_el_list.length === 1) {
|
1429
1587
|
return {
|
@@ -1436,22 +1594,22 @@ function traverse_qualified_name(qualified_name, dbSchema) {
|
|
1436
1594
|
alias: ''
|
1437
1595
|
};
|
1438
1596
|
}
|
1439
|
-
function get_colid_text(colid
|
1597
|
+
function get_colid_text(colid) {
|
1440
1598
|
const identifier = colid.identifier();
|
1441
1599
|
if (identifier) {
|
1442
|
-
return traverse_identifier(identifier
|
1600
|
+
return traverse_identifier(identifier);
|
1443
1601
|
}
|
1444
1602
|
const unreserved_keyword = colid.unreserved_keyword();
|
1445
1603
|
if (unreserved_keyword) {
|
1446
|
-
return traverse_unreserved_keyword(unreserved_keyword
|
1604
|
+
return traverse_unreserved_keyword(unreserved_keyword);
|
1447
1605
|
}
|
1448
1606
|
return '';
|
1449
1607
|
}
|
1450
|
-
function traverse_identifier(identifier
|
1608
|
+
function traverse_identifier(identifier) {
|
1451
1609
|
const tableName = identifier.Identifier().getText();
|
1452
1610
|
return tableName;
|
1453
1611
|
}
|
1454
|
-
function traverse_unreserved_keyword(unreserved_keyword
|
1612
|
+
function traverse_unreserved_keyword(unreserved_keyword) {
|
1455
1613
|
return unreserved_keyword.getText();
|
1456
1614
|
}
|
1457
1615
|
function paramIsList(c_expr) {
|
@@ -1486,8 +1644,7 @@ function paramIsList(c_expr) {
|
|
1486
1644
|
function traverseInsertstmt(insertstmt, dbSchema) {
|
1487
1645
|
const traverseResult = {
|
1488
1646
|
columnsNullability: [],
|
1489
|
-
parameters: []
|
1490
|
-
singleRow: false
|
1647
|
+
parameters: []
|
1491
1648
|
};
|
1492
1649
|
const insert_target = insertstmt.insert_target();
|
1493
1650
|
const tableName = insert_target.getText();
|
@@ -1499,7 +1656,10 @@ function traverseInsertstmt(insertstmt, dbSchema) {
|
|
1499
1656
|
const context = {
|
1500
1657
|
dbSchema,
|
1501
1658
|
fromColumns: insertColumns,
|
1659
|
+
parentColumns: [],
|
1660
|
+
withColumns: [],
|
1502
1661
|
checkConstraints: {},
|
1662
|
+
userFunctions: [],
|
1503
1663
|
collectNestedInfo: false,
|
1504
1664
|
collectDynamicQueryInfo: false
|
1505
1665
|
};
|
@@ -1535,7 +1695,10 @@ function traverseDeletestmt(deleteStmt, dbSchema, traverseResult) {
|
|
1535
1695
|
const context = {
|
1536
1696
|
dbSchema,
|
1537
1697
|
fromColumns: deleteColumns,
|
1698
|
+
parentColumns: [],
|
1699
|
+
withColumns: [],
|
1538
1700
|
checkConstraints: {},
|
1701
|
+
userFunctions: [],
|
1539
1702
|
collectNestedInfo: false,
|
1540
1703
|
collectDynamicQueryInfo: false
|
1541
1704
|
};
|
@@ -1570,12 +1733,12 @@ function traverseUpdatestmt(updatestmt, traverseContext, traverseResult) {
|
|
1570
1733
|
updatestmt.set_clause_list().set_clause_list()
|
1571
1734
|
.forEach(set_clause => traverse_set_clause(set_clause, context, traverseResult));
|
1572
1735
|
const from_clause = updatestmt.from_clause();
|
1573
|
-
const
|
1736
|
+
const fromResult = from_clause ? traverse_from_clause(from_clause, context, traverseResult) : { columns: [], singleRow: true };
|
1574
1737
|
const parametersBefore = traverseResult.parameters.length;
|
1575
1738
|
const where_clause = updatestmt.where_or_current_clause();
|
1576
1739
|
if (where_clause) {
|
1577
1740
|
const a_expr = where_clause.a_expr();
|
1578
|
-
traverse_a_expr(a_expr, Object.assign(Object.assign({}, context), { fromColumns: updateColumns.concat(
|
1741
|
+
traverse_a_expr(a_expr, Object.assign(Object.assign({}, context), { fromColumns: updateColumns.concat(fromResult.columns) }), traverseResult);
|
1579
1742
|
}
|
1580
1743
|
const whereParameters = traverseResult.parameters.slice(parametersBefore);
|
1581
1744
|
const returning_clause = updatestmt.returning_clause();
|
@@ -1840,7 +2003,7 @@ function isParameter(str) {
|
|
1840
2003
|
const paramPattern = /^\$[0-9]+(::[a-zA-Z_][a-zA-Z0-9_]*)?$/;
|
1841
2004
|
return paramPattern.test(str);
|
1842
2005
|
}
|
1843
|
-
function isSingleRowResult(selectstmt,
|
2006
|
+
function isSingleRowResult(selectstmt, fromColumns) {
|
1844
2007
|
var _a, _b;
|
1845
2008
|
const limit = checkLimit(selectstmt);
|
1846
2009
|
if (limit === 1) {
|
@@ -1873,9 +2036,7 @@ function isSingleRowResult(selectstmt, dbSchema) {
|
|
1873
2036
|
}
|
1874
2037
|
const where_clause = simple_select_pramary.where_clause();
|
1875
2038
|
if (where_clause) {
|
1876
|
-
const
|
1877
|
-
const uniqueKeys = dbSchema.filter(col => col.table_name.toLowerCase() === tableName.name.toLowerCase()
|
1878
|
-
&& (col.column_key === 'PRI' || col.column_key === 'UNI'))
|
2039
|
+
const uniqueKeys = fromColumns.filter(col => col.column_key === 'PRI' || col.column_key === 'UNI')
|
1879
2040
|
.map(col => col.column_name);
|
1880
2041
|
return isSingleRowResult_where(where_clause.a_expr(), uniqueKeys);
|
1881
2042
|
}
|