@atscript/db-postgres 0.1.135 → 0.1.136

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -78,11 +78,30 @@ const pgDialect = {
78
78
  };
79
79
  },
80
80
  calendarBucket: pgCalendarBucket,
81
+ jsonExtract: pgJsonExtract,
81
82
  createViewPrefix: "CREATE OR REPLACE VIEW",
82
83
  paramPlaceholder(index) {
83
84
  return `$${index}`;
84
85
  }
85
86
  };
87
+ /** Cast applied to the `#>>` text per leaf type — `jsonb_typeof()` names equal the type names. */
88
+ const PG_JSON_LEAF_CAST = {
89
+ string: "",
90
+ number: "::double precision",
91
+ boolean: "::boolean"
92
+ };
93
+ /**
94
+ * Typed read of a JSON leaf (`SqlDialect.jsonExtract`): `jsonb_typeof()`
95
+ * guards the declared type, so a missing path, JSON `null` or another JSON
96
+ * type yields NULL (no coercion). Numbers are `double precision`, booleans
97
+ * native. The column is cast `::jsonb`, so JSON and JSONB storage both work.
98
+ */
99
+ function pgJsonExtract(quotedCol, path, type) {
100
+ const p = (0, _atscript_db_sql_tools.sqlStringLiteral)(`{${(0, _atscript_db_sql_tools.quotedJsonPathSegments)(path).join(",")}}`);
101
+ const j = `(${quotedCol})::jsonb`;
102
+ const cast = PG_JSON_LEAF_CAST[type];
103
+ return `CASE jsonb_typeof(${j} #> ${p}) WHEN '${type}' THEN ${cast ? `(${j} #>> ${p})${cast}` : `${j} #>> ${p}`} END`;
104
+ }
86
105
  /**
87
106
  * Calendar-bucket label over an epoch-ms column (BIGINT for
88
107
  * `@db.default.now`, DOUBLE PRECISION otherwise): TEXT `'YYYY-MM-DD'` — the
@@ -472,6 +491,10 @@ var PostgresAdapter = class PostgresAdapter extends _atscript_db.BaseDbAdapter {
472
491
  calendarBucketUnits() {
473
492
  return _atscript_db.ALL_BUCKET_UNITS;
474
493
  }
494
+ /** Every aggregate function, `countDistinct` included. */
495
+ aggregateFns() {
496
+ return _atscript_db.ALL_AGGREGATE_FNS;
497
+ }
475
498
  onBeforeFlatten(_type) {}
476
499
  onAfterFlatten() {
477
500
  for (const fd of this._table.fieldDescriptors) if (fd.collate === "nocase") this._nocaseColumns.add(fd.physicalName);
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
1
+ import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
2
2
  import { TMetadataMap } from "@atscript/typescript/utils";
3
3
  import { TSqlFragment } from "@atscript/db-sql-tools";
4
4
 
@@ -118,6 +118,8 @@ declare class PostgresAdapter extends BaseDbAdapter {
118
118
  * server's tz database (an unknown one maps to `BUCKET_TZ_UNAVAILABLE`).
119
119
  */
120
120
  calendarBucketUnits(): ReadonlySet<BucketUnit>;
121
+ /** Every aggregate function, `countDistinct` included. */
122
+ aggregateFns(): ReadonlySet<AggregateFn>;
121
123
  onBeforeFlatten(_type: unknown): void;
122
124
  onAfterFlatten(): void;
123
125
  onFieldScanned(field: string, _type: unknown, metadata: TMetadataMap<AtscriptMetadata>): void;
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
1
+ import { AggregateFn, BaseDbAdapter, BucketUnit, DbQuery, DbSpace, FilterExpr, TColumnDiff, TDbDefaultFn, TDbDeleteResult, TDbFieldMeta, TDbInsertManyResult, TDbInsertResult, TDbObjectKind, TDbUpdateResult, TEnsureTableOptions, TExistingColumn, TFieldOps, TPrimaryKeyChange, TReferencingForeignKey, TSearchIndexInfo, TSyncColumnResult, TValueFormatterPair } from "@atscript/db";
2
2
  import { TSqlFragment } from "@atscript/db-sql-tools";
3
3
  import { TMetadataMap } from "@atscript/typescript/utils";
4
4
 
@@ -118,6 +118,8 @@ declare class PostgresAdapter extends BaseDbAdapter {
118
118
  * server's tz database (an unknown one maps to `BUCKET_TZ_UNAVAILABLE`).
119
119
  */
120
120
  calendarBucketUnits(): ReadonlySet<BucketUnit>;
121
+ /** Every aggregate function, `countDistinct` included. */
122
+ aggregateFns(): ReadonlySet<AggregateFn>;
121
123
  onBeforeFlatten(_type: unknown): void;
122
124
  onAfterFlatten(): void;
123
125
  onFieldScanned(field: string, _type: unknown, metadata: TMetadataMap<AtscriptMetadata>): void;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { ALL_BUCKET_UNITS, BaseDbAdapter, DbError, DbSpace, bucketTimeZoneUnavailable } from "@atscript/db";
1
+ import { ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, BaseDbAdapter, DbError, DbSpace, bucketTimeZoneUnavailable } from "@atscript/db";
2
2
  import { resolveAggregateSearch } from "@atscript/db/agg";
3
- import { buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildInsertMany, buildSelect, buildUpdate, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, fillReplacePayload, finalizeParams, geoWindowFromControls, insertManyColumns, normalizeGeoPointValue, parseRegexString, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlTimeZoneLiteral } from "@atscript/db-sql-tools";
3
+ import { buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildInsertMany, buildSelect, buildUpdate, buildWhere as buildWhere$1, defaultValueForType, defaultValueToSqlLiteral, fillReplacePayload, finalizeParams, geoWindowFromControls, insertManyColumns, normalizeGeoPointValue, parseRegexString, quotedJsonPathSegments, refActionToSql, renameGeoDistance, replaceColumnsFor, sqlStringLiteral, sqlTimeZoneLiteral } from "@atscript/db-sql-tools";
4
4
  import { BUCKET_MAX_INSTANT, BUCKET_MIN_INSTANT } from "@uniqu/core";
5
5
  //#region src/sql-builder.ts
6
6
  /**
@@ -77,11 +77,30 @@ const pgDialect = {
77
77
  };
78
78
  },
79
79
  calendarBucket: pgCalendarBucket,
80
+ jsonExtract: pgJsonExtract,
80
81
  createViewPrefix: "CREATE OR REPLACE VIEW",
81
82
  paramPlaceholder(index) {
82
83
  return `$${index}`;
83
84
  }
84
85
  };
86
+ /** Cast applied to the `#>>` text per leaf type — `jsonb_typeof()` names equal the type names. */
87
+ const PG_JSON_LEAF_CAST = {
88
+ string: "",
89
+ number: "::double precision",
90
+ boolean: "::boolean"
91
+ };
92
+ /**
93
+ * Typed read of a JSON leaf (`SqlDialect.jsonExtract`): `jsonb_typeof()`
94
+ * guards the declared type, so a missing path, JSON `null` or another JSON
95
+ * type yields NULL (no coercion). Numbers are `double precision`, booleans
96
+ * native. The column is cast `::jsonb`, so JSON and JSONB storage both work.
97
+ */
98
+ function pgJsonExtract(quotedCol, path, type) {
99
+ const p = sqlStringLiteral(`{${quotedJsonPathSegments(path).join(",")}}`);
100
+ const j = `(${quotedCol})::jsonb`;
101
+ const cast = PG_JSON_LEAF_CAST[type];
102
+ return `CASE jsonb_typeof(${j} #> ${p}) WHEN '${type}' THEN ${cast ? `(${j} #>> ${p})${cast}` : `${j} #>> ${p}`} END`;
103
+ }
85
104
  /**
86
105
  * Calendar-bucket label over an epoch-ms column (BIGINT for
87
106
  * `@db.default.now`, DOUBLE PRECISION otherwise): TEXT `'YYYY-MM-DD'` — the
@@ -471,6 +490,10 @@ var PostgresAdapter = class PostgresAdapter extends BaseDbAdapter {
471
490
  calendarBucketUnits() {
472
491
  return ALL_BUCKET_UNITS;
473
492
  }
493
+ /** Every aggregate function, `countDistinct` included. */
494
+ aggregateFns() {
495
+ return ALL_AGGREGATE_FNS;
496
+ }
474
497
  onBeforeFlatten(_type) {}
475
498
  onAfterFlatten() {
476
499
  for (const fd of this._table.fieldDescriptors) if (fd.collate === "nocase") this._nocaseColumns.add(fd.physicalName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db-postgres",
3
- "version": "0.1.135",
3
+ "version": "0.1.136",
4
4
  "description": "PostgreSQL adapter for @atscript/db with pg (node-postgres) driver support.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -55,8 +55,8 @@
55
55
  "@atscript/typescript": "^0.1.92",
56
56
  "@uniqu/core": "^0.1.11",
57
57
  "pg": ">=8.0.0",
58
- "@atscript/db": "^0.1.135",
59
- "@atscript/db-sql-tools": "^0.1.135"
58
+ "@atscript/db": "^0.1.136",
59
+ "@atscript/db-sql-tools": "^0.1.136"
60
60
  },
61
61
  "peerDependenciesMeta": {
62
62
  "pg": {