typesql-cli 0.18.2 → 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 +7 -2
- 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 +6 -5
- 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 +18 -1
- package/postgres-query-analyzer/traverse.d.ts.map +1 -1
- package/postgres-query-analyzer/traverse.js +367 -150
- 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
|
}
|
@@ -355,7 +373,7 @@ function traverse_a_expr(a_expr, context, traverseResult) {
|
|
355
373
|
is_nullable: true,
|
356
374
|
table_name: '',
|
357
375
|
table_schema: '',
|
358
|
-
type: '
|
376
|
+
type: 'unknown'
|
359
377
|
};
|
360
378
|
}
|
361
379
|
function traverse_a_expr_qual(a_expr_qual, context, traverseResult) {
|
@@ -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();
|
@@ -549,7 +568,7 @@ function traverse_expr_like(a_expr_like, context, traverseResult) {
|
|
549
568
|
is_nullable: result.some(col => col.is_nullable),
|
550
569
|
table_name: '',
|
551
570
|
table_schema: '',
|
552
|
-
type: '
|
571
|
+
type: 'unknown'
|
553
572
|
};
|
554
573
|
}
|
555
574
|
throw Error('traverse_expr_like - Not expected:' + a_expr_like.getText());
|
@@ -566,7 +585,7 @@ function traverse_expr_qual_op(a_expr_qual_op, context, traverseResult) {
|
|
566
585
|
is_nullable: result.some(col => col.is_nullable),
|
567
586
|
table_name: '',
|
568
587
|
table_schema: '',
|
569
|
-
type: '
|
588
|
+
type: 'unknown'
|
570
589
|
};
|
571
590
|
}
|
572
591
|
throw Error('traverse_expr_qual_op - Not expected:' + a_expr_qual_op.getText());
|
@@ -622,7 +641,7 @@ function traverse_expr_caret(a_expr_caret, context, traverseResult) {
|
|
622
641
|
is_nullable: notNullInfo.some(notNullInfo => notNullInfo.is_nullable),
|
623
642
|
table_name: '',
|
624
643
|
table_schema: '',
|
625
|
-
type: '
|
644
|
+
type: 'unknown'
|
626
645
|
};
|
627
646
|
return result;
|
628
647
|
}
|
@@ -710,12 +729,12 @@ 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 {
|
717
736
|
name: a_expr_const.getText(),
|
718
|
-
type: '
|
737
|
+
type: 'unknown'
|
719
738
|
};
|
720
739
|
}
|
721
740
|
function traversec_expr(c_expr, context, traverseResult) {
|
@@ -730,7 +749,7 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
730
749
|
is_nullable: true,
|
731
750
|
table_schema: '',
|
732
751
|
table_name: '',
|
733
|
-
type: '
|
752
|
+
type: 'unknown'
|
734
753
|
};
|
735
754
|
}
|
736
755
|
const array_expr = c_expr.array_expr();
|
@@ -741,8 +760,22 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
741
760
|
}
|
742
761
|
const columnref = c_expr.columnref();
|
743
762
|
if (columnref) {
|
744
|
-
|
745
|
-
|
763
|
+
if (context.columnRefIsRecord) {
|
764
|
+
const table = (0, select_columns_1.splitTableName)(columnref.getText());
|
765
|
+
const columns = filterColumns(context.fromColumns, table);
|
766
|
+
return {
|
767
|
+
column_name: columnref.getText(),
|
768
|
+
is_nullable: false,
|
769
|
+
table_name: '',
|
770
|
+
table_schema: '',
|
771
|
+
type: 'record',
|
772
|
+
recordTypes: columns
|
773
|
+
};
|
774
|
+
}
|
775
|
+
else {
|
776
|
+
const col = traverseColumnRef(columnref, context.fromColumns);
|
777
|
+
return col;
|
778
|
+
}
|
746
779
|
}
|
747
780
|
const aexprconst = c_expr.aexprconst();
|
748
781
|
if (aexprconst) {
|
@@ -766,11 +799,12 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
766
799
|
is_nullable: !!context.propagatesNull,
|
767
800
|
table_name: '',
|
768
801
|
table_schema: '',
|
769
|
-
type: '
|
802
|
+
type: 'unknown'
|
770
803
|
};
|
771
804
|
}
|
772
805
|
const fun_expr = c_expr.func_expr();
|
773
806
|
if (fun_expr) {
|
807
|
+
context.columnRefIsRecord = undefined;
|
774
808
|
const func_application = fun_expr.func_application();
|
775
809
|
if (func_application) {
|
776
810
|
if (is_json_build_object_func(func_application)) {
|
@@ -796,14 +830,14 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
796
830
|
}
|
797
831
|
const select_with_parens = c_expr.select_with_parens();
|
798
832
|
if (select_with_parens) {
|
799
|
-
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);
|
800
834
|
return {
|
801
835
|
column_name: '?column?',
|
802
|
-
is_nullable: true,
|
836
|
+
is_nullable: result.columns[0].jsonType ? result.columns[0].is_nullable : true,
|
803
837
|
table_name: '',
|
804
838
|
table_schema: '',
|
805
|
-
type: result[0].type,
|
806
|
-
jsonType: result[0].jsonType
|
839
|
+
type: result.columns[0].type,
|
840
|
+
jsonType: result.columns[0].jsonType
|
807
841
|
};
|
808
842
|
}
|
809
843
|
const a_expr_in_parens = c_expr._a_expr_in_parens;
|
@@ -819,7 +853,8 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
819
853
|
is_nullable: expr_list.some(col => col.is_nullable),
|
820
854
|
table_name: '',
|
821
855
|
table_schema: '',
|
822
|
-
type: '
|
856
|
+
type: 'record',
|
857
|
+
recordTypes: expr_list.map(expr => (Object.assign(Object.assign({}, expr), { column_name: '' })))
|
823
858
|
};
|
824
859
|
}
|
825
860
|
const implicit_row = c_expr.implicit_row();
|
@@ -831,7 +866,7 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
831
866
|
is_nullable: expr_list.some(col => col.is_nullable),
|
832
867
|
table_name: '',
|
833
868
|
table_schema: '',
|
834
|
-
type: '
|
869
|
+
type: 'unknown'
|
835
870
|
};
|
836
871
|
}
|
837
872
|
}
|
@@ -855,13 +890,7 @@ function traversec_expr(c_expr, context, traverseResult) {
|
|
855
890
|
function filterColumns(fromColumns, fieldName) {
|
856
891
|
return fromColumns.filter(col => (fieldName.prefix === '' || col.table_name === fieldName.prefix)
|
857
892
|
&& (fieldName.name === '*' || col.column_name === fieldName.name)).map(col => {
|
858
|
-
const result = {
|
859
|
-
column_name: col.column_name,
|
860
|
-
is_nullable: col.is_nullable,
|
861
|
-
table_name: col.table_name,
|
862
|
-
table_schema: col.table_schema,
|
863
|
-
type: col.type
|
864
|
-
};
|
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 }));
|
865
894
|
return result;
|
866
895
|
});
|
867
896
|
}
|
@@ -878,22 +907,33 @@ function traversec_expr_case(c_expr_case, context, traverseResult) {
|
|
878
907
|
const whenResult = case_expr.when_clause_list().when_clause_list().map(when_clause => traversewhen_clause(when_clause, context, traverseResult));
|
879
908
|
const whenIsNotNull = whenResult.every(when => when);
|
880
909
|
const elseExpr = (_a = case_expr.case_default()) === null || _a === void 0 ? void 0 : _a.a_expr();
|
881
|
-
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;
|
882
912
|
const notNull = elseIsNotNull && whenIsNotNull;
|
883
913
|
return {
|
884
914
|
column_name: '?column?',
|
885
915
|
is_nullable: !notNull,
|
886
916
|
table_name: '',
|
887
917
|
table_schema: '',
|
888
|
-
type: (_b = whenResult[0].type) !== null && _b !== void 0 ? _b : '
|
918
|
+
type: (_b = whenResult[0].type) !== null && _b !== void 0 ? _b : 'unknown',
|
919
|
+
jsonType: allJsonTypesMatch(whenResult, elseResult) ? whenResult[0].jsonType : undefined
|
889
920
|
};
|
890
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
|
+
}
|
891
931
|
function traversewhen_clause(when_clause, context, traverseResult) {
|
892
932
|
const a_expr_list = when_clause.a_expr_list();
|
893
933
|
const [whenExprList, thenExprList] = partition(a_expr_list, (index) => index % 2 === 0);
|
894
934
|
const whenExprResult = thenExprList.map((thenExpr, index) => {
|
895
935
|
traverse_a_expr(whenExprList[index], context, traverseResult);
|
896
|
-
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);
|
897
937
|
return thenExprResult;
|
898
938
|
});
|
899
939
|
const notNull = whenExprResult.every(res => res);
|
@@ -902,7 +942,8 @@ function traversewhen_clause(when_clause, context, traverseResult) {
|
|
902
942
|
is_nullable: !notNull,
|
903
943
|
table_name: '',
|
904
944
|
table_schema: '',
|
905
|
-
type: whenExprResult[0].type
|
945
|
+
type: whenExprResult[0].type,
|
946
|
+
jsonType: whenExprResult[0].jsonType
|
906
947
|
};
|
907
948
|
}
|
908
949
|
function partition(array, predicate) {
|
@@ -930,69 +971,113 @@ function is_json_agg(func_application) {
|
|
930
971
|
return functionName === 'json_agg'
|
931
972
|
|| functionName === 'jsonb_agg';
|
932
973
|
}
|
933
|
-
function
|
934
|
-
const
|
935
|
-
|
936
|
-
|
937
|
-
|
974
|
+
function mapJsonBuildArgsToJsonProperty(args, filterExpr) {
|
975
|
+
const keys = args.filter((_, index) => index % 2 === 0);
|
976
|
+
const values = args.filter((_, index) => index % 2 === 1);
|
977
|
+
const nullability = inferJsonNullability(values, filterExpr);
|
978
|
+
const properties = [];
|
979
|
+
for (let i = 0; i < values.length; i++) {
|
980
|
+
const key = keys[i];
|
981
|
+
const value = values[i];
|
938
982
|
if (value !== undefined) {
|
939
|
-
const
|
940
|
-
|
941
|
-
pairs.push({ key: key.column_name, type });
|
983
|
+
const type = value.jsonType ? value.jsonType : { name: 'json_field', type: value.type, notNull: nullability[i] };
|
984
|
+
properties.push({ key: key.column_name, type });
|
942
985
|
}
|
943
986
|
}
|
944
|
-
return
|
987
|
+
return properties;
|
988
|
+
}
|
989
|
+
function inferJsonNullability(columns, filterExpr) {
|
990
|
+
const tables = columns.filter(col => filterExpr && col.original_is_nullable === false && isNotNull_a_expr(col, filterExpr)).map(col => col.table_name);
|
991
|
+
const fields = columns.map(col => {
|
992
|
+
return col.original_is_nullable != null && tables.includes(col.table_name) ? !col.original_is_nullable : !col.is_nullable;
|
993
|
+
});
|
994
|
+
return fields;
|
995
|
+
}
|
996
|
+
function transformFieldsToJsonObjType(fields) {
|
997
|
+
const jsonObject = {
|
998
|
+
name: 'json',
|
999
|
+
properties: fields.map(col => mapFieldToPropertyDef(col))
|
1000
|
+
};
|
1001
|
+
return jsonObject;
|
1002
|
+
}
|
1003
|
+
function mapFieldToPropertyDef(field) {
|
1004
|
+
const prop = {
|
1005
|
+
key: field.name,
|
1006
|
+
type: transformFieldToJsonField(field)
|
1007
|
+
};
|
1008
|
+
return prop;
|
1009
|
+
}
|
1010
|
+
function transformFieldToJsonField(field) {
|
1011
|
+
const jsonField = { name: 'json_field', type: field.type, notNull: field.notNull };
|
1012
|
+
return jsonField;
|
945
1013
|
}
|
946
1014
|
function traverse_json_build_obj_func(func_application, context, traverseResult) {
|
947
1015
|
var _a, _b;
|
948
1016
|
const columnName = ((_a = func_application.func_name()) === null || _a === void 0 ? void 0 : _a.getText()) || func_application.getText();
|
949
1017
|
const func_arg_expr_list = ((_b = func_application.func_arg_list()) === null || _b === void 0 ? void 0 : _b.func_arg_expr_list()) || [];
|
950
1018
|
const argsResult = func_arg_expr_list.map(func_arg_expr => traversefunc_arg_expr(func_arg_expr, context, traverseResult));
|
951
|
-
|
1019
|
+
const result = {
|
952
1020
|
column_name: columnName,
|
953
|
-
is_nullable:
|
1021
|
+
is_nullable: false,
|
954
1022
|
table_name: '',
|
955
1023
|
table_schema: '',
|
956
1024
|
type: 'json',
|
957
1025
|
jsonType: {
|
958
1026
|
name: 'json',
|
959
|
-
properties:
|
1027
|
+
properties: mapJsonBuildArgsToJsonProperty(argsResult, context.filter_expr),
|
960
1028
|
}
|
961
1029
|
};
|
962
|
-
|
963
|
-
function isNotNull_json_agg(col) {
|
964
|
-
if (col.jsonType != null && col.jsonType.name == 'json') {
|
965
|
-
return col.jsonType.properties.every(prop => {
|
966
|
-
if (prop.type.name == 'json_field') {
|
967
|
-
return !prop.type.notNull;
|
968
|
-
}
|
969
|
-
return false;
|
970
|
-
});
|
971
|
-
}
|
972
|
-
return false;
|
1030
|
+
return result;
|
973
1031
|
}
|
974
1032
|
function traverse_json_agg(func_application, context, traverseResult) {
|
975
1033
|
var _a, _b;
|
976
1034
|
const columnName = ((_a = func_application.func_name()) === null || _a === void 0 ? void 0 : _a.getText()) || func_application.getText();
|
977
1035
|
const func_arg_expr_list = ((_b = func_application.func_arg_list()) === null || _b === void 0 ? void 0 : _b.func_arg_expr_list()) || [];
|
978
|
-
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));
|
979
1037
|
const result = {
|
980
1038
|
column_name: columnName,
|
981
|
-
is_nullable:
|
1039
|
+
is_nullable: context.filter_expr != null,
|
982
1040
|
table_name: '',
|
983
1041
|
table_schema: '',
|
984
1042
|
type: 'json[]',
|
985
1043
|
jsonType: {
|
986
1044
|
name: 'json[]',
|
987
|
-
properties: argsResult
|
1045
|
+
properties: createJsonTypeForJsonAgg(argsResult[0], context.filter_expr)
|
988
1046
|
}
|
989
1047
|
};
|
990
1048
|
return result;
|
991
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
|
+
}
|
992
1063
|
function traversefunc_application(func_application, context, traverseResult) {
|
993
1064
|
var _a;
|
994
1065
|
const functionName = getFunctionName(func_application);
|
995
1066
|
const func_arg_expr_list = ((_a = func_application.func_arg_list()) === null || _a === void 0 ? void 0 : _a.func_arg_expr_list()) || [];
|
1067
|
+
if (functionName === 'row_to_json') {
|
1068
|
+
const argResult = traversefunc_arg_expr(func_arg_expr_list[0], Object.assign(Object.assign({}, context), { columnRefIsRecord: true }), traverseResult);
|
1069
|
+
if (argResult.recordTypes) {
|
1070
|
+
const jsonType = mapRecordsToJsonType(argResult.recordTypes, context.filter_expr);
|
1071
|
+
return {
|
1072
|
+
column_name: functionName,
|
1073
|
+
is_nullable: false,
|
1074
|
+
table_name: '',
|
1075
|
+
table_schema: '',
|
1076
|
+
type: 'json',
|
1077
|
+
jsonType
|
1078
|
+
};
|
1079
|
+
}
|
1080
|
+
}
|
996
1081
|
const argsResult = func_arg_expr_list.map(func_arg_expr => traversefunc_arg_expr(func_arg_expr, context, traverseResult));
|
997
1082
|
if (functionName === 'count') {
|
998
1083
|
return {
|
@@ -1058,7 +1143,7 @@ function traversefunc_application(func_application, context, traverseResult) {
|
|
1058
1143
|
is_nullable: false,
|
1059
1144
|
table_name: '',
|
1060
1145
|
table_schema: '',
|
1061
|
-
type: '
|
1146
|
+
type: 'unknown'
|
1062
1147
|
};
|
1063
1148
|
}
|
1064
1149
|
if (functionName === 'row_number'
|
@@ -1112,14 +1197,27 @@ function traversefunc_application(func_application, context, traverseResult) {
|
|
1112
1197
|
};
|
1113
1198
|
}
|
1114
1199
|
if (functionName === 'sum') {
|
1115
|
-
return Object.assign(Object.assign({}, argsResult[0]), { column_name: functionName, is_nullable: true, type: argsResult[0].type ? mapSumType(argsResult[0].type) : '
|
1200
|
+
return Object.assign(Object.assign({}, argsResult[0]), { column_name: functionName, is_nullable: true, type: argsResult[0].type ? mapSumType(argsResult[0].type) : 'unknown' });
|
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
|
+
};
|
1116
1214
|
}
|
1117
1215
|
return {
|
1118
1216
|
column_name: functionName,
|
1119
1217
|
is_nullable: true,
|
1120
1218
|
table_name: '',
|
1121
1219
|
table_schema: '',
|
1122
|
-
type: '
|
1220
|
+
type: 'unknown'
|
1123
1221
|
};
|
1124
1222
|
}
|
1125
1223
|
function mapSumType(type) {
|
@@ -1162,7 +1260,7 @@ function traversefunc_expr_common_subexpr(func_expr_common_subexpr, context, tra
|
|
1162
1260
|
is_nullable: true,
|
1163
1261
|
table_name: '',
|
1164
1262
|
table_schema: '',
|
1165
|
-
type: '
|
1263
|
+
type: 'unknown'
|
1166
1264
|
};
|
1167
1265
|
}
|
1168
1266
|
function traversefunc_arg_expr(func_arg_expr, context, traverseResult) {
|
@@ -1185,7 +1283,7 @@ function traverse_array_expr(array_expr, context, traverseResult) {
|
|
1185
1283
|
is_nullable: true,
|
1186
1284
|
table_name: '',
|
1187
1285
|
table_schema: '',
|
1188
|
-
type: '
|
1286
|
+
type: 'unknown'
|
1189
1287
|
};
|
1190
1288
|
}
|
1191
1289
|
function traverse_array_expr_list(array_expr_list, context, traverseResult) {
|
@@ -1212,27 +1310,40 @@ function checkIsNullable(where_clause, field) {
|
|
1212
1310
|
function traverse_from_clause(from_clause, context, traverseResult) {
|
1213
1311
|
const from_list = from_clause.from_list();
|
1214
1312
|
if (from_list) {
|
1215
|
-
|
1313
|
+
const fromListResult = traverse_from_list(from_list, context, traverseResult);
|
1314
|
+
return fromListResult;
|
1216
1315
|
}
|
1217
|
-
return
|
1316
|
+
return {
|
1317
|
+
columns: [],
|
1318
|
+
singleRow: false
|
1319
|
+
};
|
1218
1320
|
}
|
1219
1321
|
function traverse_from_list(from_list, context, traverseResult) {
|
1220
|
-
const
|
1221
|
-
|
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;
|
1222
1333
|
}
|
1223
1334
|
function traverse_table_ref(table_ref, context, traverseResult) {
|
1224
|
-
var _a, _b, _c, _d;
|
1225
|
-
const { fromColumns, dbSchema } = context;
|
1335
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
1226
1336
|
const allColumns = [];
|
1227
1337
|
const relation_expr = table_ref.relation_expr();
|
1228
1338
|
const aliasClause = table_ref.alias_clause();
|
1229
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());
|
1230
1340
|
const alias = aliasClause ? aliasClause.colid().getText() : '';
|
1231
1341
|
if (relation_expr) {
|
1232
|
-
const tableName = traverse_relation_expr(relation_expr
|
1342
|
+
const tableName = traverse_relation_expr(relation_expr);
|
1343
|
+
const fromColumns = getFromColumns(tableName, context.withColumns, context.dbSchema);
|
1233
1344
|
const tableNameWithAlias = alias ? alias : tableName.name;
|
1234
|
-
const
|
1235
|
-
|
1345
|
+
const columnsWithAlias = fromColumns.map(col => (Object.assign(Object.assign({}, col), { table_name: tableNameWithAlias.toLowerCase() })));
|
1346
|
+
const fromColumnsResult = columnsWithAlias.concat(context.parentColumns);
|
1236
1347
|
allColumns.push(...fromColumnsResult);
|
1237
1348
|
if (context.collectNestedInfo) {
|
1238
1349
|
const key = fromColumnsResult.filter(col => col.column_key === 'PRI');
|
@@ -1248,47 +1359,78 @@ function traverse_table_ref(table_ref, context, traverseResult) {
|
|
1248
1359
|
};
|
1249
1360
|
(_d = traverseResult.relations) === null || _d === void 0 ? void 0 : _d.push(relation);
|
1250
1361
|
}
|
1251
|
-
const table_ref_list = table_ref.table_ref_list();
|
1252
|
-
const join_type_list = table_ref.join_type_list();
|
1253
|
-
const join_qual_list = table_ref.join_qual_list();
|
1254
1362
|
if (context.collectDynamicQueryInfo && traverseResult.dynamicQueryInfo.from.length == 0) {
|
1255
1363
|
collectDynamicQueryInfoTableRef(table_ref, null, null, fromColumnsResult, [], traverseResult);
|
1256
1364
|
}
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
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
|
+
};
|
1278
1394
|
}
|
1279
1395
|
const select_with_parens = table_ref.select_with_parens();
|
1280
1396
|
if (select_with_parens) {
|
1281
1397
|
const columns = traverse_select_with_parens(select_with_parens, Object.assign(Object.assign({}, context), { collectDynamicQueryInfo: false }), traverseResult);
|
1282
|
-
const withAlias = columns.map((col, i) => ({
|
1398
|
+
const withAlias = columns.columns.map((col, i) => ({
|
1283
1399
|
column_name: (aliasNameList === null || aliasNameList === void 0 ? void 0 : aliasNameList[i]) || col.column_name,
|
1284
1400
|
is_nullable: col.is_nullable,
|
1285
1401
|
table_name: alias || col.table_name,
|
1286
1402
|
table_schema: col.table_schema,
|
1287
1403
|
type: col.type
|
1288
1404
|
}));
|
1289
|
-
return
|
1405
|
+
return {
|
1406
|
+
columns: withAlias,
|
1407
|
+
singleRow: false
|
1408
|
+
};
|
1290
1409
|
}
|
1291
|
-
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;
|
1292
1434
|
}
|
1293
1435
|
function collectDynamicQueryInfoTableRef(table_ref, joinType, joinQual, columns, parameters, traverseResult) {
|
1294
1436
|
var _a, _b;
|
@@ -1358,16 +1500,88 @@ function traverse_select_with_parens(select_with_parens, context, traverseResult
|
|
1358
1500
|
if (select_no_parens) {
|
1359
1501
|
return traverse_select_no_parens(select_no_parens, context, traverseResult);
|
1360
1502
|
}
|
1361
|
-
return
|
1503
|
+
return {
|
1504
|
+
columns: [],
|
1505
|
+
singleRow: false
|
1506
|
+
};
|
1362
1507
|
}
|
1363
|
-
function
|
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());
|
1576
|
+
}
|
1577
|
+
function traverse_relation_expr(relation_expr) {
|
1364
1578
|
const qualified_name = relation_expr.qualified_name();
|
1365
|
-
const name = traverse_qualified_name(qualified_name
|
1579
|
+
const name = traverse_qualified_name(qualified_name);
|
1366
1580
|
return name;
|
1367
1581
|
}
|
1368
|
-
function traverse_qualified_name(qualified_name
|
1582
|
+
function traverse_qualified_name(qualified_name) {
|
1369
1583
|
var _a, _b;
|
1370
|
-
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()) : '';
|
1371
1585
|
const indirection_el_list = (_a = qualified_name.indirection()) === null || _a === void 0 ? void 0 : _a.indirection_el_list();
|
1372
1586
|
if (indirection_el_list && indirection_el_list.length === 1) {
|
1373
1587
|
return {
|
@@ -1380,22 +1594,22 @@ function traverse_qualified_name(qualified_name, dbSchema) {
|
|
1380
1594
|
alias: ''
|
1381
1595
|
};
|
1382
1596
|
}
|
1383
|
-
function get_colid_text(colid
|
1597
|
+
function get_colid_text(colid) {
|
1384
1598
|
const identifier = colid.identifier();
|
1385
1599
|
if (identifier) {
|
1386
|
-
return traverse_identifier(identifier
|
1600
|
+
return traverse_identifier(identifier);
|
1387
1601
|
}
|
1388
1602
|
const unreserved_keyword = colid.unreserved_keyword();
|
1389
1603
|
if (unreserved_keyword) {
|
1390
|
-
return traverse_unreserved_keyword(unreserved_keyword
|
1604
|
+
return traverse_unreserved_keyword(unreserved_keyword);
|
1391
1605
|
}
|
1392
1606
|
return '';
|
1393
1607
|
}
|
1394
|
-
function traverse_identifier(identifier
|
1608
|
+
function traverse_identifier(identifier) {
|
1395
1609
|
const tableName = identifier.Identifier().getText();
|
1396
1610
|
return tableName;
|
1397
1611
|
}
|
1398
|
-
function traverse_unreserved_keyword(unreserved_keyword
|
1612
|
+
function traverse_unreserved_keyword(unreserved_keyword) {
|
1399
1613
|
return unreserved_keyword.getText();
|
1400
1614
|
}
|
1401
1615
|
function paramIsList(c_expr) {
|
@@ -1430,8 +1644,7 @@ function paramIsList(c_expr) {
|
|
1430
1644
|
function traverseInsertstmt(insertstmt, dbSchema) {
|
1431
1645
|
const traverseResult = {
|
1432
1646
|
columnsNullability: [],
|
1433
|
-
parameters: []
|
1434
|
-
singleRow: false
|
1647
|
+
parameters: []
|
1435
1648
|
};
|
1436
1649
|
const insert_target = insertstmt.insert_target();
|
1437
1650
|
const tableName = insert_target.getText();
|
@@ -1443,7 +1656,10 @@ function traverseInsertstmt(insertstmt, dbSchema) {
|
|
1443
1656
|
const context = {
|
1444
1657
|
dbSchema,
|
1445
1658
|
fromColumns: insertColumns,
|
1659
|
+
parentColumns: [],
|
1660
|
+
withColumns: [],
|
1446
1661
|
checkConstraints: {},
|
1662
|
+
userFunctions: [],
|
1447
1663
|
collectNestedInfo: false,
|
1448
1664
|
collectDynamicQueryInfo: false
|
1449
1665
|
};
|
@@ -1479,7 +1695,10 @@ function traverseDeletestmt(deleteStmt, dbSchema, traverseResult) {
|
|
1479
1695
|
const context = {
|
1480
1696
|
dbSchema,
|
1481
1697
|
fromColumns: deleteColumns,
|
1698
|
+
parentColumns: [],
|
1699
|
+
withColumns: [],
|
1482
1700
|
checkConstraints: {},
|
1701
|
+
userFunctions: [],
|
1483
1702
|
collectNestedInfo: false,
|
1484
1703
|
collectDynamicQueryInfo: false
|
1485
1704
|
};
|
@@ -1514,12 +1733,12 @@ function traverseUpdatestmt(updatestmt, traverseContext, traverseResult) {
|
|
1514
1733
|
updatestmt.set_clause_list().set_clause_list()
|
1515
1734
|
.forEach(set_clause => traverse_set_clause(set_clause, context, traverseResult));
|
1516
1735
|
const from_clause = updatestmt.from_clause();
|
1517
|
-
const
|
1736
|
+
const fromResult = from_clause ? traverse_from_clause(from_clause, context, traverseResult) : { columns: [], singleRow: true };
|
1518
1737
|
const parametersBefore = traverseResult.parameters.length;
|
1519
1738
|
const where_clause = updatestmt.where_or_current_clause();
|
1520
1739
|
if (where_clause) {
|
1521
1740
|
const a_expr = where_clause.a_expr();
|
1522
|
-
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);
|
1523
1742
|
}
|
1524
1743
|
const whereParameters = traverseResult.parameters.slice(parametersBefore);
|
1525
1744
|
const returning_clause = updatestmt.returning_clause();
|
@@ -1694,12 +1913,12 @@ function mapAddExprType(types) {
|
|
1694
1913
|
};
|
1695
1914
|
let currentType = 'int2';
|
1696
1915
|
for (const type of types) {
|
1697
|
-
if (type === '
|
1698
|
-
return '
|
1916
|
+
if (type === 'unknown') {
|
1917
|
+
return 'unknown';
|
1699
1918
|
}
|
1700
1919
|
currentType = arithmeticMatrix[currentType][type];
|
1701
1920
|
if (!currentType) {
|
1702
|
-
return '
|
1921
|
+
return 'unknown';
|
1703
1922
|
}
|
1704
1923
|
}
|
1705
1924
|
return currentType;
|
@@ -1784,7 +2003,7 @@ function isParameter(str) {
|
|
1784
2003
|
const paramPattern = /^\$[0-9]+(::[a-zA-Z_][a-zA-Z0-9_]*)?$/;
|
1785
2004
|
return paramPattern.test(str);
|
1786
2005
|
}
|
1787
|
-
function isSingleRowResult(selectstmt,
|
2006
|
+
function isSingleRowResult(selectstmt, fromColumns) {
|
1788
2007
|
var _a, _b;
|
1789
2008
|
const limit = checkLimit(selectstmt);
|
1790
2009
|
if (limit === 1) {
|
@@ -1817,9 +2036,7 @@ function isSingleRowResult(selectstmt, dbSchema) {
|
|
1817
2036
|
}
|
1818
2037
|
const where_clause = simple_select_pramary.where_clause();
|
1819
2038
|
if (where_clause) {
|
1820
|
-
const
|
1821
|
-
const uniqueKeys = dbSchema.filter(col => col.table_name.toLowerCase() === tableName.name.toLowerCase()
|
1822
|
-
&& (col.column_key === 'PRI' || col.column_key === 'UNI'))
|
2039
|
+
const uniqueKeys = fromColumns.filter(col => col.column_key === 'PRI' || col.column_key === 'UNI')
|
1823
2040
|
.map(col => col.column_name);
|
1824
2041
|
return isSingleRowResult_where(where_clause.a_expr(), uniqueKeys);
|
1825
2042
|
}
|