@budibase/backend-core 2.32.11 → 2.32.12
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.js +380 -124
- package/dist/index.js.map +4 -4
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +4 -4
- package/dist/plugins.js.meta.json +1 -1
- package/dist/src/sql/sql.js +93 -35
- package/dist/src/sql/sql.js.map +1 -1
- package/dist/tests/core/utilities/structures/accounts.d.ts +1 -6
- package/dist/tests/core/utilities/structures/accounts.js +2 -56
- package/dist/tests/core/utilities/structures/accounts.js.map +1 -1
- package/package.json +4 -4
- package/src/sql/sql.ts +107 -36
- package/tests/core/utilities/structures/accounts.ts +1 -62
package/dist/index.js
CHANGED
|
@@ -61911,6 +61911,7 @@ __export(filters_exports, {
|
|
|
61911
61911
|
ColumnSplitter: () => ColumnSplitter,
|
|
61912
61912
|
NoEmptyFilterStrings: () => NoEmptyFilterStrings,
|
|
61913
61913
|
buildQuery: () => buildQuery,
|
|
61914
|
+
buildQueryLegacy: () => buildQueryLegacy,
|
|
61914
61915
|
cleanupQuery: () => cleanupQuery,
|
|
61915
61916
|
fixupFilterArrays: () => fixupFilterArrays,
|
|
61916
61917
|
getKeyNumbering: () => getKeyNumbering,
|
|
@@ -61926,6 +61927,156 @@ __export(filters_exports, {
|
|
|
61926
61927
|
});
|
|
61927
61928
|
var import_dayjs = __toESM(require_dayjs_min());
|
|
61928
61929
|
|
|
61930
|
+
// ../shared-core/src/utils.ts
|
|
61931
|
+
var utils_exports = {};
|
|
61932
|
+
__export(utils_exports, {
|
|
61933
|
+
filterValueToLabel: () => filterValueToLabel,
|
|
61934
|
+
hasSchema: () => hasSchema,
|
|
61935
|
+
isSupportedUserSearch: () => isSupportedUserSearch,
|
|
61936
|
+
parallelForeach: () => parallelForeach,
|
|
61937
|
+
processSearchFilters: () => processSearchFilters,
|
|
61938
|
+
trimOtherProps: () => trimOtherProps,
|
|
61939
|
+
unreachable: () => unreachable
|
|
61940
|
+
});
|
|
61941
|
+
function unreachable(value, message = `No such case in exhaustive switch: ${value}`) {
|
|
61942
|
+
throw new Error(message);
|
|
61943
|
+
}
|
|
61944
|
+
async function parallelForeach(items, task, maxConcurrency) {
|
|
61945
|
+
const promises = [];
|
|
61946
|
+
let index2 = 0;
|
|
61947
|
+
const processItem = async (item) => {
|
|
61948
|
+
try {
|
|
61949
|
+
await task(item);
|
|
61950
|
+
} finally {
|
|
61951
|
+
processNext();
|
|
61952
|
+
}
|
|
61953
|
+
};
|
|
61954
|
+
const processNext = () => {
|
|
61955
|
+
if (index2 >= items.length) {
|
|
61956
|
+
return;
|
|
61957
|
+
}
|
|
61958
|
+
const item = items[index2];
|
|
61959
|
+
index2++;
|
|
61960
|
+
const promise = processItem(item);
|
|
61961
|
+
promises.push(promise);
|
|
61962
|
+
if (promises.length >= maxConcurrency) {
|
|
61963
|
+
Promise.race(promises).then(processNext);
|
|
61964
|
+
} else {
|
|
61965
|
+
processNext();
|
|
61966
|
+
}
|
|
61967
|
+
};
|
|
61968
|
+
processNext();
|
|
61969
|
+
await Promise.all(promises);
|
|
61970
|
+
}
|
|
61971
|
+
function filterValueToLabel() {
|
|
61972
|
+
return Object.keys(OperatorOptions).reduce(
|
|
61973
|
+
(acc, key) => {
|
|
61974
|
+
const ops = OperatorOptions;
|
|
61975
|
+
const op = ops[key];
|
|
61976
|
+
acc[op["value"]] = op.label;
|
|
61977
|
+
return acc;
|
|
61978
|
+
},
|
|
61979
|
+
{}
|
|
61980
|
+
);
|
|
61981
|
+
}
|
|
61982
|
+
function hasSchema(test) {
|
|
61983
|
+
return typeof test === "object" && !Array.isArray(test) && test !== null && !(test instanceof Date) && Object.keys(test).length > 0;
|
|
61984
|
+
}
|
|
61985
|
+
function trimOtherProps(object, allowedProps) {
|
|
61986
|
+
const result = Object.keys(object).filter((key) => allowedProps.includes(key)).reduce(
|
|
61987
|
+
(acc, key) => ({ ...acc, [key]: object[key] }),
|
|
61988
|
+
{}
|
|
61989
|
+
);
|
|
61990
|
+
return result;
|
|
61991
|
+
}
|
|
61992
|
+
function isSupportedUserSearch(query) {
|
|
61993
|
+
const allowed = [
|
|
61994
|
+
{ op: "string" /* STRING */, key: "email" },
|
|
61995
|
+
{ op: "equal" /* EQUAL */, key: "_id" },
|
|
61996
|
+
{ op: "oneOf" /* ONE_OF */, key: "_id" }
|
|
61997
|
+
];
|
|
61998
|
+
for (let [key, operation] of Object.entries(query)) {
|
|
61999
|
+
if (typeof operation !== "object") {
|
|
62000
|
+
return false;
|
|
62001
|
+
}
|
|
62002
|
+
const fields = Object.keys(operation || {});
|
|
62003
|
+
if (fields.length === 0) {
|
|
62004
|
+
continue;
|
|
62005
|
+
}
|
|
62006
|
+
const allowedOperation = allowed.find(
|
|
62007
|
+
(allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
|
|
62008
|
+
);
|
|
62009
|
+
if (!allowedOperation) {
|
|
62010
|
+
return false;
|
|
62011
|
+
}
|
|
62012
|
+
}
|
|
62013
|
+
return true;
|
|
62014
|
+
}
|
|
62015
|
+
var processSearchFilters = (filters) => {
|
|
62016
|
+
if (!filters) {
|
|
62017
|
+
return;
|
|
62018
|
+
}
|
|
62019
|
+
const defaultCfg = {
|
|
62020
|
+
logicalOperator: "all" /* ALL */,
|
|
62021
|
+
groups: []
|
|
62022
|
+
};
|
|
62023
|
+
const filterAllowedKeys = [
|
|
62024
|
+
"field",
|
|
62025
|
+
"operator",
|
|
62026
|
+
"value",
|
|
62027
|
+
"type",
|
|
62028
|
+
"externalType",
|
|
62029
|
+
"valueType",
|
|
62030
|
+
"noValue",
|
|
62031
|
+
"formulaType"
|
|
62032
|
+
];
|
|
62033
|
+
if (Array.isArray(filters)) {
|
|
62034
|
+
let baseGroup = {
|
|
62035
|
+
filters: [],
|
|
62036
|
+
logicalOperator: "all" /* ALL */
|
|
62037
|
+
};
|
|
62038
|
+
return filters.reduce((acc, filter) => {
|
|
62039
|
+
const filterPropertyKeys = Object.keys(filter).sort((a, b) => {
|
|
62040
|
+
return a.localeCompare(b);
|
|
62041
|
+
}).filter((key) => key in filter);
|
|
62042
|
+
if (filterPropertyKeys.length == 1) {
|
|
62043
|
+
const key = filterPropertyKeys[0], value = filter[key];
|
|
62044
|
+
if (key === "onEmptyFilter") {
|
|
62045
|
+
acc.onEmptyFilter = value;
|
|
62046
|
+
} else if (key === "operator" && value === "allOr") {
|
|
62047
|
+
baseGroup.logicalOperator = "any" /* ANY */;
|
|
62048
|
+
}
|
|
62049
|
+
return acc;
|
|
62050
|
+
}
|
|
62051
|
+
const allowedFilterSettings = filterPropertyKeys.reduce(
|
|
62052
|
+
(acc2, key) => {
|
|
62053
|
+
const value = filter[key];
|
|
62054
|
+
if (filterAllowedKeys.includes(key)) {
|
|
62055
|
+
if (key === "field") {
|
|
62056
|
+
acc2.push([key, removeKeyNumbering(value)]);
|
|
62057
|
+
} else {
|
|
62058
|
+
acc2.push([key, value]);
|
|
62059
|
+
}
|
|
62060
|
+
}
|
|
62061
|
+
return acc2;
|
|
62062
|
+
},
|
|
62063
|
+
[]
|
|
62064
|
+
);
|
|
62065
|
+
const migratedFilter = Object.fromEntries(
|
|
62066
|
+
allowedFilterSettings
|
|
62067
|
+
);
|
|
62068
|
+
baseGroup.filters.push(migratedFilter);
|
|
62069
|
+
if (!acc.groups || !acc.groups.length) {
|
|
62070
|
+
acc.groups = [baseGroup];
|
|
62071
|
+
}
|
|
62072
|
+
return acc;
|
|
62073
|
+
}, defaultCfg);
|
|
62074
|
+
} else if (!filters?.groups) {
|
|
62075
|
+
return;
|
|
62076
|
+
}
|
|
62077
|
+
return filters;
|
|
62078
|
+
};
|
|
62079
|
+
|
|
61929
62080
|
// ../shared-core/src/helpers/index.ts
|
|
61930
62081
|
var helpers_exports = {};
|
|
61931
62082
|
__export(helpers_exports, {
|
|
@@ -62221,7 +62372,7 @@ var NoEmptyFilterStrings = [
|
|
|
62221
62372
|
];
|
|
62222
62373
|
function recurseLogicalOperators(filters, fn) {
|
|
62223
62374
|
for (const logical of LOGICAL_OPERATORS) {
|
|
62224
|
-
if (filters
|
|
62375
|
+
if (filters[logical]) {
|
|
62225
62376
|
filters[logical].conditions = filters[logical].conditions.map(
|
|
62226
62377
|
(condition) => fn(condition)
|
|
62227
62378
|
);
|
|
@@ -62241,9 +62392,6 @@ function recurseSearchFilters(filters, processFn) {
|
|
|
62241
62392
|
return filters;
|
|
62242
62393
|
}
|
|
62243
62394
|
var cleanupQuery = (query) => {
|
|
62244
|
-
if (!query) {
|
|
62245
|
-
return query;
|
|
62246
|
-
}
|
|
62247
62395
|
for (let filterField of NoEmptyFilterStrings) {
|
|
62248
62396
|
if (!query[filterField]) {
|
|
62249
62397
|
continue;
|
|
@@ -62334,7 +62482,106 @@ var ColumnSplitter = class {
|
|
|
62334
62482
|
};
|
|
62335
62483
|
}
|
|
62336
62484
|
};
|
|
62337
|
-
var
|
|
62485
|
+
var buildCondition = (expression) => {
|
|
62486
|
+
let query = {
|
|
62487
|
+
string: {},
|
|
62488
|
+
fuzzy: {},
|
|
62489
|
+
range: {},
|
|
62490
|
+
equal: {},
|
|
62491
|
+
notEqual: {},
|
|
62492
|
+
empty: {},
|
|
62493
|
+
notEmpty: {},
|
|
62494
|
+
contains: {},
|
|
62495
|
+
notContains: {},
|
|
62496
|
+
oneOf: {},
|
|
62497
|
+
containsAny: {}
|
|
62498
|
+
};
|
|
62499
|
+
let { operator, field, type, value, externalType, onEmptyFilter } = expression;
|
|
62500
|
+
if (!operator || !field) {
|
|
62501
|
+
return;
|
|
62502
|
+
}
|
|
62503
|
+
const queryOperator = operator;
|
|
62504
|
+
const isHbs = typeof value === "string" && (value.match(HBS_REGEX) || []).length > 0;
|
|
62505
|
+
if (operator === "allOr") {
|
|
62506
|
+
query.allOr = true;
|
|
62507
|
+
return;
|
|
62508
|
+
}
|
|
62509
|
+
if (onEmptyFilter) {
|
|
62510
|
+
query.onEmptyFilter = onEmptyFilter;
|
|
62511
|
+
return;
|
|
62512
|
+
}
|
|
62513
|
+
if (queryOperator === "empty" || queryOperator === "notEmpty") {
|
|
62514
|
+
value = null;
|
|
62515
|
+
}
|
|
62516
|
+
if (type === "datetime" && !isHbs && queryOperator !== "empty" && queryOperator !== "notEmpty") {
|
|
62517
|
+
if (!value) {
|
|
62518
|
+
return;
|
|
62519
|
+
}
|
|
62520
|
+
try {
|
|
62521
|
+
value = new Date(value).toISOString();
|
|
62522
|
+
} catch (error) {
|
|
62523
|
+
return;
|
|
62524
|
+
}
|
|
62525
|
+
}
|
|
62526
|
+
if (type === "number" && typeof value === "string" && !isHbs) {
|
|
62527
|
+
if (queryOperator === "oneOf") {
|
|
62528
|
+
value = value.split(",").map((item) => parseFloat(item));
|
|
62529
|
+
} else {
|
|
62530
|
+
value = parseFloat(value);
|
|
62531
|
+
}
|
|
62532
|
+
}
|
|
62533
|
+
if (type === "boolean") {
|
|
62534
|
+
value = `${value}`?.toLowerCase() === "true";
|
|
62535
|
+
}
|
|
62536
|
+
if (["contains", "notContains", "containsAny"].includes(
|
|
62537
|
+
operator.toLocaleString()
|
|
62538
|
+
) && type === "array" && typeof value === "string") {
|
|
62539
|
+
value = value.split(",");
|
|
62540
|
+
}
|
|
62541
|
+
if (operator.toLocaleString().startsWith("range") && query.range) {
|
|
62542
|
+
const minint = SqlNumberTypeRangeMap[externalType]?.min || Number.MIN_SAFE_INTEGER;
|
|
62543
|
+
const maxint = SqlNumberTypeRangeMap[externalType]?.max || Number.MAX_SAFE_INTEGER;
|
|
62544
|
+
if (!query.range[field]) {
|
|
62545
|
+
query.range[field] = {
|
|
62546
|
+
low: type === "number" ? minint : "0000-00-00T00:00:00.000Z",
|
|
62547
|
+
high: type === "number" ? maxint : "9999-00-00T00:00:00.000Z"
|
|
62548
|
+
};
|
|
62549
|
+
}
|
|
62550
|
+
if (operator === "rangeLow" && value != null && value !== "") {
|
|
62551
|
+
query.range[field] = {
|
|
62552
|
+
...query.range[field],
|
|
62553
|
+
low: value
|
|
62554
|
+
};
|
|
62555
|
+
} else if (operator === "rangeHigh" && value != null && value !== "") {
|
|
62556
|
+
query.range[field] = {
|
|
62557
|
+
...query.range[field],
|
|
62558
|
+
high: value
|
|
62559
|
+
};
|
|
62560
|
+
}
|
|
62561
|
+
} else if (isLogicalSearchOperator(queryOperator)) {
|
|
62562
|
+
} else if (query[queryOperator] && operator !== "onEmptyFilter") {
|
|
62563
|
+
if (type === "boolean") {
|
|
62564
|
+
if (queryOperator === "equal" && value === false) {
|
|
62565
|
+
query.notEqual = query.notEqual || {};
|
|
62566
|
+
query.notEqual[field] = true;
|
|
62567
|
+
} else if (queryOperator === "notEqual" && value === false) {
|
|
62568
|
+
query.equal = query.equal || {};
|
|
62569
|
+
query.equal[field] = true;
|
|
62570
|
+
} else {
|
|
62571
|
+
query[queryOperator] ??= {};
|
|
62572
|
+
query[queryOperator][field] = value;
|
|
62573
|
+
}
|
|
62574
|
+
} else {
|
|
62575
|
+
query[queryOperator] ??= {};
|
|
62576
|
+
query[queryOperator][field] = value;
|
|
62577
|
+
}
|
|
62578
|
+
}
|
|
62579
|
+
return query;
|
|
62580
|
+
};
|
|
62581
|
+
var buildQueryLegacy = (filter) => {
|
|
62582
|
+
if (!Array.isArray(filter)) {
|
|
62583
|
+
return filter;
|
|
62584
|
+
}
|
|
62338
62585
|
let query = {
|
|
62339
62586
|
string: {},
|
|
62340
62587
|
fuzzy: {},
|
|
@@ -62383,10 +62630,12 @@ var buildQuery = (filter) => {
|
|
|
62383
62630
|
if (type === "boolean") {
|
|
62384
62631
|
value = `${value}`?.toLowerCase() === "true";
|
|
62385
62632
|
}
|
|
62386
|
-
if (["contains", "notContains", "containsAny"].includes(
|
|
62633
|
+
if (["contains", "notContains", "containsAny"].includes(
|
|
62634
|
+
operator.toLocaleString()
|
|
62635
|
+
) && type === "array" && typeof value === "string") {
|
|
62387
62636
|
value = value.split(",");
|
|
62388
62637
|
}
|
|
62389
|
-
if (operator.startsWith("range") && query.range) {
|
|
62638
|
+
if (operator.toLocaleString().startsWith("range") && query.range) {
|
|
62390
62639
|
const minint = SqlNumberTypeRangeMap[externalType]?.min || Number.MIN_SAFE_INTEGER;
|
|
62391
62640
|
const maxint = SqlNumberTypeRangeMap[externalType]?.max || Number.MAX_SAFE_INTEGER;
|
|
62392
62641
|
if (!query.range[field]) {
|
|
@@ -62427,6 +62676,30 @@ var buildQuery = (filter) => {
|
|
|
62427
62676
|
});
|
|
62428
62677
|
return query;
|
|
62429
62678
|
};
|
|
62679
|
+
var buildQuery = (filter) => {
|
|
62680
|
+
const parsedFilter = processSearchFilters(filter);
|
|
62681
|
+
if (!parsedFilter) {
|
|
62682
|
+
return;
|
|
62683
|
+
}
|
|
62684
|
+
const operatorMap = {
|
|
62685
|
+
["all" /* ALL */]: "$and" /* AND */,
|
|
62686
|
+
["any" /* ANY */]: "$or" /* OR */
|
|
62687
|
+
};
|
|
62688
|
+
const globalOnEmpty = parsedFilter.onEmptyFilter ? parsedFilter.onEmptyFilter : null;
|
|
62689
|
+
const globalOperator = operatorMap[parsedFilter.logicalOperator];
|
|
62690
|
+
return {
|
|
62691
|
+
...globalOnEmpty ? { onEmptyFilter: globalOnEmpty } : {},
|
|
62692
|
+
[globalOperator]: {
|
|
62693
|
+
conditions: parsedFilter.groups?.map((group) => {
|
|
62694
|
+
return {
|
|
62695
|
+
[operatorMap[group.logicalOperator]]: {
|
|
62696
|
+
conditions: group.filters?.map((x) => buildCondition(x)).filter((filter2) => filter2)
|
|
62697
|
+
}
|
|
62698
|
+
};
|
|
62699
|
+
})
|
|
62700
|
+
}
|
|
62701
|
+
};
|
|
62702
|
+
};
|
|
62430
62703
|
function fixupFilterArrays(filters) {
|
|
62431
62704
|
for (const searchField of Object.values(ArrayOperator)) {
|
|
62432
62705
|
const field = filters[searchField];
|
|
@@ -62767,91 +63040,6 @@ var hasFilters = (query) => {
|
|
|
62767
63040
|
return check(query);
|
|
62768
63041
|
};
|
|
62769
63042
|
|
|
62770
|
-
// ../shared-core/src/utils.ts
|
|
62771
|
-
var utils_exports = {};
|
|
62772
|
-
__export(utils_exports, {
|
|
62773
|
-
filterValueToLabel: () => filterValueToLabel,
|
|
62774
|
-
hasSchema: () => hasSchema,
|
|
62775
|
-
isSupportedUserSearch: () => isSupportedUserSearch,
|
|
62776
|
-
parallelForeach: () => parallelForeach,
|
|
62777
|
-
trimOtherProps: () => trimOtherProps,
|
|
62778
|
-
unreachable: () => unreachable
|
|
62779
|
-
});
|
|
62780
|
-
function unreachable(value, message = `No such case in exhaustive switch: ${value}`) {
|
|
62781
|
-
throw new Error(message);
|
|
62782
|
-
}
|
|
62783
|
-
async function parallelForeach(items, task, maxConcurrency) {
|
|
62784
|
-
const promises = [];
|
|
62785
|
-
let index2 = 0;
|
|
62786
|
-
const processItem = async (item) => {
|
|
62787
|
-
try {
|
|
62788
|
-
await task(item);
|
|
62789
|
-
} finally {
|
|
62790
|
-
processNext();
|
|
62791
|
-
}
|
|
62792
|
-
};
|
|
62793
|
-
const processNext = () => {
|
|
62794
|
-
if (index2 >= items.length) {
|
|
62795
|
-
return;
|
|
62796
|
-
}
|
|
62797
|
-
const item = items[index2];
|
|
62798
|
-
index2++;
|
|
62799
|
-
const promise = processItem(item);
|
|
62800
|
-
promises.push(promise);
|
|
62801
|
-
if (promises.length >= maxConcurrency) {
|
|
62802
|
-
Promise.race(promises).then(processNext);
|
|
62803
|
-
} else {
|
|
62804
|
-
processNext();
|
|
62805
|
-
}
|
|
62806
|
-
};
|
|
62807
|
-
processNext();
|
|
62808
|
-
await Promise.all(promises);
|
|
62809
|
-
}
|
|
62810
|
-
function filterValueToLabel() {
|
|
62811
|
-
return Object.keys(OperatorOptions).reduce(
|
|
62812
|
-
(acc, key) => {
|
|
62813
|
-
const ops = OperatorOptions;
|
|
62814
|
-
const op = ops[key];
|
|
62815
|
-
acc[op["value"]] = op.label;
|
|
62816
|
-
return acc;
|
|
62817
|
-
},
|
|
62818
|
-
{}
|
|
62819
|
-
);
|
|
62820
|
-
}
|
|
62821
|
-
function hasSchema(test) {
|
|
62822
|
-
return typeof test === "object" && !Array.isArray(test) && test !== null && !(test instanceof Date) && Object.keys(test).length > 0;
|
|
62823
|
-
}
|
|
62824
|
-
function trimOtherProps(object, allowedProps) {
|
|
62825
|
-
const result = Object.keys(object).filter((key) => allowedProps.includes(key)).reduce(
|
|
62826
|
-
(acc, key) => ({ ...acc, [key]: object[key] }),
|
|
62827
|
-
{}
|
|
62828
|
-
);
|
|
62829
|
-
return result;
|
|
62830
|
-
}
|
|
62831
|
-
function isSupportedUserSearch(query) {
|
|
62832
|
-
const allowed = [
|
|
62833
|
-
{ op: "string" /* STRING */, key: "email" },
|
|
62834
|
-
{ op: "equal" /* EQUAL */, key: "_id" },
|
|
62835
|
-
{ op: "oneOf" /* ONE_OF */, key: "_id" }
|
|
62836
|
-
];
|
|
62837
|
-
for (let [key, operation] of Object.entries(query)) {
|
|
62838
|
-
if (typeof operation !== "object") {
|
|
62839
|
-
return false;
|
|
62840
|
-
}
|
|
62841
|
-
const fields = Object.keys(operation || {});
|
|
62842
|
-
if (fields.length === 0) {
|
|
62843
|
-
continue;
|
|
62844
|
-
}
|
|
62845
|
-
const allowedOperation = allowed.find(
|
|
62846
|
-
(allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
|
|
62847
|
-
);
|
|
62848
|
-
if (!allowedOperation) {
|
|
62849
|
-
return false;
|
|
62850
|
-
}
|
|
62851
|
-
}
|
|
62852
|
-
return true;
|
|
62853
|
-
}
|
|
62854
|
-
|
|
62855
63043
|
// ../shared-core/src/sdk/index.ts
|
|
62856
63044
|
var sdk_exports = {};
|
|
62857
63045
|
__export(sdk_exports, {
|
|
@@ -75270,25 +75458,56 @@ var InternalBuilder = class {
|
|
|
75270
75458
|
const { column } = this.splitter.run(key);
|
|
75271
75459
|
return this.table.schema[column];
|
|
75272
75460
|
}
|
|
75273
|
-
|
|
75274
|
-
// and "foo" for Postgres.
|
|
75275
|
-
quote(str) {
|
|
75461
|
+
quoteChars() {
|
|
75276
75462
|
switch (this.client) {
|
|
75277
|
-
case "sqlite3" /* SQL_LITE */:
|
|
75278
75463
|
case "oracledb" /* ORACLE */:
|
|
75279
75464
|
case "pg" /* POSTGRES */:
|
|
75280
|
-
return
|
|
75465
|
+
return ['"', '"'];
|
|
75281
75466
|
case "mssql" /* MS_SQL */:
|
|
75282
|
-
return
|
|
75467
|
+
return ["[", "]"];
|
|
75283
75468
|
case "mariadb" /* MARIADB */:
|
|
75284
75469
|
case "mysql2" /* MY_SQL */:
|
|
75285
|
-
|
|
75470
|
+
case "sqlite3" /* SQL_LITE */:
|
|
75471
|
+
return ["`", "`"];
|
|
75286
75472
|
}
|
|
75287
75473
|
}
|
|
75288
|
-
// Takes a string like
|
|
75289
|
-
//
|
|
75474
|
+
// Takes a string like foo and returns a quoted string like [foo] for SQL Server
|
|
75475
|
+
// and "foo" for Postgres.
|
|
75476
|
+
quote(str) {
|
|
75477
|
+
const [start2, end2] = this.quoteChars();
|
|
75478
|
+
return `${start2}${str}${end2}`;
|
|
75479
|
+
}
|
|
75480
|
+
isQuoted(key) {
|
|
75481
|
+
const [start2, end2] = this.quoteChars();
|
|
75482
|
+
return key.startsWith(start2) && key.endsWith(end2);
|
|
75483
|
+
}
|
|
75484
|
+
// Takes a string like a.b.c or an array like ["a", "b", "c"] and returns a
|
|
75485
|
+
// quoted identifier like [a].[b].[c] for SQL Server and `a`.`b`.`c` for
|
|
75486
|
+
// MySQL.
|
|
75290
75487
|
quotedIdentifier(key) {
|
|
75291
|
-
|
|
75488
|
+
if (!Array.isArray(key)) {
|
|
75489
|
+
key = this.splitIdentifier(key);
|
|
75490
|
+
}
|
|
75491
|
+
return key.map((part) => this.quote(part)).join(".");
|
|
75492
|
+
}
|
|
75493
|
+
// Turns an identifier like a.b.c or `a`.`b`.`c` into ["a", "b", "c"]
|
|
75494
|
+
splitIdentifier(key) {
|
|
75495
|
+
const [start2, end2] = this.quoteChars();
|
|
75496
|
+
if (this.isQuoted(key)) {
|
|
75497
|
+
return key.slice(1, -1).split(`${end2}.${start2}`);
|
|
75498
|
+
}
|
|
75499
|
+
return key.split(".");
|
|
75500
|
+
}
|
|
75501
|
+
qualifyIdentifier(key) {
|
|
75502
|
+
const tableName = this.getTableName();
|
|
75503
|
+
const parts = this.splitIdentifier(key);
|
|
75504
|
+
if (parts[0] !== tableName) {
|
|
75505
|
+
parts.unshift(tableName);
|
|
75506
|
+
}
|
|
75507
|
+
if (this.isQuoted(key)) {
|
|
75508
|
+
return this.quotedIdentifier(parts);
|
|
75509
|
+
}
|
|
75510
|
+
return parts.join(".");
|
|
75292
75511
|
}
|
|
75293
75512
|
isFullSelectStatementRequired() {
|
|
75294
75513
|
const { meta } = this.query;
|
|
@@ -75339,13 +75558,22 @@ var InternalBuilder = class {
|
|
|
75339
75558
|
// OracleDB can't use character-large-objects (CLOBs) in WHERE clauses,
|
|
75340
75559
|
// so when we use them we need to wrap them in to_char(). This function
|
|
75341
75560
|
// converts a field name to the appropriate identifier.
|
|
75342
|
-
convertClobs(field) {
|
|
75343
|
-
|
|
75561
|
+
convertClobs(field, opts) {
|
|
75562
|
+
if (this.client !== "oracledb" /* ORACLE */) {
|
|
75563
|
+
throw new Error(
|
|
75564
|
+
"you've called convertClobs on a DB that's not Oracle, this is a mistake"
|
|
75565
|
+
);
|
|
75566
|
+
}
|
|
75567
|
+
const parts = this.splitIdentifier(field);
|
|
75344
75568
|
const col = parts.pop();
|
|
75345
75569
|
const schema = this.table.schema[col];
|
|
75346
75570
|
let identifier = this.quotedIdentifier(field);
|
|
75347
75571
|
if (schema.type === "string" /* STRING */ || schema.type === "longform" /* LONGFORM */ || schema.type === "bb_reference_single" /* BB_REFERENCE_SINGLE */ || schema.type === "bb_reference" /* BB_REFERENCE */ || schema.type === "options" /* OPTIONS */ || schema.type === "barcodeqr" /* BARCODEQR */) {
|
|
75348
|
-
|
|
75572
|
+
if (opts?.forSelect) {
|
|
75573
|
+
identifier = `to_char(${identifier}) as ${this.quotedIdentifier(col)}`;
|
|
75574
|
+
} else {
|
|
75575
|
+
identifier = `to_char(${identifier})`;
|
|
75576
|
+
}
|
|
75349
75577
|
}
|
|
75350
75578
|
return identifier;
|
|
75351
75579
|
}
|
|
@@ -75842,28 +76070,56 @@ var InternalBuilder = class {
|
|
|
75842
76070
|
const fields = this.query.resource?.fields || [];
|
|
75843
76071
|
const tableName = this.getTableName();
|
|
75844
76072
|
if (fields.length > 0) {
|
|
75845
|
-
|
|
75846
|
-
|
|
76073
|
+
const qualifiedFields = fields.map((field) => this.qualifyIdentifier(field));
|
|
76074
|
+
if (this.client === "oracledb" /* ORACLE */) {
|
|
76075
|
+
const groupByFields = qualifiedFields.map(
|
|
76076
|
+
(field) => this.convertClobs(field)
|
|
76077
|
+
);
|
|
76078
|
+
const selectFields = qualifiedFields.map(
|
|
76079
|
+
(field) => this.convertClobs(field, { forSelect: true })
|
|
76080
|
+
);
|
|
76081
|
+
query = query.groupByRaw(groupByFields.join(", ")).select(this.knex.raw(selectFields.join(", ")));
|
|
76082
|
+
} else {
|
|
76083
|
+
query = query.groupBy(qualifiedFields).select(qualifiedFields);
|
|
76084
|
+
}
|
|
75847
76085
|
}
|
|
75848
76086
|
for (const aggregation of aggregations) {
|
|
75849
76087
|
const op = aggregation.calculationType;
|
|
75850
|
-
|
|
75851
|
-
|
|
75852
|
-
|
|
75853
|
-
|
|
75854
|
-
|
|
75855
|
-
|
|
75856
|
-
|
|
75857
|
-
|
|
75858
|
-
|
|
75859
|
-
|
|
75860
|
-
|
|
75861
|
-
|
|
75862
|
-
|
|
75863
|
-
|
|
75864
|
-
|
|
75865
|
-
|
|
75866
|
-
|
|
76088
|
+
if (op === "count" /* COUNT */) {
|
|
76089
|
+
if ("distinct" in aggregation && aggregation.distinct) {
|
|
76090
|
+
if (this.client === "oracledb" /* ORACLE */) {
|
|
76091
|
+
const field = this.convertClobs(`${tableName}.${aggregation.field}`);
|
|
76092
|
+
query = query.select(
|
|
76093
|
+
this.knex.raw(
|
|
76094
|
+
`COUNT(DISTINCT ${field}) as ${this.quotedIdentifier(
|
|
76095
|
+
aggregation.name
|
|
76096
|
+
)}`
|
|
76097
|
+
)
|
|
76098
|
+
);
|
|
76099
|
+
} else {
|
|
76100
|
+
query = query.countDistinct(
|
|
76101
|
+
`${tableName}.${aggregation.field} as ${aggregation.name}`
|
|
76102
|
+
);
|
|
76103
|
+
}
|
|
76104
|
+
} else {
|
|
76105
|
+
query = query.count(`* as ${aggregation.name}`);
|
|
76106
|
+
}
|
|
76107
|
+
} else {
|
|
76108
|
+
const field = `${tableName}.${aggregation.field} as ${aggregation.name}`;
|
|
76109
|
+
switch (op) {
|
|
76110
|
+
case "sum" /* SUM */:
|
|
76111
|
+
query = query.sum(field);
|
|
76112
|
+
break;
|
|
76113
|
+
case "avg" /* AVG */:
|
|
76114
|
+
query = query.avg(field);
|
|
76115
|
+
break;
|
|
76116
|
+
case "min" /* MIN */:
|
|
76117
|
+
query = query.min(field);
|
|
76118
|
+
break;
|
|
76119
|
+
case "max" /* MAX */:
|
|
76120
|
+
query = query.max(field);
|
|
76121
|
+
break;
|
|
76122
|
+
}
|
|
75867
76123
|
}
|
|
75868
76124
|
}
|
|
75869
76125
|
return query;
|