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.
Files changed (32) hide show
  1. package/code-generator2.d.ts.map +1 -1
  2. package/code-generator2.js +12 -1
  3. package/code-generator2.js.map +1 -1
  4. package/dialects/postgres.d.ts.map +1 -1
  5. package/dialects/postgres.js +5 -0
  6. package/dialects/postgres.js.map +1 -1
  7. package/drivers/postgres.d.ts +2 -0
  8. package/drivers/postgres.d.ts.map +1 -1
  9. package/drivers/postgres.js +21 -0
  10. package/drivers/postgres.js.map +1 -1
  11. package/drivers/types.d.ts +2 -0
  12. package/drivers/types.d.ts.map +1 -1
  13. package/mysql-query-analyzer/select-columns.d.ts +1 -0
  14. package/mysql-query-analyzer/select-columns.d.ts.map +1 -1
  15. package/mysql-query-analyzer/select-columns.js +13 -0
  16. package/mysql-query-analyzer/select-columns.js.map +1 -1
  17. package/package.json +1 -1
  18. package/postgres-query-analyzer/describe.d.ts.map +1 -1
  19. package/postgres-query-analyzer/describe.js +5 -4
  20. package/postgres-query-analyzer/describe.js.map +1 -1
  21. package/postgres-query-analyzer/parser.d.ts +3 -2
  22. package/postgres-query-analyzer/parser.d.ts.map +1 -1
  23. package/postgres-query-analyzer/parser.js +19 -5
  24. package/postgres-query-analyzer/parser.js.map +1 -1
  25. package/postgres-query-analyzer/traverse.d.ts +17 -6
  26. package/postgres-query-analyzer/traverse.d.ts.map +1 -1
  27. package/postgres-query-analyzer/traverse.js +290 -129
  28. package/postgres-query-analyzer/traverse.js.map +1 -1
  29. package/postgres-query-analyzer/types.d.ts +8 -0
  30. package/postgres-query-analyzer/types.d.ts.map +1 -1
  31. package/sqlite-query-analyzer/types.d.ts +6 -2
  32. 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
- checkConstraints
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 columns = traverse_selectstmt(selectstmt, context, traverseResult);
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, context.dbSchema);
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
- return [];
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 newContext = Object.assign(Object.assign({}, context), { fromColumns: withColumns.concat(context.fromColumns) });
120
- const withResult = traverse_common_table_expr(common_table_expr, newContext, traverseResult);
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 newContext = Object.assign(Object.assign({}, context), { fromColumns: withColumns.concat(context.fromColumns) });
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 columns = traverse_selectstmt(select_stmt, Object.assign(Object.assign({}, context), { collectDynamicQueryInfo: false }), traverseResult);
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
- let selectColumns = [];
177
- if (simple_select_intersect_list) {
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 unionNotNull = traverse_simple_select_intersect(simple_select_intersect_list[index], context, traverseResult);
183
- selectColumns = selectColumns.map((value, columnIndex) => {
184
- const col = Object.assign({ column_name: value.column_name, is_nullable: value.is_nullable || unionNotNull[columnIndex].is_nullable, table_name: '', table_schema: '', type: value.type }, (value.column_default && { column_default: value.column_default }));
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 selectColumns;
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
- const fromColumns = [];
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
- const fields = traverse_from_clause(from_clause, context, traverseResult);
204
- const fieldsNotNull = where_clause != null ? fields.map(field => checkIsNullable(where_clause, field)) : fields;
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 valuesColumns;
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
- const newContext = Object.assign(Object.assign({}, context), { fromColumns: fromColumns.concat(context.fromColumns) });
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 filteredColumns;
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: 'unknown'
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: 'unknown',
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: 'unknown',
834
- recordTypes: expr_list.map(rec => ({ type: rec.type, notNull: !rec.is_nullable }))
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 elseIsNotNull = elseExpr ? !traverse_a_expr(elseExpr, context, traverseResult).is_nullable : false;
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 someIsNotNull = columns.some(col => filterExpr && col.original_is_nullable === false && isNotNull_a_expr(col, filterExpr));
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
- if (someIsNotNull) {
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
- return {
1019
+ const result = {
990
1020
  column_name: columnName,
991
- is_nullable: true,
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.map(arg => arg.jsonType || { name: 'json_field', type: arg.type, notNull: !arg.is_nullable })
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 fields = argResult.recordTypes.map((record, index) => ({ name: `f${index + 1}`, type: record.type, notNull: record.notNull }));
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
- return traverse_from_list(from_list, context, traverseResult);
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 newColumns = from_list.table_ref_list().flatMap(table_ref => traverse_table_ref(table_ref, context, traverseResult));
1277
- return newColumns;
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, dbSchema);
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 fromColumnsResult = fromColumns.concat(dbSchema).filter(col => col.table_name.toLowerCase() === tableName.name.toLowerCase())
1291
- .map(col => (Object.assign(Object.assign({}, col), { table_name: tableNameWithAlias.toLowerCase() })));
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
- if (table_ref_list) {
1314
- const joinColumns = table_ref_list.flatMap((table_ref, joinIndex) => {
1315
- const joinType = join_type_list[joinIndex]; //INNER, LEFT
1316
- const joinQual = join_qual_list[joinIndex];
1317
- const numParamsBefore = traverseResult.parameters.length;
1318
- const joinColumns = traverse_table_ref(table_ref, context, traverseResult);
1319
- const isUsing = (joinQual === null || joinQual === void 0 ? void 0 : joinQual.USING()) ? true : false;
1320
- const isLeftJoin = joinType === null || joinType === void 0 ? void 0 : joinType.LEFT();
1321
- const filteredColumns = isUsing ? filterUsingColumns(joinColumns, joinQual) : joinColumns;
1322
- const resultColumns = isLeftJoin ? filteredColumns.map(col => (Object.assign(Object.assign({}, col), { is_nullable: true, original_is_nullable: col.is_nullable }))) : filteredColumns;
1323
- if (context.collectNestedInfo) {
1324
- collectNestedInfo(joinQual, resultColumns, traverseResult);
1325
- }
1326
- if (context.collectDynamicQueryInfo) {
1327
- const parameters = traverseResult.parameters.slice(numParamsBefore).map((_, index) => index + numParamsBefore);
1328
- collectDynamicQueryInfoTableRef(table_ref, joinType, joinQual, resultColumns, parameters, traverseResult);
1329
- }
1330
- return resultColumns;
1331
- });
1332
- allColumns.push(...joinColumns);
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 withAlias;
1405
+ return {
1406
+ columns: withAlias,
1407
+ singleRow: false
1408
+ };
1346
1409
  }
1347
- return allColumns;
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, dbSchema) {
1577
+ function traverse_relation_expr(relation_expr) {
1420
1578
  const qualified_name = relation_expr.qualified_name();
1421
- const name = traverse_qualified_name(qualified_name, dbSchema);
1579
+ const name = traverse_qualified_name(qualified_name);
1422
1580
  return name;
1423
1581
  }
1424
- function traverse_qualified_name(qualified_name, dbSchema) {
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(), dbSchema) : '';
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, dbSchema) {
1597
+ function get_colid_text(colid) {
1440
1598
  const identifier = colid.identifier();
1441
1599
  if (identifier) {
1442
- return traverse_identifier(identifier, dbSchema);
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, dbSchema);
1604
+ return traverse_unreserved_keyword(unreserved_keyword);
1447
1605
  }
1448
1606
  return '';
1449
1607
  }
1450
- function traverse_identifier(identifier, dbSchema) {
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, dbSchema) {
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 fromColumns = from_clause ? traverse_from_clause(from_clause, context, traverseResult) : [];
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(fromColumns) }), traverseResult);
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, dbSchema) {
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 tableName = getTableName(table_ref_list[0]);
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
  }