@atscript/db-sql-tools 0.1.153 → 0.1.155
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 +51 -0
- package/dist/index.d.cts +52 -2
- package/dist/index.d.mts +52 -2
- package/dist/index.mjs +49 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1470,6 +1470,19 @@ function buildProjection(dialect, select, qualifier) {
|
|
|
1470
1470
|
}
|
|
1471
1471
|
return sql || `${prefix}*`;
|
|
1472
1472
|
}
|
|
1473
|
+
/**
|
|
1474
|
+
* One query counting the rows of `quotedTable` that `columns` cannot hold as
|
|
1475
|
+
* a primary key: rows with a NULL in one of them, plus every row of a group
|
|
1476
|
+
* sharing the same values. Schema sync asks it before rebuilding the key of
|
|
1477
|
+
* a populated table (result column `violations`).
|
|
1478
|
+
* @since 0.1.155
|
|
1479
|
+
*/
|
|
1480
|
+
function buildKeyViolationCount(dialect, quotedTable, columns) {
|
|
1481
|
+
const cols = columns.map((c) => dialect.quoteIdentifier(c));
|
|
1482
|
+
const anyNull = cols.map((c) => `${c} IS NULL`).join(" OR ");
|
|
1483
|
+
const noNull = cols.map((c) => `${c} IS NOT NULL`).join(" AND ");
|
|
1484
|
+
return `SELECT (SELECT COUNT(*) FROM ${quotedTable} WHERE ${anyNull}) + (SELECT COALESCE(SUM(${dialect.quoteIdentifier("n")}), 0) FROM (SELECT COUNT(*) AS ${dialect.quoteIdentifier("n")} FROM ${quotedTable} WHERE ${noNull} GROUP BY ${cols.join(", ")} HAVING COUNT(*) > 1) ${dialect.quoteIdentifier("d")}) AS ` + dialect.quoteIdentifier("violations");
|
|
1485
|
+
}
|
|
1473
1486
|
//#endregion
|
|
1474
1487
|
//#region src/geo.ts
|
|
1475
1488
|
/**
|
|
@@ -1748,6 +1761,41 @@ function viewReadSource(dialect, readable, tableName, query, kind, partitionBy)
|
|
|
1748
1761
|
return source;
|
|
1749
1762
|
}
|
|
1750
1763
|
//#endregion
|
|
1764
|
+
//#region src/json-copy.ts
|
|
1765
|
+
/**
|
|
1766
|
+
* `UPDATE` copying the JSON values of the text column `source` into
|
|
1767
|
+
* `targets` (`BaseDbAdapter.copyFromJsonColumn`, since 0.1.155): each target
|
|
1768
|
+
* reads its path with the dialect's {@link SqlDialect.jsonExtractText} (a
|
|
1769
|
+
* `boolean` target with `jsonExtract(…, "boolean")`, a `json` one with
|
|
1770
|
+
* {@link SqlDialect.jsonExtractValue}), passed through `cast` (the
|
|
1771
|
+
* adapter's conversion to the column type). Only rows where `source` holds
|
|
1772
|
+
* a value and every target is NULL are touched, so a re-run never
|
|
1773
|
+
* overwrites values written since.
|
|
1774
|
+
*/
|
|
1775
|
+
function buildJsonColumnCopy(dialect, table, source, targets, cast = (expr) => expr) {
|
|
1776
|
+
if (!dialect.jsonExtractText || !dialect.jsonExtractValue || !dialect.jsonExtract) throw new Error("Copying JSON values into columns is not supported by this adapter");
|
|
1777
|
+
const src = dialect.quoteIdentifier(source);
|
|
1778
|
+
const sets = [];
|
|
1779
|
+
const empty = [];
|
|
1780
|
+
for (const target of targets) {
|
|
1781
|
+
const col = dialect.quoteIdentifier(target.column);
|
|
1782
|
+
const expr = target.kind === "json" ? dialect.jsonExtractValue(src, target.path) : target.kind === "boolean" ? dialect.jsonExtract(src, target.path, "boolean") : dialect.jsonExtractText(src, target.path);
|
|
1783
|
+
sets.push(`${col} = ${cast(expr, target)}`);
|
|
1784
|
+
empty.push(`${col} IS NULL`);
|
|
1785
|
+
}
|
|
1786
|
+
return `UPDATE ${dialect.quoteTable(table)} SET ${sets.join(", ")} WHERE ${src} IS NOT NULL AND ${empty.join(" AND ")}`;
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* `UPDATE` rewriting the text column `column` as JSON text
|
|
1790
|
+
* (`BaseDbAdapter.jsonifyTextColumn`, since 0.1.155): valid JSON stays, other
|
|
1791
|
+
* text becomes a JSON string — see {@link SqlDialect.jsonFromText}.
|
|
1792
|
+
*/
|
|
1793
|
+
function buildJsonifyText(dialect, table, column) {
|
|
1794
|
+
if (!dialect.jsonFromText) throw new Error("Converting text values to JSON is not supported by this adapter");
|
|
1795
|
+
const col = dialect.quoteIdentifier(column);
|
|
1796
|
+
return `UPDATE ${dialect.quoteTable(table)} SET ${col} = ${dialect.jsonFromText(col)} WHERE ${col} IS NOT NULL`;
|
|
1797
|
+
}
|
|
1798
|
+
//#endregion
|
|
1751
1799
|
exports.AGG_FN_SQL = AGG_FN_SQL;
|
|
1752
1800
|
exports.EMPTY_AND = EMPTY_AND;
|
|
1753
1801
|
exports.EMPTY_OR = EMPTY_OR;
|
|
@@ -1766,6 +1814,9 @@ exports.buildGeoSearchCount = buildGeoSearchCount;
|
|
|
1766
1814
|
exports.buildGeoSearchSelect = buildGeoSearchSelect;
|
|
1767
1815
|
exports.buildInsert = buildInsert;
|
|
1768
1816
|
exports.buildInsertMany = buildInsertMany;
|
|
1817
|
+
exports.buildJsonColumnCopy = buildJsonColumnCopy;
|
|
1818
|
+
exports.buildJsonifyText = buildJsonifyText;
|
|
1819
|
+
exports.buildKeyViolationCount = buildKeyViolationCount;
|
|
1769
1820
|
exports.buildPartitionedSelect = buildPartitionedSelect;
|
|
1770
1821
|
exports.buildProjection = buildProjection;
|
|
1771
1822
|
exports.buildSelect = buildSelect;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AtscriptExprNode, AtscriptQueryFieldRef, AtscriptQueryNode, DbControls, DbError, DbQuery, TDbDefaultFn, TDbFieldMeta, TDbForeignKey, TDbReferentialAction, TFieldOps, TReadColumnsKind, TResolvedBucket, TViewColumnMapping, TViewJsonType, TViewPlan, UniquSelect } from "@atscript/db";
|
|
1
|
+
import { AtscriptExprNode, AtscriptQueryFieldRef, AtscriptQueryNode, DbControls, DbError, DbQuery, TDbDefaultFn, TDbFieldMeta, TDbForeignKey, TDbReferentialAction, TFieldOps, TJsonCopyTarget, TReadColumnsKind, TResolvedBucket, TViewColumnMapping, TViewJsonType, TViewPlan, UniquSelect } from "@atscript/db";
|
|
2
2
|
import { FilterExpr, FilterVisitor, NullsPlacement } from "@uniqu/core";
|
|
3
3
|
import { TDbAggregateFn } from "@atscript/db/agg";
|
|
4
4
|
|
|
@@ -100,6 +100,29 @@ interface SqlDialect {
|
|
|
100
100
|
* @since 0.1.136
|
|
101
101
|
*/
|
|
102
102
|
jsonExtract?(quotedCol: string, path: readonly string[], type: TViewJsonType): string;
|
|
103
|
+
/**
|
|
104
|
+
* Schema sync's copy out of a JSON text column ({@link buildJsonColumnCopy},
|
|
105
|
+
* since 0.1.155): the value at `path` as text — a JSON string unquoted, a
|
|
106
|
+
* number / boolean as its JSON text (SQLite: as the SQL value), an object
|
|
107
|
+
* or array as JSON text; NULL when the path is missing or the value is JSON
|
|
108
|
+
* `null`. A malformed JSON column value makes the statement fail.
|
|
109
|
+
* Parameter-free; dialects without it cannot run that copy.
|
|
110
|
+
* @since 0.1.155
|
|
111
|
+
*/
|
|
112
|
+
jsonExtractText?(quotedCol: string, path: readonly string[]): string;
|
|
113
|
+
/**
|
|
114
|
+
* The value at `path` as JSON (for a JSON column), NULL when missing or
|
|
115
|
+
* JSON `null` — see {@link jsonExtractText}.
|
|
116
|
+
* @since 0.1.155
|
|
117
|
+
*/
|
|
118
|
+
jsonExtractValue?(quotedCol: string, path: readonly string[]): string;
|
|
119
|
+
/**
|
|
120
|
+
* A text column's value as JSON text ({@link buildJsonifyText}, since
|
|
121
|
+
* 0.1.155): a valid JSON value is kept, any other text becomes a JSON
|
|
122
|
+
* string (`abc` → `"abc"`). Parameter-free.
|
|
123
|
+
* @since 0.1.155
|
|
124
|
+
*/
|
|
125
|
+
jsonFromText?(quotedCol: string): string;
|
|
103
126
|
/**
|
|
104
127
|
* `expr` cast to an IEEE double — how a computed view column
|
|
105
128
|
* (`@db.compute`) evaluates every field / literal leaf, so `7 / 2 = 3.5`
|
|
@@ -642,6 +665,14 @@ declare function derivedColumnExpr(dialect: SqlDialect, field: TDbFieldMeta): st
|
|
|
642
665
|
* or aliased source such as the geo / vector search subqueries (since 0.1.143).
|
|
643
666
|
*/
|
|
644
667
|
declare function buildProjection(dialect: SqlDialect, select?: UniquSelect, qualifier?: string): string;
|
|
668
|
+
/**
|
|
669
|
+
* One query counting the rows of `quotedTable` that `columns` cannot hold as
|
|
670
|
+
* a primary key: rows with a NULL in one of them, plus every row of a group
|
|
671
|
+
* sharing the same values. Schema sync asks it before rebuilding the key of
|
|
672
|
+
* a populated table (result column `violations`).
|
|
673
|
+
* @since 0.1.155
|
|
674
|
+
*/
|
|
675
|
+
declare function buildKeyViolationCount(dialect: SqlDialect, quotedTable: string, columns: readonly string[]): string;
|
|
645
676
|
//#endregion
|
|
646
677
|
//#region src/common.d.ts
|
|
647
678
|
/** Formats a string value as a SQL literal with single-quote escaping. */
|
|
@@ -775,4 +806,23 @@ interface TReadableLike {
|
|
|
775
806
|
*/
|
|
776
807
|
declare function viewReadSource(dialect: SqlDialect, readable: TReadableLike, tableName: string, query: DbQuery, kind: TReadColumnsKind, partitionBy?: readonly string[]): TSqlFromSource;
|
|
777
808
|
//#endregion
|
|
778
|
-
|
|
809
|
+
//#region src/json-copy.d.ts
|
|
810
|
+
/**
|
|
811
|
+
* `UPDATE` copying the JSON values of the text column `source` into
|
|
812
|
+
* `targets` (`BaseDbAdapter.copyFromJsonColumn`, since 0.1.155): each target
|
|
813
|
+
* reads its path with the dialect's {@link SqlDialect.jsonExtractText} (a
|
|
814
|
+
* `boolean` target with `jsonExtract(…, "boolean")`, a `json` one with
|
|
815
|
+
* {@link SqlDialect.jsonExtractValue}), passed through `cast` (the
|
|
816
|
+
* adapter's conversion to the column type). Only rows where `source` holds
|
|
817
|
+
* a value and every target is NULL are touched, so a re-run never
|
|
818
|
+
* overwrites values written since.
|
|
819
|
+
*/
|
|
820
|
+
declare function buildJsonColumnCopy(dialect: SqlDialect, table: string, source: string, targets: readonly TJsonCopyTarget[], cast?: (expr: string, target: TJsonCopyTarget) => string): string;
|
|
821
|
+
/**
|
|
822
|
+
* `UPDATE` rewriting the text column `column` as JSON text
|
|
823
|
+
* (`BaseDbAdapter.jsonifyTextColumn`, since 0.1.155): valid JSON stays, other
|
|
824
|
+
* text becomes a JSON string — see {@link SqlDialect.jsonFromText}.
|
|
825
|
+
*/
|
|
826
|
+
declare function buildJsonifyText(dialect: SqlDialect, table: string, column: string): string;
|
|
827
|
+
//#endregion
|
|
828
|
+
export { AGG_FN_SQL, EMPTY_AND, EMPTY_OR, GEO_DISTANCE_ALIAS, InsertSqlCache, PARTITION_ROW_NUMBER_ALIAS, SEARCH_SOURCE_ALIAS, SQL_DEFAULT, type SqlDialect, type TArithFailure, type TFilterVisitorOptions, type TGeoCircle, type TGeoSearchControls, type TGeoWindow, type TReplaceColumn, type TSqlDerivedSource, type TSqlFragment, type TSqlFromSource, VECTOR_DISTANCE_ALIAS, arithOverflowError, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildInsertMany, buildJsonColumnCopy, buildJsonifyText, buildKeyViolationCount, buildPartitionedSelect, buildProjection, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildViewSelect, buildWhere, chunkInsertRows, createFilterVisitor, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, finalizeParams, foreignKeySql, fromSourceHint, fromSourceSql, geoWindowFromControls, groupKeySql, insertManyColumns, jsonDollarPath, mapQueryErrors, normalizeGeoPointValue, nullsOrderSql, nullsPlacementOf, numericOutOfRangeError, orFragment, orderByList, orderKeySql, parseRegexString, queryNodeToSql, queryOpToSql, quotedJsonPathSegments, refActionToSql, renameGeoDistance, renderArith, replaceColumnsFor, sqlStringLiteral, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue, vectorDistanceSource, viewReadSource };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AtscriptExprNode, AtscriptQueryFieldRef, AtscriptQueryNode, DbControls, DbError, DbQuery, TDbDefaultFn, TDbFieldMeta, TDbForeignKey, TDbReferentialAction, TFieldOps, TReadColumnsKind, TResolvedBucket, TViewColumnMapping, TViewJsonType, TViewPlan, UniquSelect } from "@atscript/db";
|
|
1
|
+
import { AtscriptExprNode, AtscriptQueryFieldRef, AtscriptQueryNode, DbControls, DbError, DbQuery, TDbDefaultFn, TDbFieldMeta, TDbForeignKey, TDbReferentialAction, TFieldOps, TJsonCopyTarget, TReadColumnsKind, TResolvedBucket, TViewColumnMapping, TViewJsonType, TViewPlan, UniquSelect } from "@atscript/db";
|
|
2
2
|
import { FilterExpr, FilterVisitor, NullsPlacement } from "@uniqu/core";
|
|
3
3
|
import { TDbAggregateFn } from "@atscript/db/agg";
|
|
4
4
|
|
|
@@ -100,6 +100,29 @@ interface SqlDialect {
|
|
|
100
100
|
* @since 0.1.136
|
|
101
101
|
*/
|
|
102
102
|
jsonExtract?(quotedCol: string, path: readonly string[], type: TViewJsonType): string;
|
|
103
|
+
/**
|
|
104
|
+
* Schema sync's copy out of a JSON text column ({@link buildJsonColumnCopy},
|
|
105
|
+
* since 0.1.155): the value at `path` as text — a JSON string unquoted, a
|
|
106
|
+
* number / boolean as its JSON text (SQLite: as the SQL value), an object
|
|
107
|
+
* or array as JSON text; NULL when the path is missing or the value is JSON
|
|
108
|
+
* `null`. A malformed JSON column value makes the statement fail.
|
|
109
|
+
* Parameter-free; dialects without it cannot run that copy.
|
|
110
|
+
* @since 0.1.155
|
|
111
|
+
*/
|
|
112
|
+
jsonExtractText?(quotedCol: string, path: readonly string[]): string;
|
|
113
|
+
/**
|
|
114
|
+
* The value at `path` as JSON (for a JSON column), NULL when missing or
|
|
115
|
+
* JSON `null` — see {@link jsonExtractText}.
|
|
116
|
+
* @since 0.1.155
|
|
117
|
+
*/
|
|
118
|
+
jsonExtractValue?(quotedCol: string, path: readonly string[]): string;
|
|
119
|
+
/**
|
|
120
|
+
* A text column's value as JSON text ({@link buildJsonifyText}, since
|
|
121
|
+
* 0.1.155): a valid JSON value is kept, any other text becomes a JSON
|
|
122
|
+
* string (`abc` → `"abc"`). Parameter-free.
|
|
123
|
+
* @since 0.1.155
|
|
124
|
+
*/
|
|
125
|
+
jsonFromText?(quotedCol: string): string;
|
|
103
126
|
/**
|
|
104
127
|
* `expr` cast to an IEEE double — how a computed view column
|
|
105
128
|
* (`@db.compute`) evaluates every field / literal leaf, so `7 / 2 = 3.5`
|
|
@@ -642,6 +665,14 @@ declare function derivedColumnExpr(dialect: SqlDialect, field: TDbFieldMeta): st
|
|
|
642
665
|
* or aliased source such as the geo / vector search subqueries (since 0.1.143).
|
|
643
666
|
*/
|
|
644
667
|
declare function buildProjection(dialect: SqlDialect, select?: UniquSelect, qualifier?: string): string;
|
|
668
|
+
/**
|
|
669
|
+
* One query counting the rows of `quotedTable` that `columns` cannot hold as
|
|
670
|
+
* a primary key: rows with a NULL in one of them, plus every row of a group
|
|
671
|
+
* sharing the same values. Schema sync asks it before rebuilding the key of
|
|
672
|
+
* a populated table (result column `violations`).
|
|
673
|
+
* @since 0.1.155
|
|
674
|
+
*/
|
|
675
|
+
declare function buildKeyViolationCount(dialect: SqlDialect, quotedTable: string, columns: readonly string[]): string;
|
|
645
676
|
//#endregion
|
|
646
677
|
//#region src/common.d.ts
|
|
647
678
|
/** Formats a string value as a SQL literal with single-quote escaping. */
|
|
@@ -775,4 +806,23 @@ interface TReadableLike {
|
|
|
775
806
|
*/
|
|
776
807
|
declare function viewReadSource(dialect: SqlDialect, readable: TReadableLike, tableName: string, query: DbQuery, kind: TReadColumnsKind, partitionBy?: readonly string[]): TSqlFromSource;
|
|
777
808
|
//#endregion
|
|
778
|
-
|
|
809
|
+
//#region src/json-copy.d.ts
|
|
810
|
+
/**
|
|
811
|
+
* `UPDATE` copying the JSON values of the text column `source` into
|
|
812
|
+
* `targets` (`BaseDbAdapter.copyFromJsonColumn`, since 0.1.155): each target
|
|
813
|
+
* reads its path with the dialect's {@link SqlDialect.jsonExtractText} (a
|
|
814
|
+
* `boolean` target with `jsonExtract(…, "boolean")`, a `json` one with
|
|
815
|
+
* {@link SqlDialect.jsonExtractValue}), passed through `cast` (the
|
|
816
|
+
* adapter's conversion to the column type). Only rows where `source` holds
|
|
817
|
+
* a value and every target is NULL are touched, so a re-run never
|
|
818
|
+
* overwrites values written since.
|
|
819
|
+
*/
|
|
820
|
+
declare function buildJsonColumnCopy(dialect: SqlDialect, table: string, source: string, targets: readonly TJsonCopyTarget[], cast?: (expr: string, target: TJsonCopyTarget) => string): string;
|
|
821
|
+
/**
|
|
822
|
+
* `UPDATE` rewriting the text column `column` as JSON text
|
|
823
|
+
* (`BaseDbAdapter.jsonifyTextColumn`, since 0.1.155): valid JSON stays, other
|
|
824
|
+
* text becomes a JSON string — see {@link SqlDialect.jsonFromText}.
|
|
825
|
+
*/
|
|
826
|
+
declare function buildJsonifyText(dialect: SqlDialect, table: string, column: string): string;
|
|
827
|
+
//#endregion
|
|
828
|
+
export { AGG_FN_SQL, EMPTY_AND, EMPTY_OR, GEO_DISTANCE_ALIAS, InsertSqlCache, PARTITION_ROW_NUMBER_ALIAS, SEARCH_SOURCE_ALIAS, SQL_DEFAULT, type SqlDialect, type TArithFailure, type TFilterVisitorOptions, type TGeoCircle, type TGeoSearchControls, type TGeoWindow, type TReplaceColumn, type TSqlDerivedSource, type TSqlFragment, type TSqlFromSource, VECTOR_DISTANCE_ALIAS, arithOverflowError, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildInsertMany, buildJsonColumnCopy, buildJsonifyText, buildKeyViolationCount, buildPartitionedSelect, buildProjection, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildViewSelect, buildWhere, chunkInsertRows, createFilterVisitor, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, finalizeParams, foreignKeySql, fromSourceHint, fromSourceSql, geoWindowFromControls, groupKeySql, insertManyColumns, jsonDollarPath, mapQueryErrors, normalizeGeoPointValue, nullsOrderSql, nullsPlacementOf, numericOutOfRangeError, orFragment, orderByList, orderKeySql, parseRegexString, queryNodeToSql, queryOpToSql, quotedJsonPathSegments, refActionToSql, renameGeoDistance, renderArith, replaceColumnsFor, sqlStringLiteral, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue, vectorDistanceSource, viewReadSource };
|
package/dist/index.mjs
CHANGED
|
@@ -1469,6 +1469,19 @@ function buildProjection(dialect, select, qualifier) {
|
|
|
1469
1469
|
}
|
|
1470
1470
|
return sql || `${prefix}*`;
|
|
1471
1471
|
}
|
|
1472
|
+
/**
|
|
1473
|
+
* One query counting the rows of `quotedTable` that `columns` cannot hold as
|
|
1474
|
+
* a primary key: rows with a NULL in one of them, plus every row of a group
|
|
1475
|
+
* sharing the same values. Schema sync asks it before rebuilding the key of
|
|
1476
|
+
* a populated table (result column `violations`).
|
|
1477
|
+
* @since 0.1.155
|
|
1478
|
+
*/
|
|
1479
|
+
function buildKeyViolationCount(dialect, quotedTable, columns) {
|
|
1480
|
+
const cols = columns.map((c) => dialect.quoteIdentifier(c));
|
|
1481
|
+
const anyNull = cols.map((c) => `${c} IS NULL`).join(" OR ");
|
|
1482
|
+
const noNull = cols.map((c) => `${c} IS NOT NULL`).join(" AND ");
|
|
1483
|
+
return `SELECT (SELECT COUNT(*) FROM ${quotedTable} WHERE ${anyNull}) + (SELECT COALESCE(SUM(${dialect.quoteIdentifier("n")}), 0) FROM (SELECT COUNT(*) AS ${dialect.quoteIdentifier("n")} FROM ${quotedTable} WHERE ${noNull} GROUP BY ${cols.join(", ")} HAVING COUNT(*) > 1) ${dialect.quoteIdentifier("d")}) AS ` + dialect.quoteIdentifier("violations");
|
|
1484
|
+
}
|
|
1472
1485
|
//#endregion
|
|
1473
1486
|
//#region src/geo.ts
|
|
1474
1487
|
/**
|
|
@@ -1747,4 +1760,39 @@ function viewReadSource(dialect, readable, tableName, query, kind, partitionBy)
|
|
|
1747
1760
|
return source;
|
|
1748
1761
|
}
|
|
1749
1762
|
//#endregion
|
|
1750
|
-
|
|
1763
|
+
//#region src/json-copy.ts
|
|
1764
|
+
/**
|
|
1765
|
+
* `UPDATE` copying the JSON values of the text column `source` into
|
|
1766
|
+
* `targets` (`BaseDbAdapter.copyFromJsonColumn`, since 0.1.155): each target
|
|
1767
|
+
* reads its path with the dialect's {@link SqlDialect.jsonExtractText} (a
|
|
1768
|
+
* `boolean` target with `jsonExtract(…, "boolean")`, a `json` one with
|
|
1769
|
+
* {@link SqlDialect.jsonExtractValue}), passed through `cast` (the
|
|
1770
|
+
* adapter's conversion to the column type). Only rows where `source` holds
|
|
1771
|
+
* a value and every target is NULL are touched, so a re-run never
|
|
1772
|
+
* overwrites values written since.
|
|
1773
|
+
*/
|
|
1774
|
+
function buildJsonColumnCopy(dialect, table, source, targets, cast = (expr) => expr) {
|
|
1775
|
+
if (!dialect.jsonExtractText || !dialect.jsonExtractValue || !dialect.jsonExtract) throw new Error("Copying JSON values into columns is not supported by this adapter");
|
|
1776
|
+
const src = dialect.quoteIdentifier(source);
|
|
1777
|
+
const sets = [];
|
|
1778
|
+
const empty = [];
|
|
1779
|
+
for (const target of targets) {
|
|
1780
|
+
const col = dialect.quoteIdentifier(target.column);
|
|
1781
|
+
const expr = target.kind === "json" ? dialect.jsonExtractValue(src, target.path) : target.kind === "boolean" ? dialect.jsonExtract(src, target.path, "boolean") : dialect.jsonExtractText(src, target.path);
|
|
1782
|
+
sets.push(`${col} = ${cast(expr, target)}`);
|
|
1783
|
+
empty.push(`${col} IS NULL`);
|
|
1784
|
+
}
|
|
1785
|
+
return `UPDATE ${dialect.quoteTable(table)} SET ${sets.join(", ")} WHERE ${src} IS NOT NULL AND ${empty.join(" AND ")}`;
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1788
|
+
* `UPDATE` rewriting the text column `column` as JSON text
|
|
1789
|
+
* (`BaseDbAdapter.jsonifyTextColumn`, since 0.1.155): valid JSON stays, other
|
|
1790
|
+
* text becomes a JSON string — see {@link SqlDialect.jsonFromText}.
|
|
1791
|
+
*/
|
|
1792
|
+
function buildJsonifyText(dialect, table, column) {
|
|
1793
|
+
if (!dialect.jsonFromText) throw new Error("Converting text values to JSON is not supported by this adapter");
|
|
1794
|
+
const col = dialect.quoteIdentifier(column);
|
|
1795
|
+
return `UPDATE ${dialect.quoteTable(table)} SET ${col} = ${dialect.jsonFromText(col)} WHERE ${col} IS NOT NULL`;
|
|
1796
|
+
}
|
|
1797
|
+
//#endregion
|
|
1798
|
+
export { AGG_FN_SQL, EMPTY_AND, EMPTY_OR, GEO_DISTANCE_ALIAS, InsertSqlCache, PARTITION_ROW_NUMBER_ALIAS, SEARCH_SOURCE_ALIAS, SQL_DEFAULT, VECTOR_DISTANCE_ALIAS, arithOverflowError, buildAggregateCount, buildAggregateSelect, buildCreateView, buildDelete, buildGeoSearchCount, buildGeoSearchSelect, buildInsert, buildInsertMany, buildJsonColumnCopy, buildJsonifyText, buildKeyViolationCount, buildPartitionedSelect, buildProjection, buildSelect, buildUpdate, buildVectorSearchCount, buildVectorSearchSelect, buildViewSelect, buildWhere, chunkInsertRows, createFilterVisitor, defaultValueForType, defaultValueToSqlLiteral, derivedColumnExpr, fillReplacePayload, finalizeParams, foreignKeySql, fromSourceHint, fromSourceSql, geoWindowFromControls, groupKeySql, insertManyColumns, jsonDollarPath, mapQueryErrors, normalizeGeoPointValue, nullsOrderSql, nullsPlacementOf, numericOutOfRangeError, orFragment, orderByList, orderKeySql, parseRegexString, queryNodeToSql, queryOpToSql, quotedJsonPathSegments, refActionToSql, renameGeoDistance, renderArith, replaceColumnsFor, sqlStringLiteral, sqlTimeZoneLiteral, stripPartitionRowNumber, toSqlValue, vectorDistanceSource, viewReadSource };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/db-sql-tools",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.155",
|
|
4
4
|
"description": "Shared SQL builder utilities for @atscript database adapters.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atscript",
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@uniqu/core": "^0.1.15",
|
|
41
|
-
"unplugin-atscript": "^0.1.
|
|
41
|
+
"unplugin-atscript": "^0.1.105"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@uniqu/core": "^0.1.15",
|
|
45
|
-
"@atscript/db": "^0.1.
|
|
45
|
+
"@atscript/db": "^0.1.155"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "vp pack",
|