@nshiab/simple-data-analysis-core 0.0.27 → 0.1.1

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 (113) hide show
  1. package/esm/class/SimpleDB.d.ts +3 -8
  2. package/esm/class/SimpleDB.d.ts.map +1 -1
  3. package/esm/class/SimpleDB.js +8 -10
  4. package/esm/class/SimpleTable.d.ts +29 -48
  5. package/esm/class/SimpleTable.d.ts.map +1 -1
  6. package/esm/class/SimpleTable.js +170 -210
  7. package/esm/helpers/convertForJS.js +1 -1
  8. package/esm/helpers/findGeoColumn.js +2 -2
  9. package/esm/helpers/hasGeometryColumn.js +1 -1
  10. package/esm/helpers/logData.d.ts.map +1 -1
  11. package/esm/helpers/logData.js +7 -2
  12. package/esm/helpers/parseTypes.d.ts +1 -1
  13. package/esm/helpers/parseTypes.d.ts.map +1 -1
  14. package/esm/helpers/parseTypes.js +3 -1
  15. package/esm/helpers/setDbProps.d.ts +1 -1
  16. package/esm/helpers/setDbProps.d.ts.map +1 -1
  17. package/esm/helpers/setDbProps.js +5 -9
  18. package/esm/helpers/unifyColumns.d.ts +0 -2
  19. package/esm/helpers/unifyColumns.d.ts.map +1 -1
  20. package/esm/helpers/unifyColumns.js +2 -6
  21. package/esm/helpers/writeGeoData.d.ts.map +1 -1
  22. package/esm/helpers/writeGeoData.js +11 -41
  23. package/esm/helpers/writeIndexes.d.ts +3 -0
  24. package/esm/helpers/writeIndexes.d.ts.map +1 -0
  25. package/esm/helpers/writeIndexes.js +16 -0
  26. package/esm/methods/bm25.d.ts.map +1 -1
  27. package/esm/methods/bm25.js +1 -1
  28. package/esm/methods/cache.js +1 -1
  29. package/esm/methods/distanceQuery.d.ts.map +1 -1
  30. package/esm/methods/distanceQuery.js +4 -2
  31. package/esm/methods/fuzzyJoin.d.ts.map +1 -1
  32. package/esm/methods/fuzzyJoin.js +1 -6
  33. package/esm/methods/getGeoData.d.ts.map +1 -1
  34. package/esm/methods/getGeoData.js +1 -10
  35. package/esm/methods/join.d.ts.map +1 -1
  36. package/esm/methods/join.js +1 -7
  37. package/esm/methods/joinGeo.d.ts.map +1 -1
  38. package/esm/methods/joinGeo.js +1 -14
  39. package/esm/methods/joinGeoQuery.js +1 -1
  40. package/esm/methods/randomPointQuery.d.ts +1 -1
  41. package/esm/methods/randomPointQuery.d.ts.map +1 -1
  42. package/esm/methods/randomPointQuery.js +3 -3
  43. package/esm/methods/summarizeQuery.js +1 -1
  44. package/esm/methods/writeGeoDataQuery.js +2 -2
  45. package/package.json +2 -2
  46. package/script/class/SimpleDB.d.ts +3 -8
  47. package/script/class/SimpleDB.d.ts.map +1 -1
  48. package/script/class/SimpleDB.js +8 -10
  49. package/script/class/SimpleTable.d.ts +29 -48
  50. package/script/class/SimpleTable.d.ts.map +1 -1
  51. package/script/class/SimpleTable.js +170 -210
  52. package/script/helpers/convertForJS.js +1 -1
  53. package/script/helpers/findGeoColumn.js +2 -2
  54. package/script/helpers/hasGeometryColumn.js +1 -1
  55. package/script/helpers/logData.d.ts.map +1 -1
  56. package/script/helpers/logData.js +7 -2
  57. package/script/helpers/parseTypes.d.ts +1 -1
  58. package/script/helpers/parseTypes.d.ts.map +1 -1
  59. package/script/helpers/parseTypes.js +3 -1
  60. package/script/helpers/setDbProps.d.ts +1 -1
  61. package/script/helpers/setDbProps.d.ts.map +1 -1
  62. package/script/helpers/setDbProps.js +5 -9
  63. package/script/helpers/unifyColumns.d.ts +0 -2
  64. package/script/helpers/unifyColumns.d.ts.map +1 -1
  65. package/script/helpers/unifyColumns.js +2 -6
  66. package/script/helpers/writeGeoData.d.ts.map +1 -1
  67. package/script/helpers/writeGeoData.js +11 -41
  68. package/script/helpers/writeIndexes.d.ts +3 -0
  69. package/script/helpers/writeIndexes.d.ts.map +1 -0
  70. package/script/helpers/writeIndexes.js +19 -0
  71. package/script/methods/bm25.d.ts.map +1 -1
  72. package/script/methods/bm25.js +1 -1
  73. package/script/methods/cache.js +1 -1
  74. package/script/methods/distanceQuery.d.ts.map +1 -1
  75. package/script/methods/distanceQuery.js +4 -2
  76. package/script/methods/fuzzyJoin.d.ts.map +1 -1
  77. package/script/methods/fuzzyJoin.js +1 -6
  78. package/script/methods/getGeoData.d.ts.map +1 -1
  79. package/script/methods/getGeoData.js +1 -10
  80. package/script/methods/join.d.ts.map +1 -1
  81. package/script/methods/join.js +1 -7
  82. package/script/methods/joinGeo.d.ts.map +1 -1
  83. package/script/methods/joinGeo.js +1 -14
  84. package/script/methods/joinGeoQuery.js +1 -1
  85. package/script/methods/randomPointQuery.d.ts +1 -1
  86. package/script/methods/randomPointQuery.d.ts.map +1 -1
  87. package/script/methods/randomPointQuery.js +3 -3
  88. package/script/methods/summarizeQuery.js +1 -1
  89. package/script/methods/writeGeoDataQuery.js +2 -2
  90. package/esm/helpers/getProjection.d.ts +0 -3
  91. package/esm/helpers/getProjection.d.ts.map +0 -1
  92. package/esm/helpers/getProjection.js +0 -25
  93. package/esm/helpers/getProjectionParquet.d.ts +0 -3
  94. package/esm/helpers/getProjectionParquet.d.ts.map +0 -1
  95. package/esm/helpers/getProjectionParquet.js +0 -24
  96. package/esm/helpers/shouldFlipBeforeExport.d.ts +0 -2
  97. package/esm/helpers/shouldFlipBeforeExport.d.ts.map +0 -1
  98. package/esm/helpers/shouldFlipBeforeExport.js +0 -3
  99. package/esm/helpers/writeProjectionsAndIndexes.d.ts +0 -3
  100. package/esm/helpers/writeProjectionsAndIndexes.d.ts.map +0 -1
  101. package/esm/helpers/writeProjectionsAndIndexes.js +0 -29
  102. package/script/helpers/getProjection.d.ts +0 -3
  103. package/script/helpers/getProjection.d.ts.map +0 -1
  104. package/script/helpers/getProjection.js +0 -31
  105. package/script/helpers/getProjectionParquet.d.ts +0 -3
  106. package/script/helpers/getProjectionParquet.d.ts.map +0 -1
  107. package/script/helpers/getProjectionParquet.js +0 -30
  108. package/script/helpers/shouldFlipBeforeExport.d.ts +0 -2
  109. package/script/helpers/shouldFlipBeforeExport.d.ts.map +0 -1
  110. package/script/helpers/shouldFlipBeforeExport.js +0 -6
  111. package/script/helpers/writeProjectionsAndIndexes.d.ts +0 -3
  112. package/script/helpers/writeProjectionsAndIndexes.d.ts.map +0 -1
  113. package/script/helpers/writeProjectionsAndIndexes.js +0 -32
@@ -67,7 +67,6 @@ const summarize_js_1 = __importDefault(require("../methods/summarize.js"));
67
67
  const correlations_js_1 = __importDefault(require("../methods/correlations.js"));
68
68
  const linearRegressions_js_1 = __importDefault(require("../methods/linearRegressions.js"));
69
69
  const joinGeo_js_1 = __importDefault(require("../methods/joinGeo.js"));
70
- const getProjection_js_1 = __importDefault(require("../helpers/getProjection.js"));
71
70
  const cache_js_1 = __importDefault(require("../methods/cache.js"));
72
71
  const camelCase_js_1 = __importDefault(require("../helpers/camelCase.js"));
73
72
  const formatNumber_js_1 = __importDefault(require("../helpers/formatNumber.js"));
@@ -90,7 +89,6 @@ const getIdenticalColumns_js_1 = __importDefault(require("../helpers/getIdentica
90
89
  const capitalizeQuery_js_1 = __importDefault(require("../methods/capitalizeQuery.js"));
91
90
  const truncateQuery_js_1 = __importDefault(require("../methods/truncateQuery.js"));
92
91
  const padQuery_js_1 = __importDefault(require("../methods/padQuery.js"));
93
- const getProjectionParquet_js_1 = __importDefault(require("../helpers/getProjectionParquet.js"));
94
92
  const hasGeometryColumn_js_1 = __importDefault(require("../helpers/hasGeometryColumn.js"));
95
93
  const unifyColumns_js_1 = __importDefault(require("../helpers/unifyColumns.js"));
96
94
  const accumulateQuery_js_1 = __importDefault(require("../helpers/accumulateQuery.js"));
@@ -152,7 +150,6 @@ class SimpleTable extends Simple_js_1.default {
152
150
  * Creates an instance of SimpleTable.
153
151
  *
154
152
  * @param name - The name of the table.
155
- * @param projections - An object mapping column names to their geospatial projections.
156
153
  * @param simpleDB - The SimpleDB instance that this table belongs to.
157
154
  * @param options - An optional object with configuration options:
158
155
  * @param options.debug - A boolean indicating whether to enable debug mode.
@@ -161,7 +158,7 @@ class SimpleTable extends Simple_js_1.default {
161
158
  * @param options.types - A boolean indicating whether to include data types when logging a table.
162
159
  * @category Constructor
163
160
  */
164
- constructor(name, projections, simpleDB, options = {}) {
161
+ constructor(name, simpleDB, options = {}) {
165
162
  super(options);
166
163
  /**
167
164
  * Name of the table in the database.
@@ -175,19 +172,7 @@ class SimpleTable extends Simple_js_1.default {
175
172
  value: void 0
176
173
  });
177
174
  /**
178
- * The projections of the geospatial data, if any.
179
- *
180
- * @defaultValue `{}`
181
- * @category Properties
182
- */
183
- Object.defineProperty(this, "projections", {
184
- enumerable: true,
185
- configurable: true,
186
- writable: true,
187
- value: void 0
188
- });
189
- /**
190
- * The indexes of the table.
175
+ * The indexes of the table, if any.
191
176
  *
192
177
  * @defaultValue `[]`
193
178
  * @category Properties
@@ -199,7 +184,6 @@ class SimpleTable extends Simple_js_1.default {
199
184
  value: void 0
200
185
  });
201
186
  this.name = name;
202
- this.projections = projections;
203
187
  this.sdb = simpleDB;
204
188
  this.runQuery = runQuery_js_1.default;
205
189
  this.indexes = [];
@@ -247,8 +231,9 @@ class SimpleTable extends Simple_js_1.default {
247
231
  let spatial = "";
248
232
  if (Object.values(types)
249
233
  .map((d) => d.toLowerCase())
250
- .includes("geometry")) {
251
- spatial = "INSTALL spatial; LOAD spatial;\n";
234
+ .some((d) => d.startsWith("geometry"))) {
235
+ spatial =
236
+ "INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;\n";
252
237
  }
253
238
  await (0, queryDB_js_1.default)(this, `${spatial}CREATE OR REPLACE TABLE "${this.name}" (${Object.keys(types)
254
239
  .map((d) => `"${d}" ${(0, parseTypes_js_1.default)(types[d])}`)
@@ -403,12 +388,10 @@ class SimpleTable extends Simple_js_1.default {
403
388
  }
404
389
  /**
405
390
  * Loads geospatial data from an external file or URL into the table.
406
- * The coordinates of files or URLs ending with `.json` or `.geojson` are automatically flipped to `[latitude, longitude]` axis order.
407
391
  *
408
392
  * @param file - The URL or absolute path to the external file containing the geospatial data.
409
393
  * @param options - An optional object with configuration options:
410
- * @param options.toWGS84 - If `true`, the method will attempt to reproject the data to WGS84 with `[latitude, longitude]` axis order. If the file is `.json` or `.geojson`, coordinates are automatically flipped, and this option has no additional effect. Defaults to `false`.
411
- * @param options.from - An optional string specifying the original projection of the data, if the method is unable to detect it automatically.
394
+ * @param options.toWGS84 - If `true`, the method will attempt to reproject the data to WGS84.
412
395
  * @returns A promise that resolves to the SimpleTable instance after the geospatial data has been loaded.
413
396
  * @category Geospatial
414
397
  *
@@ -439,7 +422,7 @@ class SimpleTable extends Simple_js_1.default {
439
422
  async loadGeoData(file, options = {}) {
440
423
  const fileExtension = (0, getExtension_js_1.default)(file);
441
424
  if (fileExtension === "geoparquet" || fileExtension === "parquet") {
442
- await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial;${file.toLowerCase().includes("http")
425
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;${file.toLowerCase().includes("http")
443
426
  ? " INSTALL https; LOAD https;"
444
427
  : ""}
445
428
  CREATE OR REPLACE TABLE "${this.name}" AS SELECT * FROM read_parquet('${(0, cleanPath_js_1.default)(file)}');`, (0, mergeOptions_js_1.default)(this, {
@@ -447,32 +430,21 @@ class SimpleTable extends Simple_js_1.default {
447
430
  method: "loadGeoData()",
448
431
  parameters: { file, options },
449
432
  }));
450
- this.projections = await (0, getProjectionParquet_js_1.default)(this, file);
451
- if (options.toWGS84) {
452
- console.log("\nThis file is a parquet. Option toWGS84 has no effect. Use the .reproject() method instead.\n");
453
- }
454
433
  }
455
434
  else {
456
- await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial;${file.toLowerCase().includes("http")
435
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;${file.toLowerCase().includes("http")
457
436
  ? " INSTALL https; LOAD https;"
458
437
  : ""}
459
- CREATE OR REPLACE TABLE "${this.name}" AS SELECT * FROM ST_Read('${file}');`, (0, mergeOptions_js_1.default)(this, {
438
+ CREATE OR REPLACE TABLE "${this.name}" AS SELECT * EXCLUDE OGC_FID FROM ST_Read('${file}');`, (0, mergeOptions_js_1.default)(this, {
460
439
  table: this.name,
461
440
  method: "loadGeoData()",
462
441
  parameters: { file, options },
463
442
  }));
464
- // column storing geometries is geom by default
465
- this.projections["geom"] = await (0, getProjection_js_1.default)(this.sdb, file);
466
- const extension = (0, getExtension_js_1.default)(file);
467
- if (extension === "json" || extension === "geojson") {
468
- await this.flipCoordinates("geom"); // column storing geometries
469
- this.projections["geom"] = "+proj=latlong +datum=WGS84 +no_defs";
470
- if (options.toWGS84) {
471
- console.log("This file is a json or geojson. Option toWGS84 has no effect.");
472
- }
473
- }
474
- else if (options.toWGS84) {
475
- await this.reproject("WGS84", { ...options, column: "geom" }); // column storing geometries is geom by default
443
+ }
444
+ if (options.toWGS84) {
445
+ const geoType = await this.getProjection("geom");
446
+ if (geoType !== "GEOMETRY('EPSG:4326')") {
447
+ await this.reproject("EPSG:4326");
476
448
  }
477
449
  }
478
450
  return this;
@@ -764,9 +736,8 @@ class SimpleTable extends Simple_js_1.default {
764
736
  : [tablesToInsert];
765
737
  if (!await this.sdb.hasTable(this.name)) {
766
738
  await this.setTypes((await array[0].getTypes()));
767
- this.projections = structuredClone(array[0].projections);
768
739
  }
769
- // Checking columns, types and projections
740
+ // Checking columns, types
770
741
  if (!options.unifyColumns) {
771
742
  const thisColumns = (await this.getColumns()).sort().join(",");
772
743
  for (const table of array) {
@@ -778,27 +749,22 @@ class SimpleTable extends Simple_js_1.default {
778
749
  }
779
750
  const allTables = [this, ...array];
780
751
  const allTypes = {};
781
- const allProjections = {};
782
752
  for (const table of allTables) {
783
753
  const types = await table.getTypes();
784
754
  for (const key in types) {
785
755
  if (!allTypes[key]) {
786
756
  allTypes[key] = types[key];
787
- allProjections[key] = table.projections[key];
788
757
  }
789
758
  else {
790
759
  if (allTypes[key] !== types[key]) {
791
760
  throw new Error(`The column ${key} has different types in the tables.`);
792
761
  }
793
- else if (allProjections[key] !== table.projections[key]) {
794
- throw new Error(`The column ${key} has different projections in the tables.`);
795
- }
796
762
  }
797
763
  }
798
764
  }
799
765
  let columnsAdded = {};
800
766
  if (options.unifyColumns) {
801
- columnsAdded = await (0, unifyColumns_js_1.default)(allTables, allTypes, allProjections);
767
+ columnsAdded = await (0, unifyColumns_js_1.default)(allTables, allTypes);
802
768
  }
803
769
  await (0, queryDB_js_1.default)(this, array
804
770
  .map((tableToInsert) => `INSERT INTO "${this.name}" BY NAME SELECT * FROM "${tableToInsert.name}";`)
@@ -897,29 +863,16 @@ class SimpleTable extends Simple_js_1.default {
897
863
  const columns = typeof nameOrOptions === "object" && nameOrOptions.columns
898
864
  ? (0, stringToArray_js_1.default)(nameOrOptions.columns)
899
865
  : [];
900
- // Dealing with projections
901
- const clonedProjections = structuredClone(this.projections);
902
- let newProjections = {};
903
- if (columns.length > 0) {
904
- for (const col of columns) {
905
- if (clonedProjections[col]) {
906
- newProjections[col] = clonedProjections[col];
907
- }
908
- }
909
- }
910
- else {
911
- newProjections = clonedProjections;
912
- }
913
866
  // Delegate to sdb.newTable() so subclasses using tableClass work correctly.
914
867
  let clonedTable;
915
868
  const options = typeof nameOrOptions === "string"
916
869
  ? { outputTable: nameOrOptions }
917
870
  : nameOrOptions;
918
871
  if (typeof options.outputTable === "string") {
919
- clonedTable = this.sdb.newTable(options.outputTable, newProjections);
872
+ clonedTable = this.sdb.newTable(options.outputTable);
920
873
  }
921
874
  else {
922
- clonedTable = this.sdb.newTable(undefined, newProjections);
875
+ clonedTable = this.sdb.newTable(undefined);
923
876
  }
924
877
  await (0, queryDB_js_1.default)(this, (0, cloneQuery_js_1.default)(this.name, clonedTable.name, columns, options), (0, mergeOptions_js_1.default)(this, {
925
878
  table: clonedTable.name,
@@ -950,9 +903,6 @@ class SimpleTable extends Simple_js_1.default {
950
903
  method: "cloneColumn()",
951
904
  parameters: { originalColumn, newColumn },
952
905
  }));
953
- if (typeof this.projections[originalColumn] === "string") {
954
- this.projections[newColumn] = this.projections[originalColumn];
955
- }
956
906
  }
957
907
  /**
958
908
  * Clones a column in the table and offsets its values by a specified number of rows.
@@ -1017,9 +967,6 @@ class SimpleTable extends Simple_js_1.default {
1017
967
  method: "cloneColumnWithOffset()",
1018
968
  parameters: { originalColumn, newColumn },
1019
969
  }));
1020
- if (typeof this.projections[originalColumn] === "string") {
1021
- this.projections[newColumn] = this.projections[originalColumn];
1022
- }
1023
970
  }
1024
971
  /**
1025
972
  * Fills `NULL` values in specified columns. By default, each `NULL` is replaced with the last non-`NULL` value from the preceding row. When `interpolate` is `true`, `NULL` values are replaced using linear interpolation (or extrapolation at the ends). Pass `interpolateBy` with a real numeric or date column name to use it as the X-axis, so that interpolated values are proportional to the actual distances between X-axis values rather than treating every row as equidistant. When `interpolateBy` is set, `interpolate` is automatically assumed `true`.
@@ -1265,7 +1212,7 @@ class SimpleTable extends Simple_js_1.default {
1265
1212
  parameters: { count, options },
1266
1213
  }));
1267
1214
  if (typeof options.outputTable === "string") {
1268
- return this.sdb.newTable(options.outputTable, this.projections);
1215
+ return this.sdb.newTable(options.outputTable);
1269
1216
  }
1270
1217
  else {
1271
1218
  return this;
@@ -1538,15 +1485,6 @@ class SimpleTable extends Simple_js_1.default {
1538
1485
  method: "renameColumns()",
1539
1486
  parameters: { names },
1540
1487
  }));
1541
- // Taking care of projections
1542
- const types = await this.getTypes();
1543
- for (let i = 0; i < newNames.length; i++) {
1544
- if (types[newNames[i]] === "GEOMETRY") {
1545
- const projection = this.projections[oldNames[i]];
1546
- delete this.projections[oldNames[i]];
1547
- this.projections[newNames[i]] = projection;
1548
- }
1549
- }
1550
1488
  }
1551
1489
  /**
1552
1490
  * Cleans column names by removing non-alphanumeric characters and formatting them to camel case.
@@ -1763,12 +1701,6 @@ class SimpleTable extends Simple_js_1.default {
1763
1701
  method: "removeColumns()",
1764
1702
  parameters: { columns },
1765
1703
  }));
1766
- // Taking care of projections
1767
- for (const col of cols) {
1768
- if (Object.prototype.hasOwnProperty.call(this.projections, col)) {
1769
- delete this.projections[col];
1770
- }
1771
- }
1772
1704
  }
1773
1705
  /**
1774
1706
  * Adds a new column to the table based on a specified data type (JavaScript or SQL types) and a SQL definition.
@@ -1777,7 +1709,6 @@ class SimpleTable extends Simple_js_1.default {
1777
1709
  * @param type - The data type for the new column. Can be a JavaScript type (e.g., `"number"`, `"string"`) or a SQL type (e.g., `"integer"`, `"varchar"`).
1778
1710
  * @param definition - A SQL expression defining how the values for the new column should be computed (e.g., `"column1 + column2"`, `"ST_Centroid(geom_column)"`).
1779
1711
  * @param options - An optional object with configuration options:
1780
- * @param options.projection - Required if the new column stores geometries. Specifies the geospatial projection of the new geometry column. You can reuse the projection of an existing geometry column (available in `table.projections`).
1781
1712
  * @returns A promise that resolves when the new column has been added.
1782
1713
  * @category Column Operations
1783
1714
  *
@@ -1790,28 +1721,21 @@ class SimpleTable extends Simple_js_1.default {
1790
1721
  * @example
1791
1722
  * ```ts
1792
1723
  * // Add a new geometry column 'centroid' using the centroid of an existing 'country' geometry column
1793
- * // The projection of the new 'centroid' column is set to be the same as 'country'.
1794
- * await table.addColumn("centroid", "geometry", `ST_Centroid("country")`, {
1795
- * projection: table.projections.country,
1796
- * });
1724
+ * await table.addColumn("centroid", "geometry('EPSG:4326')", `ST_Centroid("country")`);
1797
1725
  * ```
1798
1726
  */
1799
- async addColumn(newColumn, type, definition, options = {}) {
1727
+ async addColumn(newColumn, type, definition) {
1800
1728
  const newType = (0, parseTypes_js_1.default)(type);
1801
- await (0, queryDB_js_1.default)(this, `ALTER TABLE "${this.name}" ADD "${newColumn}" ${newType};
1729
+ let spatial = "";
1730
+ if (newType.toLowerCase().includes("geometry")) {
1731
+ spatial = "INSTALL spatial; LOAD spatial; SET geometry_always_xy = true;";
1732
+ }
1733
+ await (0, queryDB_js_1.default)(this, `${spatial} ALTER TABLE "${this.name}" ADD "${newColumn}" ${newType};
1802
1734
  UPDATE "${this.name}" SET "${newColumn}" = ${definition}`, (0, mergeOptions_js_1.default)(this, {
1803
1735
  table: this.name,
1804
1736
  method: "addColumn()",
1805
1737
  parameters: { newColumn, type, definition },
1806
1738
  }));
1807
- if (newType === "GEOMETRY") {
1808
- if (typeof options.projection === "string") {
1809
- this.projections[newColumn] = options.projection;
1810
- }
1811
- else {
1812
- throw new Error("You are creating a new column storing geometries. You must specify a projection. See examples in documentation.");
1813
- }
1814
- }
1815
1739
  }
1816
1740
  /**
1817
1741
  * Adds a new column to the table containing the row number, starting at 0 (like an index).
@@ -1891,15 +1815,10 @@ class SimpleTable extends Simple_js_1.default {
1891
1815
  method: "crossJoin()",
1892
1816
  parameters: { rightTable, options },
1893
1817
  }));
1894
- const allProjections = {
1895
- ...this.projections,
1896
- ...rightTable.projections,
1897
- };
1898
1818
  if (typeof options.outputTable === "string") {
1899
- return this.sdb.newTable(options.outputTable, allProjections);
1819
+ return this.sdb.newTable(options.outputTable);
1900
1820
  }
1901
1821
  else {
1902
- this.projections = allProjections;
1903
1822
  return this;
1904
1823
  }
1905
1824
  }
@@ -3034,7 +2953,7 @@ class SimpleTable extends Simple_js_1.default {
3034
2953
  }
3035
2954
  await (0, summarize_js_1.default)(this, options);
3036
2955
  if (typeof options.outputTable === "string") {
3037
- return this.sdb.newTable(options.outputTable, this.projections);
2956
+ return this.sdb.newTable(options.outputTable);
3038
2957
  }
3039
2958
  else {
3040
2959
  return this;
@@ -3176,7 +3095,7 @@ class SimpleTable extends Simple_js_1.default {
3176
3095
  }
3177
3096
  await (0, correlations_js_1.default)(this, options);
3178
3097
  if (typeof options.outputTable === "string") {
3179
- return this.sdb.newTable(options.outputTable, this.projections);
3098
+ return this.sdb.newTable(options.outputTable);
3180
3099
  }
3181
3100
  else {
3182
3101
  return this;
@@ -3233,7 +3152,7 @@ class SimpleTable extends Simple_js_1.default {
3233
3152
  }
3234
3153
  await (0, linearRegressions_js_1.default)(this, options);
3235
3154
  if (typeof options.outputTable === "string") {
3236
- return this.sdb.newTable(options.outputTable, this.projections);
3155
+ return this.sdb.newTable(options.outputTable);
3237
3156
  }
3238
3157
  else {
3239
3158
  return this;
@@ -4088,7 +4007,7 @@ class SimpleTable extends Simple_js_1.default {
4088
4007
  }
4089
4008
  // GEOSPATIAL
4090
4009
  /**
4091
- * Creates point geometries from longitude and latitude columns. The geometries will have `[latitude, longitude]` axis order.
4010
+ * Creates point geometries from latitude and longitude columns.
4092
4011
  *
4093
4012
  * @param columnLat - The name of the column storing the latitude values.
4094
4013
  * @param columnLon - The name of the column storing the longitude values.
@@ -4104,13 +4023,12 @@ class SimpleTable extends Simple_js_1.default {
4104
4023
  */
4105
4024
  async points(columnLat, columnLon, newColumn) {
4106
4025
  await (0, queryDB_js_1.default)(this, (await this.getColumns()).includes(newColumn)
4107
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Point2D("${columnLat}", "${columnLon}")`
4108
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD COLUMN "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Point2D("${columnLat}", "${columnLon}")`, (0, mergeOptions_js_1.default)(this, {
4026
+ ? `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Point("${columnLon}", "${columnLat}")::GEOMETRY('EPSG:4326') AS "${newColumn}") FROM "${this.name}"`
4027
+ : `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD COLUMN "${newColumn}" GEOMETRY('EPSG:4326'); UPDATE "${this.name}" SET "${newColumn}" = ST_Point("${columnLon}", "${columnLat}");`, (0, mergeOptions_js_1.default)(this, {
4109
4028
  table: this.name,
4110
4029
  method: "points()",
4111
4030
  parameters: { columnLat, columnLon, newColumn },
4112
4031
  }));
4113
- this.projections[newColumn] = "+proj=latlong +datum=WGS84 +no_defs";
4114
4032
  }
4115
4033
  /**
4116
4034
  * Adds a column with boolean values indicating the validity of geometries.
@@ -4197,7 +4115,8 @@ class SimpleTable extends Simple_js_1.default {
4197
4115
  */
4198
4116
  async fixGeo(column) {
4199
4117
  const col = column ?? (await (0, findGeoColumn_js_1.default)(this));
4200
- await (0, queryDB_js_1.default)(this, `UPDATE "${this.name}" SET "${col}" = ST_MakeValid("${col}")`, (0, mergeOptions_js_1.default)(this, {
4118
+ const geoType = await this.getProjection(col);
4119
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_MakeValid("${col}")::${geoType} AS "${col}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4201
4120
  table: this.name,
4202
4121
  method: "fixGeo()",
4203
4122
  parameters: { column },
@@ -4267,7 +4186,7 @@ class SimpleTable extends Simple_js_1.default {
4267
4186
  }
4268
4187
  /**
4269
4188
  * Flips the coordinate order of geometries in a specified column (e.g., from `[lon, lat]` to `[lat, lon]` or vice-versa).
4270
- * **Warning:** This method should be used with caution as it directly manipulates coordinate order and can affect the accuracy of geospatial operations if not used correctly. It also messes up with the projections stored in `table.projections`.
4189
+ * **Warning:** This method should be used with caution as it directly manipulates coordinate order and can affect the accuracy of geospatial operations if not used correctly.
4271
4190
  *
4272
4191
  * @param column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.
4273
4192
  * @returns A promise that resolves when the coordinates have been flipped.
@@ -4287,7 +4206,8 @@ class SimpleTable extends Simple_js_1.default {
4287
4206
  */
4288
4207
  async flipCoordinates(column) {
4289
4208
  const col = column ?? (await (0, findGeoColumn_js_1.default)(this));
4290
- await (0, queryDB_js_1.default)(this, `UPDATE "${this.name}" SET "${col}" = ST_FlipCoordinates("${col}")`, (0, mergeOptions_js_1.default)(this, {
4209
+ const geoType = await this.getProjection(col);
4210
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_FlipCoordinates("${col}")::${geoType} AS "${col}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4291
4211
  table: this.name,
4292
4212
  method: "flipCoordinates()",
4293
4213
  parameters: { column },
@@ -4318,7 +4238,8 @@ class SimpleTable extends Simple_js_1.default {
4318
4238
  const column = typeof options.column === "string"
4319
4239
  ? options.column
4320
4240
  : await (0, findGeoColumn_js_1.default)(this);
4321
- await (0, queryDB_js_1.default)(this, `UPDATE "${this.name}" SET "${column}" = ST_ReducePrecision("${column}", ${1 / Math.pow(10, decimals)})`, (0, mergeOptions_js_1.default)(this, {
4241
+ const geoType = await this.getProjection(column);
4242
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_ReducePrecision("${column}", ${1 / Math.pow(10, decimals)})::${geoType} AS "${column}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4322
4243
  table: this.name,
4323
4244
  method: "reducePrecision()",
4324
4245
  parameters: { column, decimals },
@@ -4326,11 +4247,9 @@ class SimpleTable extends Simple_js_1.default {
4326
4247
  }
4327
4248
  /**
4328
4249
  * Reprojects the geometries in a specified column to another Spatial Reference System (SRS).
4329
- * If reprojecting to WGS84 (`"WGS84"` or `"EPSG:4326"`), the resulting geometries will have `[latitude, longitude]` axis order.
4330
4250
  *
4331
4251
  * @param to - The target SRS (e.g., `"EPSG:3347"`, `"WGS84"`).
4332
4252
  * @param options - An optional object with configuration options:
4333
- * @param options.from - The original projection of the geometries. If omitted, the method attempts to automatically detect it. Provide this option if auto-detection fails.
4334
4253
  * @param options.column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.
4335
4254
  * @returns A promise that resolves when the geometries have been reprojected.
4336
4255
  * @category Geospatial
@@ -4343,43 +4262,25 @@ class SimpleTable extends Simple_js_1.default {
4343
4262
  *
4344
4263
  * @example
4345
4264
  * ```ts
4346
- * // Reproject geometries from EPSG:4326 to EPSG:3347, specifying the original projection
4347
- * await table.reproject("EPSG:3347", { from: "EPSG:4326" });
4348
- * ```
4349
- *
4350
- * @example
4351
- * ```ts
4352
4265
  * // Reproject geometries in a specific column named 'myGeom' to EPSG:3347
4353
- * await table.reproject("EPSG:3347", { column: "myGeom", from: "EPSG:4326" });
4266
+ * await table.reproject("EPSG:3347", { column: "myGeom" });
4354
4267
  * ```
4355
4268
  */
4356
4269
  async reproject(to, options = {}) {
4270
+ const cleanedTo = to.replace("WGS84", "EPSG:4326");
4271
+ const targetGeoType = `GEOMETRY${cleanedTo !== "null" ? `('${cleanedTo}')` : ""}`;
4357
4272
  const column = typeof options.column === "string"
4358
4273
  ? options.column
4359
4274
  : await (0, findGeoColumn_js_1.default)(this);
4360
- const from = options.from ?? this.projections[column];
4361
- if (typeof from !== "string" || from === "") {
4362
- throw new Error("Method reproject can't determine the original projection. Use the option 'from' to provide one.");
4363
- }
4364
- if (from === "+proj=latlong +datum=WGS84 +no_defs") {
4365
- await this.flipCoordinates(column);
4366
- }
4367
- if (to.toUpperCase() === "WGS84" || to.toUpperCase() === "EPSG:4326") {
4368
- to = "+proj=latlong +datum=WGS84 +no_defs";
4369
- }
4370
- await (0, queryDB_js_1.default)(this, `UPDATE "${this.name}" SET "${column}" = ST_Transform("${column}", '${from}', '${to}')`, (0, mergeOptions_js_1.default)(this, {
4275
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Transform("${column}", '${cleanedTo}')::${targetGeoType} AS "${column}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4371
4276
  table: this.name,
4372
4277
  method: "reproject()",
4373
4278
  parameters: { column, to },
4374
4279
  }));
4375
- this.projections[column] = to;
4376
- if (this.projections[column] === "+proj=latlong +datum=WGS84 +no_defs") {
4377
- await this.flipCoordinates(column);
4378
- }
4379
4280
  }
4380
4281
  /**
4381
4282
  * Computes the area of geometries in square meters (`"m2"`) or optionally square kilometers (`"km2"`).
4382
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4283
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4383
4284
  *
4384
4285
  * @param newColumn - The name of the new column where the computed areas will be stored.
4385
4286
  * @param options - An optional object with configuration options:
@@ -4418,7 +4319,7 @@ class SimpleTable extends Simple_js_1.default {
4418
4319
  }
4419
4320
  /**
4420
4321
  * Computes the length of line geometries in meters (`"m"`) or optionally kilometers (`"km"`).
4421
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4322
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4422
4323
  *
4423
4324
  * @param newColumn - The name of the new column where the computed lengths will be stored.
4424
4325
  * @param options - An optional object with configuration options:
@@ -4457,7 +4358,7 @@ class SimpleTable extends Simple_js_1.default {
4457
4358
  }
4458
4359
  /**
4459
4360
  * Computes the perimeter of polygon geometries in meters (`"m"`) or optionally kilometers (`"km"`).
4460
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4361
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4461
4362
  *
4462
4363
  * @param newColumn - The name of the new column where the computed perimeters will be stored.
4463
4364
  * @param options - An optional object with configuration options:
@@ -4521,14 +4422,22 @@ class SimpleTable extends Simple_js_1.default {
4521
4422
  const column = typeof options.column === "string"
4522
4423
  ? options.column
4523
4424
  : await (0, findGeoColumn_js_1.default)(this);
4524
- await (0, queryDB_js_1.default)(this, (await this.getColumns()).includes(newColumn)
4525
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`
4526
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`, (0, mergeOptions_js_1.default)(this, {
4527
- table: this.name,
4528
- method: "buffer()",
4529
- parameters: { column, newColumn, distance },
4530
- }));
4531
- this.projections[newColumn] = this.projections[column];
4425
+ const geoType = await this.getProjection(column);
4426
+ const columns = await this.getColumns();
4427
+ if (columns.includes(newColumn)) {
4428
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Buffer("${column}", ${distance})::${geoType} AS "${newColumn}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4429
+ table: this.name,
4430
+ method: "buffer()",
4431
+ parameters: { column, newColumn, distance },
4432
+ }));
4433
+ }
4434
+ else {
4435
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" ${geoType}; UPDATE "${this.name}" SET "${newColumn}" = ST_Buffer("${column}", ${distance})`, (0, mergeOptions_js_1.default)(this, {
4436
+ table: this.name,
4437
+ method: "buffer()",
4438
+ parameters: { column, newColumn, distance },
4439
+ }));
4440
+ }
4532
4441
  }
4533
4442
  /**
4534
4443
  * Merges the data of this table (considered the left table) with another table (the right table) based on a spatial relationship.
@@ -4606,17 +4515,22 @@ class SimpleTable extends Simple_js_1.default {
4606
4515
  * ```
4607
4516
  */
4608
4517
  async intersection(column1, column2, newColumn) {
4609
- if (this.projections[column1] !== this.projections[column2]) {
4610
- throw new Error(`${column1} and ${column2} don't have the same projection.\n${column1}: ${this.projections[column1]}\n${column2}: ${this.projections[column2]}`);
4518
+ const geoType = await this.getProjection(column1);
4519
+ const columns = await this.getColumns();
4520
+ if (columns.includes(newColumn)) {
4521
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Intersection("${column1}", "${column2}")::${geoType} AS "${newColumn}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4522
+ table: this.name,
4523
+ method: "intersection()",
4524
+ parameters: { column1, column2, newColumn },
4525
+ }));
4526
+ }
4527
+ else {
4528
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" ${geoType}; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`, (0, mergeOptions_js_1.default)(this, {
4529
+ table: this.name,
4530
+ method: "intersection()",
4531
+ parameters: { column1, column2, newColumn },
4532
+ }));
4611
4533
  }
4612
- await (0, queryDB_js_1.default)(this, (await this.getColumns()).includes(newColumn)
4613
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`
4614
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Intersection("${column1}", "${column2}")`, (0, mergeOptions_js_1.default)(this, {
4615
- table: this.name,
4616
- method: "intersection()",
4617
- parameters: { column1, column2, newColumn },
4618
- }));
4619
- this.projections[newColumn] = this.projections[column1];
4620
4534
  }
4621
4535
  /**
4622
4536
  * Removes the intersection of two geometries from the first geometry, effectively computing the geometric difference.
@@ -4634,17 +4548,22 @@ class SimpleTable extends Simple_js_1.default {
4634
4548
  * ```
4635
4549
  */
4636
4550
  async removeIntersection(column1, column2, newColumn) {
4637
- if (this.projections[column1] !== this.projections[column2]) {
4638
- throw new Error(`${column1} and ${column2} don't have the same projection.\n${column1}: ${this.projections[column1]}\n${column2}: ${this.projections[column2]}`);
4551
+ const geoType = await this.getProjection(column1);
4552
+ const columns = await this.getColumns();
4553
+ if (columns.includes(newColumn)) {
4554
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Difference("${column1}", "${column2}")::${geoType} AS "${newColumn}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4555
+ table: this.name,
4556
+ method: "removeIntersection()",
4557
+ parameters: { column1, column2, newColumn },
4558
+ }));
4559
+ }
4560
+ else {
4561
+ await (0, queryDB_js_1.default)(this, `ALTER TABLE "${this.name}" ADD "${newColumn}" ${geoType}; UPDATE "${this.name}" SET "${newColumn}" = ST_Difference("${column1}", "${column2}")`, (0, mergeOptions_js_1.default)(this, {
4562
+ table: this.name,
4563
+ method: "removeIntersection()",
4564
+ parameters: { column1, column2, newColumn },
4565
+ }));
4639
4566
  }
4640
- await (0, queryDB_js_1.default)(this, (await this.getColumns()).includes(newColumn)
4641
- ? `UPDATE "${this.name}" SET "${newColumn}" = ST_Difference("${column1}", "${column2}")`
4642
- : `ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Difference("${column1}", "${column2}")`, (0, mergeOptions_js_1.default)(this, {
4643
- table: this.name,
4644
- method: "removeIntersection()",
4645
- parameters: { column1, column2, newColumn },
4646
- }));
4647
- this.projections[newColumn] = this.projections[column1];
4648
4567
  }
4649
4568
  /**
4650
4569
  * Fills holes in polygon geometries.
@@ -4733,21 +4652,26 @@ class SimpleTable extends Simple_js_1.default {
4733
4652
  * ```
4734
4653
  */
4735
4654
  async union(column1, column2, newColumn) {
4736
- if (this.projections[column1] !== this.projections[column2]) {
4737
- throw new Error(`${column1} and ${column2} don't have the same projection.\n${column1}: ${this.projections[column1]}\n${column2}: ${this.projections[column2]}`);
4655
+ const geoType = await this.getProjection(column1);
4656
+ const columns = await this.getColumns();
4657
+ if (columns.includes(newColumn)) {
4658
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Union("${column1}", "${column2}")::${geoType} AS "${newColumn}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4659
+ table: this.name,
4660
+ method: "union()",
4661
+ parameters: { column1, column2, newColumn },
4662
+ }));
4663
+ }
4664
+ else {
4665
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" ${geoType}; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`, (0, mergeOptions_js_1.default)(this, {
4666
+ table: this.name,
4667
+ method: "union()",
4668
+ parameters: { column1, column2, newColumn },
4669
+ }));
4738
4670
  }
4739
- await (0, queryDB_js_1.default)(this, (await this.getColumns()).includes(newColumn)
4740
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`
4741
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Union("${column1}", "${column2}")`, (0, mergeOptions_js_1.default)(this, {
4742
- table: this.name,
4743
- method: "union()",
4744
- parameters: { column1, column2, newColumn },
4745
- }));
4746
- this.projections[newColumn] = this.projections[column1];
4747
4671
  }
4748
4672
  /**
4749
4673
  * Extracts the latitude and longitude coordinates from point geometries.
4750
- * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4674
+ * The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
4751
4675
  *
4752
4676
  * @param column - The name of the column storing the point geometries.
4753
4677
  * @param columnLat - The name of the new column where the extracted latitude values will be stored.
@@ -4762,8 +4686,8 @@ class SimpleTable extends Simple_js_1.default {
4762
4686
  * ```
4763
4687
  */
4764
4688
  async latLon(column, columnLat, columnLon) {
4765
- await (0, queryDB_js_1.default)(this, `ALTER TABLE "${this.name}" ADD "${columnLat}" DOUBLE; UPDATE "${this.name}" SET "${columnLat}" = ST_X("${column}");
4766
- ALTER TABLE "${this.name}" ADD "${columnLon}" DOUBLE; UPDATE "${this.name}" SET "${columnLon}" = ST_Y("${column}");`, (0, mergeOptions_js_1.default)(this, {
4689
+ await (0, queryDB_js_1.default)(this, `ALTER TABLE "${this.name}" ADD "${columnLat}" DOUBLE; UPDATE "${this.name}" SET "${columnLat}" = ST_Y("${column}");
4690
+ ALTER TABLE "${this.name}" ADD "${columnLon}" DOUBLE; UPDATE "${this.name}" SET "${columnLon}" = ST_X("${column}");`, (0, mergeOptions_js_1.default)(this, {
4767
4691
  table: this.name,
4768
4692
  method: "latLon()",
4769
4693
  parameters: { column, columnLon, columnLat },
@@ -4796,7 +4720,8 @@ class SimpleTable extends Simple_js_1.default {
4796
4720
  ? options.column
4797
4721
  : await (0, findGeoColumn_js_1.default)(this);
4798
4722
  await this.addRowNumber("rowNumberForSimplify");
4799
- await (0, queryDB_js_1.default)(this, `CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE(ST_CoverageSimplify(ARRAY_AGG("${column}"), ${tolerance}${options.simplifyBoundary === false ? ", FAlSE" : ""}) AS "${column}") FROM "${this.name}" GROUP BY ALL;`, (0, mergeOptions_js_1.default)(this, {
4723
+ const geoType = await this.getProjection(column);
4724
+ await (0, queryDB_js_1.default)(this, `CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE(ST_CoverageSimplify(ARRAY_AGG("${column}"), ${tolerance}${options.simplifyBoundary === false ? ", FAlSE" : ""})::${geoType} AS "${column}") FROM "${this.name}" GROUP BY ALL;`, (0, mergeOptions_js_1.default)(this, {
4800
4725
  table: this.name,
4801
4726
  method: "simplify()",
4802
4727
  parameters: { column, tolerance },
@@ -4829,14 +4754,22 @@ class SimpleTable extends Simple_js_1.default {
4829
4754
  const column = typeof options.column === "string"
4830
4755
  ? options.column
4831
4756
  : await (0, findGeoColumn_js_1.default)(this);
4832
- await (0, queryDB_js_1.default)(this, (await this.getColumns()).includes(newColumn)
4833
- ? `INSTALL spatial; LOAD spatial; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`
4834
- : `INSTALL spatial; LOAD spatial; ALTER TABLE "${this.name}" ADD "${newColumn}" GEOMETRY; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`, (0, mergeOptions_js_1.default)(this, {
4835
- table: this.name,
4836
- method: "centroid()",
4837
- parameters: { column, newColumn },
4838
- }));
4839
- this.projections[newColumn] = this.projections[column];
4757
+ const geoType = await this.getProjection(column);
4758
+ const columns = await this.getColumns();
4759
+ if (columns.includes(newColumn)) {
4760
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; CREATE OR REPLACE TABLE "${this.name}" AS SELECT * REPLACE (ST_Centroid("${column}")::${geoType} AS "${newColumn}") FROM "${this.name}"`, (0, mergeOptions_js_1.default)(this, {
4761
+ table: this.name,
4762
+ method: "centroid()",
4763
+ parameters: { column, newColumn },
4764
+ }));
4765
+ }
4766
+ else {
4767
+ await (0, queryDB_js_1.default)(this, `INSTALL spatial; LOAD spatial; SET geometry_always_xy = true; ALTER TABLE "${this.name}" ADD "${newColumn}" ${geoType}; UPDATE "${this.name}" SET "${newColumn}" = ST_Centroid("${column}")`, (0, mergeOptions_js_1.default)(this, {
4768
+ table: this.name,
4769
+ method: "centroid()",
4770
+ parameters: { column, newColumn },
4771
+ }));
4772
+ }
4840
4773
  }
4841
4774
  /**
4842
4775
  * Generates a random point within the geometries of a specified column.
@@ -4872,10 +4805,11 @@ class SimpleTable extends Simple_js_1.default {
4872
4805
  const column = typeof options.column === "string"
4873
4806
  ? options.column
4874
4807
  : await (0, findGeoColumn_js_1.default)(this);
4875
- await (0, queryDB_js_1.default)(this, (0, randomPointQuery_js_1.default)(this.name, column, newColumn, nbPointsToTry), (0, mergeOptions_js_1.default)(this, {
4808
+ const geoType = await this.getProjection(column);
4809
+ await (0, queryDB_js_1.default)(this, (0, randomPointQuery_js_1.default)(this.name, column, newColumn, nbPointsToTry, geoType), (0, mergeOptions_js_1.default)(this, {
4876
4810
  table: this.name,
4877
4811
  method: "randomPoint()",
4878
- parameters: { column, newColumn, nbPointsToTry, options },
4812
+ parameters: { column, newColumn, nbPointsToTry, options, geoType },
4879
4813
  }));
4880
4814
  const nbNulls = await this.getNbRows({
4881
4815
  conditions: `"${newColumn}" IS NULL`,
@@ -4883,13 +4817,12 @@ class SimpleTable extends Simple_js_1.default {
4883
4817
  if (nbNulls > 0 && !options.try) {
4884
4818
  throw new Error(`${nbNulls} points could not be generated. Consider increasing nbPointsToTry or set options.try to true.`);
4885
4819
  }
4886
- this.projections[newColumn] = this.projections[column];
4887
4820
  }
4888
4821
  /**
4889
4822
  * Computes the distance between geometries in two specified columns.
4890
4823
  * By default, the distance is calculated in the Spatial Reference System (SRS) unit of the input geometries.
4891
4824
  * You can optionally specify `"spheroid"` or `"haversine"` methods to get results in meters or kilometers.
4892
- * If using `"spheroid"` or `"haversine"`, the input geometries must be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4825
+ * If using `"spheroid"` or `"haversine"`, the input geometries must be in the EPSG:4326 coordinate system (WGS84).
4893
4826
  *
4894
4827
  * @param column1 - The name of the first column storing geometries.
4895
4828
  * @param column2 - The name of the second column storing geometries.
@@ -5005,7 +4938,7 @@ class SimpleTable extends Simple_js_1.default {
5005
4938
  parameters: { column, method, options },
5006
4939
  }));
5007
4940
  if (typeof options.outputTable === "string") {
5008
- return this.sdb.newTable(options.outputTable, this.projections);
4941
+ return this.sdb.newTable(options.outputTable);
5009
4942
  }
5010
4943
  else {
5011
4944
  return this;
@@ -5040,7 +4973,7 @@ class SimpleTable extends Simple_js_1.default {
5040
4973
  }
5041
4974
  /**
5042
4975
  * Returns the bounding box of geometries in `[minLat, minLon, maxLat, maxLon]` order.
5043
- * By default, the method will try to find the column with the geometries. The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84), with `[latitude, longitude]` axis order.
4976
+ * By default, the method will try to find the column with the geometries. The input geometry is assumed to be in the EPSG:4326 coordinate system (WGS84).
5044
4977
  *
5045
4978
  * @param column - The name of the column storing geometries. If omitted, the method will automatically attempt to find a geometry column.
5046
4979
  * @returns A promise that resolves to an array `[minLat, minLon, maxLat, maxLon]` representing the bounding box.
@@ -5063,10 +4996,10 @@ class SimpleTable extends Simple_js_1.default {
5063
4996
  async getBoundingBox(column) {
5064
4997
  const col = column ?? (await (0, findGeoColumn_js_1.default)(this));
5065
4998
  const result = (await (0, queryDB_js_1.default)(this, `SELECT
5066
- MIN(ST_XMin("${col}")) AS minX,
5067
- MIN(ST_YMin("${col}")) AS minY,
5068
- MAX(ST_XMax("${col}")) AS maxX,
5069
- MAX(ST_YMax("${col}")) AS maxY,
4999
+ MIN(ST_YMin("${col}")) AS minX,
5000
+ MIN(ST_XMin("${col}")) AS minY,
5001
+ MAX(ST_YMax("${col}")) AS maxX,
5002
+ MAX(ST_XMax("${col}")) AS maxY,
5070
5003
  from "${this.name}";`, (0, mergeOptions_js_1.default)(this, {
5071
5004
  table: this.name,
5072
5005
  method: "getBoundingBox()",
@@ -5078,7 +5011,6 @@ class SimpleTable extends Simple_js_1.default {
5078
5011
  /**
5079
5012
  * Returns the table's geospatial data as a GeoJSON object.
5080
5013
  * If the table has multiple geometry columns, you must specify which one to use.
5081
- * If the geometry column's projection is WGS84 or EPSG:4326 (`[latitude, longitude]` axis order), the coordinates will be flipped to follow the RFC7946 standard (`[longitude, latitude]` axis order) in the output GeoJSON.
5082
5014
  *
5083
5015
  * @param column - The name of the column storing the geometries. If omitted, the method will automatically attempt to find a geometry column.
5084
5016
  * @param options - An optional object with configuration options:
@@ -5183,8 +5115,6 @@ class SimpleTable extends Simple_js_1.default {
5183
5115
  * Writes the table's geospatial data to a file in GeoJSON, GeoParquet, or Shapefile format.
5184
5116
  * If the specified path does not exist, it will be created.
5185
5117
  *
5186
- * For GeoJSON files (`.geojson` or `.json`), if the projection is WGS84 or EPSG:4326 (`[latitude, longitude]` axis order), the coordinates will be flipped to follow the RFC7946 standard (`[longitude, latitude]` axis order) in the output.
5187
- *
5188
5118
  * @param file - The absolute path to the output file (e.g., `"./output.geojson"`, `"./output.geoparquet"`, `"./shapefile-folder/output.shp"`).
5189
5119
  * @param options - An optional object with configuration options:
5190
5120
  * @param options.precision - For GeoJSON, the maximum number of figures after the decimal separator to write in coordinates. Defaults to `undefined` (full precision).
@@ -5438,6 +5368,24 @@ class SimpleTable extends Simple_js_1.default {
5438
5368
  console.table(await (0, getDescription_js_1.default)(this));
5439
5369
  }
5440
5370
  }
5371
+ /**
5372
+ * Retrieves the projection of a specified geospatial column.
5373
+ *
5374
+ * @param column - The name of the geospatial column for which to retrieve the projection.
5375
+ * @returns A promise that resolves to the projection of the specified column.
5376
+ * @category Geospatial
5377
+ *
5378
+ * @example
5379
+ * ```ts
5380
+ * // Get the projection of the 'geom' column
5381
+ * const projection = await table.getProjection("geom");
5382
+ * ```
5383
+ */
5384
+ async getProjection(column) {
5385
+ const res = (await this.sdb.customQuery(`SELECT ST_CRS("${column}") AS proj FROM "${this.name}" LIMIT 1;`, { returnDataFrom: "query" }))[0];
5386
+ const proj = res && res.proj !== "null" ? res.proj : null;
5387
+ return `GEOMETRY${proj ? `('${proj}')` : ""}`;
5388
+ }
5441
5389
  /**
5442
5390
  * Logs the projections of the geospatial data (if any) to the console.
5443
5391
  *
@@ -5452,7 +5400,19 @@ class SimpleTable extends Simple_js_1.default {
5452
5400
  */
5453
5401
  async logProjections() {
5454
5402
  console.log(`\nTable ${this.name} projections:`);
5455
- console.log(this.projections);
5403
+ const types = await this.getTypes();
5404
+ const geoColumns = Object.entries(types)
5405
+ .filter(([_, type]) => type.toLowerCase().includes("geometry"))
5406
+ .map(([column]) => column);
5407
+ if (geoColumns.length === 0) {
5408
+ console.log("No geometry columns found.");
5409
+ }
5410
+ else {
5411
+ for (const column of geoColumns) {
5412
+ const projection = types[column];
5413
+ console.log(`- Column "${column}": ${projection}`);
5414
+ }
5415
+ }
5456
5416
  return await this;
5457
5417
  }
5458
5418
  /**