typesql-cli 0.18.4 → 0.18.6

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 (37) hide show
  1. package/code-generator2.d.ts.map +1 -1
  2. package/code-generator2.js +2 -1
  3. package/code-generator2.js.map +1 -1
  4. package/dialects/postgres.d.ts +2 -1
  5. package/dialects/postgres.d.ts.map +1 -1
  6. package/dialects/postgres.js +13 -1
  7. package/dialects/postgres.js.map +1 -1
  8. package/drivers/postgres.d.ts +2 -1
  9. package/drivers/postgres.d.ts.map +1 -1
  10. package/drivers/postgres.js.map +1 -1
  11. package/drivers/types.d.ts +2 -2
  12. package/drivers/types.d.ts.map +1 -1
  13. package/package.json +1 -1
  14. package/postgres-query-analyzer/case-nullability-checker.d.ts +3 -0
  15. package/postgres-query-analyzer/case-nullability-checker.d.ts.map +1 -0
  16. package/postgres-query-analyzer/case-nullability-checker.js +110 -0
  17. package/postgres-query-analyzer/case-nullability-checker.js.map +1 -0
  18. package/postgres-query-analyzer/describe.d.ts.map +1 -1
  19. package/postgres-query-analyzer/describe.js +4 -4
  20. package/postgres-query-analyzer/describe.js.map +1 -1
  21. package/postgres-query-analyzer/enum-parser.d.ts +2 -1
  22. package/postgres-query-analyzer/enum-parser.d.ts.map +1 -1
  23. package/postgres-query-analyzer/enum-parser.js.map +1 -1
  24. package/postgres-query-analyzer/nullability-checker.d.ts +3 -0
  25. package/postgres-query-analyzer/nullability-checker.d.ts.map +1 -0
  26. package/postgres-query-analyzer/nullability-checker.js +110 -0
  27. package/postgres-query-analyzer/nullability-checker.js.map +1 -0
  28. package/postgres-query-analyzer/traverse.d.ts +2 -2
  29. package/postgres-query-analyzer/traverse.d.ts.map +1 -1
  30. package/postgres-query-analyzer/traverse.js +266 -85
  31. package/postgres-query-analyzer/traverse.js.map +1 -1
  32. package/sqlite-query-analyzer/replace-list-params.d.ts +0 -1
  33. package/sqlite-query-analyzer/replace-list-params.d.ts.map +1 -1
  34. package/sqlite-query-analyzer/replace-list-params.js +0 -57
  35. package/sqlite-query-analyzer/replace-list-params.js.map +1 -1
  36. package/sqlite-query-analyzer/types.d.ts +3 -1
  37. package/sqlite-query-analyzer/types.d.ts.map +1 -1
@@ -7,6 +7,7 @@ const PostgreSQLParser_1 = require("@wsporto/typesql-parser/postgres/PostgreSQLP
7
7
  const typesql_parser_1 = require("@wsporto/typesql-parser");
8
8
  const select_columns_1 = require("../mysql-query-analyzer/select-columns");
9
9
  const postgres_1 = require("@wsporto/typesql-parser/postgres");
10
+ const case_nullability_checker_1 = require("./case-nullability-checker");
10
11
  function defaultOptions() {
11
12
  return {
12
13
  collectNestedInfo: false,
@@ -123,8 +124,12 @@ function traverse_select_no_parens(select_no_parens, context, traverseResult) {
123
124
  if (with_clause) {
124
125
  with_clause.cte_list().common_table_expr_list()
125
126
  .forEach(common_table_expr => {
126
- const withResult = traverse_common_table_expr(common_table_expr, context, traverseResult);
127
- context.withColumns.push(...withResult);
127
+ var _a, _b, _c;
128
+ const recursiveTableName = with_clause.RECURSIVE() ? common_table_expr.name().getText() : undefined;
129
+ const recursiveColumnNames = (_c = (_b = (_a = common_table_expr.name_list_()) === null || _a === void 0 ? void 0 : _a.name_list()) === null || _b === void 0 ? void 0 : _b.name_list()) === null || _c === void 0 ? void 0 : _c.map(name => name.getText());
130
+ const withResult = traverse_common_table_expr(common_table_expr, Object.assign(Object.assign({}, context), { recursiveTableName, recursiveColumnNames }), traverseResult);
131
+ const columns = recursiveColumnNames ? withResult.map((col, index) => { var _a; return (Object.assign(Object.assign({}, col), { column_name: (_a = recursiveColumnNames[index]) !== null && _a !== void 0 ? _a : col.column_name })); }) : withResult;
132
+ context.withColumns.push(...columns);
128
133
  });
129
134
  }
130
135
  const select_clause = select_no_parens.select_clause();
@@ -181,8 +186,11 @@ function traverse_select_clause(select_clause, context, traverseResult) {
181
186
  const mainSelectResult = traverse_simple_select_intersect(simple_select_intersect_list[0], context, traverseResult);
182
187
  let columns = mainSelectResult.columns;
183
188
  //union
189
+ const { recursiveTableName, recursiveColumnNames } = context;
190
+ const recursiveColumns = recursiveTableName ? mainSelectResult.columns
191
+ .map((col, index) => { var _a; return (Object.assign(Object.assign({}, col), { table_name: recursiveTableName, column_name: (_a = recursiveColumnNames === null || recursiveColumnNames === void 0 ? void 0 : recursiveColumnNames[index]) !== null && _a !== void 0 ? _a : col.column_name })); }) : [];
184
192
  for (let index = 1; index < simple_select_intersect_list.length; index++) {
185
- const unionResult = traverse_simple_select_intersect(simple_select_intersect_list[index], context, traverseResult);
193
+ const unionResult = traverse_simple_select_intersect(simple_select_intersect_list[index], Object.assign(Object.assign({}, context), { fromColumns: context.fromColumns.concat(recursiveColumns) }), traverseResult);
186
194
  columns = columns.map((value, columnIndex) => {
187
195
  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 }));
188
196
  return col;
@@ -243,14 +251,18 @@ function traverse_simple_select_pramary(simple_select_pramary, context, traverse
243
251
  (_d = (_c = simple_select_pramary.group_clause()) === null || _c === void 0 ? void 0 : _c.group_by_list()) === null || _d === void 0 ? void 0 : _d.group_by_item_list().forEach(group_by => {
244
252
  const a_expr = group_by.a_expr();
245
253
  if (a_expr) {
254
+ newContext.groupBy = true;
255
+ /* The GROUP BY clause can reference column aliases defined in the SELECT list.
256
+ There's no need to retrieve nullability or type information from the GROUP BY expressions (findColumn(col). */
246
257
  traverse_a_expr(a_expr, newContext, traverseResult);
258
+ newContext.groupBy = false;
247
259
  }
248
260
  });
249
261
  const having_expr = (_e = simple_select_pramary.having_clause()) === null || _e === void 0 ? void 0 : _e.a_expr();
250
262
  if (having_expr) {
251
263
  traverse_a_expr(having_expr, newContext, traverseResult);
252
264
  }
253
- const filteredColumns = filterColumns_simple_select_pramary(simple_select_pramary, newContext, traverseResult);
265
+ const filteredColumns = filterColumns_simple_select_pramary(simple_select_pramary, Object.assign(Object.assign({}, context), { fromColumns: context.fromColumns.concat(fromResult.columns) }), traverseResult);
254
266
  return {
255
267
  columns: filteredColumns,
256
268
  singleRow: fromResult.singleRow
@@ -358,7 +370,7 @@ function traverse_target_el(target_el, context, traverseResult) {
358
370
  parameters
359
371
  });
360
372
  }
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 }));
373
+ return Object.assign(Object.assign(Object.assign({ column_name: alias || exprResult.column_name, is_nullable: exprResult.is_nullable, table_name: exprResult.table_name, table_schema: exprResult.table_schema, type: exprResult.type }, (exprResult.column_default != null) && { column_default: exprResult.column_default }), (exprResult.column_key != null && { column_key: exprResult.column_key })), (exprResult.jsonType != null && { jsonType: exprResult.jsonType }));
362
374
  }
363
375
  throw Error('Column not found');
364
376
  }
@@ -746,7 +758,7 @@ function traversec_expr(c_expr, context, traverseResult) {
746
758
  traverse_select_with_parens(select_with_parens, context, traverseResult);
747
759
  return {
748
760
  column_name: '?column?',
749
- is_nullable: true,
761
+ is_nullable: false, //empty array
750
762
  table_schema: '',
751
763
  table_name: '',
752
764
  type: 'unknown'
@@ -760,6 +772,15 @@ function traversec_expr(c_expr, context, traverseResult) {
760
772
  }
761
773
  const columnref = c_expr.columnref();
762
774
  if (columnref) {
775
+ if (context.groupBy) {
776
+ return {
777
+ column_name: columnref.getText(),
778
+ is_nullable: false,
779
+ table_name: '',
780
+ table_schema: '',
781
+ type: 'unknown'
782
+ };
783
+ }
763
784
  if (context.columnRefIsRecord) {
764
785
  const table = (0, select_columns_1.splitTableName)(columnref.getText());
765
786
  const columns = filterColumns(context.fromColumns, table);
@@ -831,13 +852,15 @@ function traversec_expr(c_expr, context, traverseResult) {
831
852
  const select_with_parens = c_expr.select_with_parens();
832
853
  if (select_with_parens) {
833
854
  const result = traverse_select_with_parens(select_with_parens, Object.assign(Object.assign({}, context), { parentColumns: context.fromColumns, fromColumns: [] }), traverseResult);
855
+ const jsonType = result.columns[0].jsonType;
856
+ const is_nullable = jsonType == null ? true : jsonType.name !== 'json[]' && jsonType.name !== 'json_map'; //json[], json_map are not nullable
834
857
  return {
835
858
  column_name: '?column?',
836
- is_nullable: result.columns[0].jsonType ? result.columns[0].is_nullable : true,
859
+ is_nullable,
837
860
  table_name: '',
838
861
  table_schema: '',
839
862
  type: result.columns[0].type,
840
- jsonType: result.columns[0].jsonType
863
+ jsonType: jsonType != null && jsonType.name === 'json' ? Object.assign(Object.assign({}, jsonType), { notNull: !is_nullable }) : jsonType
841
864
  };
842
865
  }
843
866
  const a_expr_in_parens = c_expr._a_expr_in_parens;
@@ -902,23 +925,37 @@ function excludeColumns(fromColumns, excludeList) {
902
925
  });
903
926
  }
904
927
  function traversec_expr_case(c_expr_case, context, traverseResult) {
905
- var _a, _b;
928
+ var _a;
906
929
  const case_expr = c_expr_case.case_expr();
907
- const whenResult = case_expr.when_clause_list().when_clause_list().map(when_clause => traversewhen_clause(when_clause, context, traverseResult));
908
- const whenIsNotNull = whenResult.every(when => when);
909
- const elseExpr = (_a = case_expr.case_default()) === null || _a === void 0 ? void 0 : _a.a_expr();
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;
930
+ const whenClauseList = case_expr.when_clause_list().when_clause_list();
931
+ const whenResult = whenClauseList.map(when_clause => traversewhen_clause(when_clause, context, traverseResult));
932
+ const whenIsNotNull = whenResult.every(when => !when.is_nullable);
933
+ const elseExpr = case_expr.case_default();
934
+ const elseResult = elseExpr ? traverse_a_expr(elseExpr.a_expr(), Object.assign({}, context), traverseResult) : null;
935
+ const branchNotNull = elseResult ? evaluateBranches(whenClauseList, elseExpr, whenResult.map(col => !col.is_nullable)) : false;
936
+ const elseIsNotNull = (elseResult === null || elseResult === void 0 ? void 0 : elseResult.is_nullable) === false || branchNotNull;
912
937
  const notNull = elseIsNotNull && whenIsNotNull;
913
938
  return {
914
939
  column_name: '?column?',
915
940
  is_nullable: !notNull,
916
941
  table_name: '',
917
942
  table_schema: '',
918
- type: (_b = whenResult[0].type) !== null && _b !== void 0 ? _b : 'unknown',
943
+ type: (_a = whenResult[0].type) !== null && _a !== void 0 ? _a : 'unknown',
919
944
  jsonType: allJsonTypesMatch(whenResult, elseResult) ? whenResult[0].jsonType : undefined
920
945
  };
921
946
  }
947
+ function evaluateBranches(whenClauseList, elseExpr, whenIsNotNull) {
948
+ const exprIndex = whenClauseList.findIndex(when => {
949
+ const whenExpr = when.a_expr(0);
950
+ const evaluatesIfNull = (0, case_nullability_checker_1.evaluatesTrueIfNull)(elseExpr, whenExpr);
951
+ if (evaluatesIfNull) {
952
+ return true;
953
+ }
954
+ return false;
955
+ });
956
+ const result = exprIndex !== -1 ? whenIsNotNull[exprIndex] : false;
957
+ return result;
958
+ }
922
959
  function allJsonTypesMatch(whenResultList, elseResult) {
923
960
  var _a;
924
961
  const firstType = (_a = whenResultList[0]) === null || _a === void 0 ? void 0 : _a.jsonType;
@@ -936,7 +973,7 @@ function traversewhen_clause(when_clause, context, traverseResult) {
936
973
  const thenExprResult = traverse_a_expr(thenExpr, Object.assign(Object.assign({}, context), { filter_expr: whenExprList[index] }), traverseResult);
937
974
  return thenExprResult;
938
975
  });
939
- const notNull = whenExprResult.every(res => res);
976
+ const notNull = whenExprResult.every(res => !res.is_nullable);
940
977
  return {
941
978
  column_name: '?column?',
942
979
  is_nullable: !notNull,
@@ -987,7 +1024,9 @@ function mapJsonBuildArgsToJsonProperty(args, filterExpr) {
987
1024
  return properties;
988
1025
  }
989
1026
  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);
1027
+ const tables = columns.filter(col => filterExpr && col.original_is_nullable === false
1028
+ && isNotNull_a_expr({ name: col.column_name, prefix: col.table_name }, filterExpr))
1029
+ .map(col => col.table_name);
991
1030
  const fields = columns.map(col => {
992
1031
  return col.original_is_nullable != null && tables.includes(col.table_name) ? !col.original_is_nullable : !col.is_nullable;
993
1032
  });
@@ -996,19 +1035,20 @@ function inferJsonNullability(columns, filterExpr) {
996
1035
  function transformFieldsToJsonObjType(fields) {
997
1036
  const jsonObject = {
998
1037
  name: 'json',
1038
+ notNull: true,
999
1039
  properties: fields.map(col => mapFieldToPropertyDef(col))
1000
1040
  };
1001
1041
  return jsonObject;
1002
1042
  }
1003
1043
  function mapFieldToPropertyDef(field) {
1004
1044
  const prop = {
1005
- key: field.name,
1045
+ key: field.column_name,
1006
1046
  type: transformFieldToJsonField(field)
1007
1047
  };
1008
1048
  return prop;
1009
1049
  }
1010
1050
  function transformFieldToJsonField(field) {
1011
- const jsonField = { name: 'json_field', type: field.type, notNull: field.notNull };
1051
+ const jsonField = field.jsonType ? field.jsonType : { name: 'json_field', type: field.type, notNull: !field.is_nullable };
1012
1052
  return jsonField;
1013
1053
  }
1014
1054
  function traverse_json_build_obj_func(func_application, context, traverseResult) {
@@ -1024,6 +1064,7 @@ function traverse_json_build_obj_func(func_application, context, traverseResult)
1024
1064
  type: 'json',
1025
1065
  jsonType: {
1026
1066
  name: 'json',
1067
+ notNull: true,
1027
1068
  properties: mapJsonBuildArgsToJsonProperty(argsResult, context.filter_expr),
1028
1069
  }
1029
1070
  };
@@ -1040,23 +1081,26 @@ function traverse_json_agg(func_application, context, traverseResult) {
1040
1081
  table_name: '',
1041
1082
  table_schema: '',
1042
1083
  type: 'json[]',
1043
- jsonType: {
1044
- name: 'json[]',
1045
- properties: createJsonTypeForJsonAgg(argsResult[0], context.filter_expr)
1046
- }
1084
+ jsonType: createJsonTypeForJsonAgg(argsResult[0], context.filter_expr)
1047
1085
  };
1048
1086
  return result;
1049
1087
  }
1050
1088
  function createJsonTypeForJsonAgg(arg, filter_expr) {
1051
1089
  if (arg.recordTypes) {
1052
1090
  const jsonType = mapRecordsToJsonType(arg.recordTypes, filter_expr);
1053
- return [jsonType];
1091
+ return {
1092
+ name: 'json[]',
1093
+ properties: [jsonType]
1094
+ };
1054
1095
  }
1055
- return [arg.jsonType || { name: 'json_field', type: arg.type, notNull: !arg.is_nullable }];
1096
+ const jsonType = arg.jsonType ? { name: 'json[]', properties: [arg.jsonType] } : undefined;
1097
+ const fieldType = { name: 'json[]', properties: [{ name: 'json_field', type: arg.type, notNull: !arg.is_nullable }] };
1098
+ const result = jsonType || fieldType;
1099
+ return result;
1056
1100
  }
1057
1101
  function mapRecordsToJsonType(recordTypes, filterExpr) {
1058
1102
  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] }));
1103
+ const fields = recordTypes.map((col, index) => (Object.assign(Object.assign({}, col), { column_name: col.column_name ? col.column_name : `f${index + 1}`, is_nullable: !jsonNullability[index] })));
1060
1104
  const jsonType = transformFieldsToJsonObjType(fields);
1061
1105
  return jsonType;
1062
1106
  }
@@ -1212,6 +1256,15 @@ function traversefunc_application(func_application, context, traverseResult) {
1212
1256
  }
1213
1257
  };
1214
1258
  }
1259
+ if (functionName === 'unnest') {
1260
+ return {
1261
+ column_name: functionName,
1262
+ is_nullable: argsResult[0].is_nullable,
1263
+ type: argsResult[0].type,
1264
+ table_name: '',
1265
+ table_schema: ''
1266
+ };
1267
+ }
1215
1268
  return {
1216
1269
  column_name: functionName,
1217
1270
  is_nullable: true,
@@ -1271,7 +1324,7 @@ function traverse_array_expr(array_expr, context, traverseResult) {
1271
1324
  const expr_list = array_expr.expr_list();
1272
1325
  if (expr_list) {
1273
1326
  const traverse_expr_list_result = traverse_expr_list(expr_list, context, traverseResult);
1274
- return Object.assign(Object.assign({}, traverse_expr_list_result[0]), { column_name: '?column?', table_name: '', table_schema: '' });
1327
+ return Object.assign(Object.assign({}, traverse_expr_list_result[0]), { is_nullable: traverse_expr_list_result.some(expr => expr.is_nullable), column_name: '?column?', table_name: '', table_schema: '' });
1275
1328
  }
1276
1329
  const array_expr_list = array_expr.array_expr_list();
1277
1330
  if (array_expr_list) {
@@ -1293,17 +1346,21 @@ function traverse_array_expr_list(array_expr_list, context, traverseResult) {
1293
1346
  return result;
1294
1347
  }
1295
1348
  function findColumn(fieldName, fromColumns) {
1296
- const col = fromColumns.find(col => (fieldName.prefix === '' || col.table_name.toLowerCase() === fieldName.prefix.toLowerCase()) && col.column_name.toLowerCase() === fieldName.name.toLowerCase());
1349
+ const col = findColumnOrNull(fieldName, fromColumns);
1297
1350
  if (col == null) {
1298
1351
  throw Error('Column not found: ' + fieldNameToString(fieldName));
1299
1352
  }
1300
1353
  return col;
1301
1354
  }
1355
+ function findColumnOrNull(fieldName, fromColumns) {
1356
+ const col = fromColumns.find(col => (fieldName.prefix === '' || col.table_name.toLowerCase() === fieldName.prefix.toLowerCase()) && col.column_name.toLowerCase() === fieldName.name.toLowerCase());
1357
+ return col;
1358
+ }
1302
1359
  function fieldNameToString(fieldName) {
1303
1360
  return fieldName.prefix !== '' ? `${fieldName.prefix}.${fieldName.name}` : fieldName.name;
1304
1361
  }
1305
1362
  function checkIsNullable(where_clause, field) {
1306
- const isNotNullResult = !field.is_nullable || isNotNull(field, where_clause);
1363
+ const isNotNullResult = !field.is_nullable || isNotNull({ name: field.column_name, prefix: field.table_name }, where_clause);
1307
1364
  const col = Object.assign(Object.assign({}, field), { is_nullable: !isNotNullResult });
1308
1365
  return col;
1309
1366
  }
@@ -1331,19 +1388,48 @@ function getFromColumns(tableName, withColumns, dbSchema) {
1331
1388
  const filteredSchema = filteredWithColumns.length > 0 ? filteredWithColumns : dbSchema.filter(col => col.table_name.toLowerCase() === tableName.name.toLowerCase());
1332
1389
  return filteredSchema;
1333
1390
  }
1391
+ function checkLeftJoinIsNullable(leftJoin, subsequentJoins, fromColumns) {
1392
+ if (!leftJoin.joinQual) {
1393
+ return true; // No condition = always nullable
1394
+ }
1395
+ const leftTable = getTableName(leftJoin.tableRef);
1396
+ const leftJoinColumns = getJoinColumns(leftJoin.joinQual)
1397
+ .filter(col => {
1398
+ if (col.prefix === leftTable.name && col.prefix === leftTable.alias) {
1399
+ return true;
1400
+ }
1401
+ if (findColumnOrNull(col, fromColumns)) { //column without table reference (ex: fk_user)
1402
+ return true;
1403
+ }
1404
+ return false;
1405
+ });
1406
+ for (const join of subsequentJoins) {
1407
+ // Only INNER JOINs can cancel nullability
1408
+ if (!(join.joinType === null || join.joinType.INNER_P())) {
1409
+ continue;
1410
+ }
1411
+ const joinConditionColumns = getJoinColumns(join.joinQual);
1412
+ const filteredJoinColumnsFromLeft = joinConditionColumns.filter(col => leftJoinColumns.some(lc => lc.prefix === col.prefix));
1413
+ // Are *all* columns from the left join used in not-null filtering?
1414
+ const referencesLeftJoin = filteredJoinColumnsFromLeft.length > 0 &&
1415
+ filteredJoinColumnsFromLeft.every(col => { var _a; return isNotNull_a_expr(col, (_a = join.joinQual) === null || _a === void 0 ? void 0 : _a.a_expr()); });
1416
+ if (referencesLeftJoin) {
1417
+ return false; // LEFT JOIN is effectively filtered by INNER JOIN — not nullable
1418
+ }
1419
+ }
1420
+ return true; // No INNER JOIN filtered it — remains nullable
1421
+ }
1334
1422
  function traverse_table_ref(table_ref, context, traverseResult) {
1335
- var _a, _b, _c, _d, _e, _f, _g;
1423
+ var _a, _b;
1336
1424
  const allColumns = [];
1337
1425
  const relation_expr = table_ref.relation_expr();
1338
1426
  const aliasClause = table_ref.alias_clause();
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());
1340
1427
  const alias = aliasClause ? aliasClause.colid().getText() : '';
1341
1428
  if (relation_expr) {
1342
1429
  const tableName = traverse_relation_expr(relation_expr);
1343
- const fromColumns = getFromColumns(tableName, context.withColumns, context.dbSchema);
1430
+ const fromColumns = getFromColumns(tableName, context.fromColumns.concat(context.withColumns), context.dbSchema);
1344
1431
  const tableNameWithAlias = alias ? alias : tableName.name;
1345
- const columnsWithAlias = fromColumns.map(col => (Object.assign(Object.assign({}, col), { table_name: tableNameWithAlias.toLowerCase() })));
1346
- const fromColumnsResult = columnsWithAlias.concat(context.parentColumns);
1432
+ const fromColumnsResult = fromColumns.map(col => (Object.assign(Object.assign({}, col), { table_name: tableNameWithAlias.toLowerCase() })));
1347
1433
  allColumns.push(...fromColumnsResult);
1348
1434
  if (context.collectNestedInfo) {
1349
1435
  const key = fromColumnsResult.filter(col => col.column_key === 'PRI');
@@ -1353,38 +1439,56 @@ function traverse_table_ref(table_ref, context, traverseResult) {
1353
1439
  alias: alias,
1354
1440
  renameAs,
1355
1441
  parentRelation: '',
1356
- joinColumn: ((_c = key[0]) === null || _c === void 0 ? void 0 : _c.column_name) || '',
1442
+ joinColumn: ((_a = key[0]) === null || _a === void 0 ? void 0 : _a.column_name) || '',
1357
1443
  cardinality: 'one',
1358
1444
  parentCardinality: 'one'
1359
1445
  };
1360
- (_d = traverseResult.relations) === null || _d === void 0 ? void 0 : _d.push(relation);
1446
+ (_b = traverseResult.relations) === null || _b === void 0 ? void 0 : _b.push(relation);
1361
1447
  }
1362
1448
  if (context.collectDynamicQueryInfo && traverseResult.dynamicQueryInfo.from.length == 0) {
1363
1449
  collectDynamicQueryInfoTableRef(table_ref, null, null, fromColumnsResult, [], traverseResult);
1364
1450
  }
1365
1451
  const joinList = extractJoins(table_ref);
1366
- const joinColumns = joinList.flatMap((join) => {
1452
+ joinList.forEach((join, index) => {
1367
1453
  const joinType = join.joinType; //INNER, LEFT
1368
1454
  const joinQual = join.joinQual;
1369
1455
  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;
1456
+ const subsequentJoints = joinList.slice(index + 1);
1457
+ let joinColumns = [];
1458
+ if (join.tableRef.LATERAL_P()) {
1459
+ const newContext = Object.assign(Object.assign({}, context), { parentColumns: allColumns, collectDynamicQueryInfo: false });
1460
+ const lateralJoinResult = traverse_select_with_parens_or_func_table(join.tableRef, newContext, traverseResult);
1461
+ joinColumns = lateralJoinResult.columns;
1462
+ }
1463
+ else {
1464
+ const joinTableRefResult = traverse_table_ref(join.tableRef, context, traverseResult);
1465
+ joinColumns = (joinQual === null || joinQual === void 0 ? void 0 : joinQual.USING()) ? filterUsingColumns(joinTableRefResult.columns, joinQual) : joinTableRefResult.columns;
1466
+ }
1467
+ const nullableColumns = (joinType === null || joinType === void 0 ? void 0 : joinType.LEFT())
1468
+ ? joinColumns.map(col => (Object.assign(Object.assign({}, col), { original_is_nullable: col.is_nullable, is_nullable: checkLeftJoinIsNullable(join, subsequentJoints, joinColumns) ? true : col.is_nullable })))
1469
+ : joinColumns;
1470
+ allColumns.push(...nullableColumns);
1374
1471
  if (context.collectNestedInfo && joinQual) {
1375
- collectNestedInfo(joinQual, resultColumns, traverseResult);
1472
+ collectNestedInfo(joinQual, joinColumns, traverseResult);
1376
1473
  }
1377
1474
  if (context.collectDynamicQueryInfo) {
1378
1475
  const parameters = traverseResult.parameters.slice(numParamsBefore).map((_, index) => index + numParamsBefore);
1379
- collectDynamicQueryInfoTableRef(join.tableRef, joinType, joinQual, resultColumns, parameters, traverseResult);
1476
+ collectDynamicQueryInfoTableRef(join.tableRef, joinType, joinQual, joinColumns, parameters, traverseResult);
1380
1477
  }
1381
- return resultColumns;
1382
1478
  });
1383
- allColumns.push(...joinColumns);
1479
+ return {
1480
+ columns: allColumns,
1481
+ singleRow: false
1482
+ };
1384
1483
  }
1385
- const func_table = table_ref.func_table();
1484
+ const select_with_parens_or_func_result = traverse_select_with_parens_or_func_table(table_ref, context, traverseResult);
1485
+ return select_with_parens_or_func_result;
1486
+ }
1487
+ function traverse_select_with_parens_or_func_table(tableRef, context, traverseResult) {
1488
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1489
+ const func_table = tableRef.func_table();
1386
1490
  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()) || '';
1491
+ const funcAlias = ((_c = (_b = (_a = tableRef.func_alias_clause()) === null || _a === void 0 ? void 0 : _a.alias_clause()) === null || _b === void 0 ? void 0 : _b.colid()) === null || _c === void 0 ? void 0 : _c.getText()) || '';
1388
1492
  const result = traverse_func_table(func_table, context, traverseResult);
1389
1493
  const resultWithAlias = result.columns.map(col => (Object.assign(Object.assign({}, col), { table_name: funcAlias || col.table_name })));
1390
1494
  return {
@@ -1392,25 +1496,18 @@ function traverse_table_ref(table_ref, context, traverseResult) {
1392
1496
  singleRow: result.singleRow
1393
1497
  };
1394
1498
  }
1395
- const select_with_parens = table_ref.select_with_parens();
1499
+ const select_with_parens = tableRef.select_with_parens();
1396
1500
  if (select_with_parens) {
1397
1501
  const columns = traverse_select_with_parens(select_with_parens, Object.assign(Object.assign({}, context), { collectDynamicQueryInfo: false }), traverseResult);
1398
- const withAlias = columns.columns.map((col, i) => ({
1399
- column_name: (aliasNameList === null || aliasNameList === void 0 ? void 0 : aliasNameList[i]) || col.column_name,
1400
- is_nullable: col.is_nullable,
1401
- table_name: alias || col.table_name,
1402
- table_schema: col.table_schema,
1403
- type: col.type
1404
- }));
1502
+ const aliasNameList = (_f = (_e = (_d = tableRef.alias_clause()) === null || _d === void 0 ? void 0 : _d.name_list()) === null || _e === void 0 ? void 0 : _e.name_list()) === null || _f === void 0 ? void 0 : _f.map(name => name.getText());
1503
+ const alias = (_h = (_g = tableRef.alias_clause()) === null || _g === void 0 ? void 0 : _g.colid().getText()) !== null && _h !== void 0 ? _h : '';
1504
+ const withAlias = columns.columns.map((col, i) => (Object.assign(Object.assign({}, col), { column_name: (aliasNameList === null || aliasNameList === void 0 ? void 0 : aliasNameList[i]) || col.column_name, table_name: alias || col.table_name })));
1405
1505
  return {
1406
1506
  columns: withAlias,
1407
1507
  singleRow: false
1408
1508
  };
1409
1509
  }
1410
- return {
1411
- columns: allColumns,
1412
- singleRow: false
1413
- };
1510
+ throw Error('Stmt not expected:' + tableRef.getText());
1414
1511
  }
1415
1512
  function extractJoins(table_ref) {
1416
1513
  const joinList = [];
@@ -1720,7 +1817,7 @@ function traverseDeletestmt(deleteStmt, dbSchema, traverseResult) {
1720
1817
  return result;
1721
1818
  }
1722
1819
  function addConstraintIfNotNull(checkConstraint) {
1723
- return checkConstraint !== undefined ? { checkConstraint } : {};
1820
+ return checkConstraint !== undefined ? { checkConstraint } : undefined;
1724
1821
  }
1725
1822
  function traverseUpdatestmt(updatestmt, traverseContext, traverseResult) {
1726
1823
  var _a;
@@ -1853,7 +1950,14 @@ function isNotNull_a_expr_unary_not(a_expr_unary_not, field) {
1853
1950
  function isNotNull_a_expr_isnull(a_expr_isnull, field) {
1854
1951
  const a_expr_is_not = a_expr_isnull.a_expr_is_not();
1855
1952
  if (a_expr_is_not) {
1856
- return isNotNull_a_expr_is_not(a_expr_is_not, field);
1953
+ const isNotNull = isNotNull_a_expr_is_not(a_expr_is_not, field);
1954
+ if (isNotNull && a_expr_is_not.IS() && a_expr_is_not.NOT() && a_expr_is_not.NULL_P()) {
1955
+ return true;
1956
+ }
1957
+ if (a_expr_is_not.IS() && a_expr_is_not.NULL_P()) {
1958
+ return false;
1959
+ }
1960
+ return isNotNull;
1857
1961
  }
1858
1962
  return false;
1859
1963
  }
@@ -1977,7 +2081,7 @@ function isNotNull_c_expr(c_expr, field) {
1977
2081
  const columnref = c_expr.columnref();
1978
2082
  if (columnref) {
1979
2083
  const fieldName = (0, select_columns_1.splitName)(columnref.getText());
1980
- return (fieldName.name === field.column_name && (fieldName.prefix === '' || field.table_name === fieldName.prefix));
2084
+ return (fieldName.name === field.name && (fieldName.prefix === '' || field.prefix === fieldName.prefix));
1981
2085
  }
1982
2086
  const aexprconst = c_expr.aexprconst();
1983
2087
  if (aexprconst) {
@@ -2004,7 +2108,7 @@ function isParameter(str) {
2004
2108
  return paramPattern.test(str);
2005
2109
  }
2006
2110
  function isSingleRowResult(selectstmt, fromColumns) {
2007
- var _a, _b;
2111
+ var _a;
2008
2112
  const limit = checkLimit(selectstmt);
2009
2113
  if (limit === 1) {
2010
2114
  return true;
@@ -2018,11 +2122,11 @@ function isSingleRowResult(selectstmt, fromColumns) {
2018
2122
  const simple_select_pramary = simple_select_pramary_list[0];
2019
2123
  const from_clause = simple_select_pramary.from_clause();
2020
2124
  if (!from_clause) {
2021
- const hasSetReturningFunction = (_b = simple_select_pramary.target_list_()) === null || _b === void 0 ? void 0 : _b.target_list().target_el_list().some(target_el => isSetReturningFunction_target_el(target_el));
2125
+ const hasSetReturningFunction = hasFunction(simple_select_pramary, fun => isSetReturningFunction(fun));
2022
2126
  return !hasSetReturningFunction;
2023
2127
  }
2024
2128
  if (!simple_select_pramary.group_clause()) {
2025
- const agreegateFunction = hasAggregateFunction(simple_select_pramary);
2129
+ const agreegateFunction = hasFunction(simple_select_pramary, fun => isAggregateFunction(fun));
2026
2130
  if (agreegateFunction) {
2027
2131
  return true;
2028
2132
  }
@@ -2042,28 +2146,32 @@ function isSingleRowResult(selectstmt, fromColumns) {
2042
2146
  }
2043
2147
  return false;
2044
2148
  }
2045
- function hasAggregateFunction(simple_select_pramary) {
2149
+ function hasFunction(simple_select_pramary, checkFunction) {
2046
2150
  const target_list_ = simple_select_pramary.target_list_();
2047
2151
  if (target_list_) {
2048
- return target_list_.target_list().target_el_list().some(target_el => isAggregateFunction_target_el(target_el));
2152
+ return target_list_.target_list().target_el_list().some(target_el => checkFunction_target_el(target_el, checkFunction));
2049
2153
  }
2050
2154
  const target_list = simple_select_pramary.target_list();
2051
- return target_list.target_el_list().some(target_el => isAggregateFunction_target_el(target_el));
2155
+ if (target_list) {
2156
+ return target_list.target_el_list().some(target_el => checkFunction_target_el(target_el, checkFunction));
2157
+ }
2158
+ return false;
2052
2159
  }
2053
2160
  function getTableName(table_ref) {
2054
2161
  const relation_expr = table_ref.relation_expr();
2055
- const tableName = relation_expr.qualified_name().getText();
2162
+ if (relation_expr) {
2163
+ return traverse_relation_expr(relation_expr);
2164
+ }
2056
2165
  const aliasClause = table_ref.alias_clause();
2057
- const tableAlias = aliasClause ? aliasClause.colid().getText() : '';
2058
2166
  return {
2059
- name: tableName,
2060
- alias: tableAlias
2167
+ name: aliasClause.colid().getText(),
2168
+ alias: ''
2061
2169
  };
2062
2170
  }
2063
- function isAggregateFunction_target_el(target_el) {
2171
+ function checkFunction_target_el(target_el, checkFunction) {
2064
2172
  if (target_el instanceof PostgreSQLParser_1.Target_labelContext) {
2065
2173
  const c_expr_list = collectContextsOfType(target_el, PostgreSQLParser_1.Func_exprContext, false);
2066
- const aggrFunction = c_expr_list.some(func_expr => isAggregateFunction_c_expr(func_expr));
2174
+ const aggrFunction = c_expr_list.some(func_expr => checkFunction(func_expr));
2067
2175
  return aggrFunction;
2068
2176
  }
2069
2177
  return false;
@@ -2116,25 +2224,98 @@ const aggregateFunctions = new Set([
2116
2224
  'variance',
2117
2225
  'xmlagg'
2118
2226
  ]);
2119
- function isAggregateFunction_c_expr(func_expr) {
2227
+ function isAggregateFunction(func_expr) {
2120
2228
  var _a, _b, _c;
2121
2229
  const funcName = (_c = (_b = (_a = func_expr === null || func_expr === void 0 ? void 0 : func_expr.func_application()) === null || _a === void 0 ? void 0 : _a.func_name()) === null || _b === void 0 ? void 0 : _b.getText()) === null || _c === void 0 ? void 0 : _c.toLowerCase();
2122
2230
  // RANK(), DENSE_RANK(), PERCENT_RANK() - they are window functions, not aggregate functions,
2123
2231
  // even though your query is returning them from a join involving pg_aggregate.
2124
2232
  return !func_expr.over_clause() && aggregateFunctions.has(funcName);
2125
2233
  }
2126
- function isSetReturningFunction_target_el(target_el) {
2127
- if (target_el instanceof PostgreSQLParser_1.Target_labelContext) {
2128
- const c_expr_list = collectContextsOfType(target_el, PostgreSQLParser_1.Func_exprContext);
2129
- const setReturningFunction = c_expr_list.some(func_expr => isSetReturningFunction_c_expr(func_expr));
2130
- return setReturningFunction;
2131
- }
2132
- return false;
2133
- }
2134
- function isSetReturningFunction_c_expr(func_expr) {
2234
+ // SELECT distinct '''' || p.proname || ''',' AS function_name
2235
+ // FROM pg_proc p
2236
+ // JOIN pg_namespace n ON p.pronamespace = n.oid
2237
+ // WHERE p.proretset = true
2238
+ // ORDER BY function_name;
2239
+ function isSetReturningFunction(func_expr) {
2135
2240
  var _a, _b, _c;
2136
2241
  const funcName = (_c = (_b = (_a = func_expr === null || func_expr === void 0 ? void 0 : func_expr.func_application()) === null || _a === void 0 ? void 0 : _a.func_name()) === null || _b === void 0 ? void 0 : _b.getText()) === null || _c === void 0 ? void 0 : _c.toLowerCase();
2137
- return funcName === 'generate_series';
2242
+ const setReturning = new Set([
2243
+ '_pg_expandarray',
2244
+ 'aclexplode',
2245
+ 'generate_series',
2246
+ 'generate_subscripts',
2247
+ 'get_clients_with_addresses',
2248
+ 'get_mytable1',
2249
+ 'get_mytable1_by_id',
2250
+ 'get_mytable1_with_nested_function',
2251
+ 'get_mytable_plpgsql',
2252
+ 'get_users_with_posts',
2253
+ 'get_users_with_posts_plpgsql',
2254
+ 'json_array_elements',
2255
+ 'json_array_elements_text',
2256
+ 'json_each',
2257
+ 'json_each_text',
2258
+ 'json_object_keys',
2259
+ 'json_populate_recordset',
2260
+ 'json_to_recordset',
2261
+ 'jsonb_array_elements',
2262
+ 'jsonb_array_elements_text',
2263
+ 'jsonb_each',
2264
+ 'jsonb_each_text',
2265
+ 'jsonb_object_keys',
2266
+ 'jsonb_path_query',
2267
+ 'jsonb_populate_recordset',
2268
+ 'jsonb_to_recordset',
2269
+ 'pg_available_extension_versions',
2270
+ 'pg_available_extensions',
2271
+ 'pg_config',
2272
+ 'pg_cursor',
2273
+ 'pg_event_trigger_ddl_commands',
2274
+ 'pg_event_trigger_dropped_objects',
2275
+ 'pg_extension_update_paths',
2276
+ 'pg_get_keywords',
2277
+ 'pg_get_multixact_members',
2278
+ 'pg_get_publication_tables',
2279
+ 'pg_get_replication_slots',
2280
+ 'pg_hba_file_rules',
2281
+ 'pg_listening_channels',
2282
+ 'pg_lock_status',
2283
+ 'pg_logical_slot_get_binary_changes',
2284
+ 'pg_logical_slot_get_changes',
2285
+ 'pg_logical_slot_peek_binary_changes',
2286
+ 'pg_logical_slot_peek_changes',
2287
+ 'pg_ls_archive_statusdir',
2288
+ 'pg_ls_dir',
2289
+ 'pg_ls_logdir',
2290
+ 'pg_ls_tmpdir',
2291
+ 'pg_ls_waldir',
2292
+ 'pg_mcv_list_items',
2293
+ 'pg_options_to_table',
2294
+ 'pg_partition_ancestors',
2295
+ 'pg_partition_tree',
2296
+ 'pg_prepared_statement',
2297
+ 'pg_prepared_xact',
2298
+ 'pg_show_all_file_settings',
2299
+ 'pg_show_all_settings',
2300
+ 'pg_show_replication_origin_status',
2301
+ 'pg_stat_get_activity',
2302
+ 'pg_stat_get_backend_idset',
2303
+ 'pg_stat_get_progress_info',
2304
+ 'pg_stat_get_wal_senders',
2305
+ 'pg_stop_backup',
2306
+ 'pg_tablespace_databases',
2307
+ 'pg_timezone_abbrevs',
2308
+ 'pg_timezone_names',
2309
+ 'regexp_matches',
2310
+ 'regexp_split_to_table',
2311
+ 'ts_debug',
2312
+ 'ts_parse',
2313
+ 'ts_stat',
2314
+ 'ts_token_type',
2315
+ 'txid_snapshot_xip',
2316
+ 'unnest'
2317
+ ]);
2318
+ return setReturning.has(funcName);
2138
2319
  }
2139
2320
  function isSingleRowResult_where(a_expr, uniqueKeys) {
2140
2321
  var _a, _b;