@budibase/backend-core 2.33.0 → 2.33.2

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 CHANGED
@@ -75562,6 +75562,21 @@ function convertBooleans(query) {
75562
75562
  function isSqs(table) {
75563
75563
  return table.sourceType === "internal" /* INTERNAL */ || table.sourceId === INTERNAL_TABLE_SOURCE_ID;
75564
75564
  }
75565
+ var allowEmptyRelationships = {
75566
+ ["equal" /* EQUAL */]: false,
75567
+ ["notEqual" /* NOT_EQUAL */]: true,
75568
+ ["empty" /* EMPTY */]: false,
75569
+ ["notEmpty" /* NOT_EMPTY */]: true,
75570
+ ["fuzzy" /* FUZZY */]: false,
75571
+ ["string" /* STRING */]: false,
75572
+ ["range" /* RANGE */]: false,
75573
+ ["contains" /* CONTAINS */]: false,
75574
+ ["notContains" /* NOT_CONTAINS */]: true,
75575
+ ["containsAny" /* CONTAINS_ANY */]: false,
75576
+ ["oneOf" /* ONE_OF */]: false,
75577
+ ["$and" /* AND */]: false,
75578
+ ["$or" /* OR */]: false
75579
+ };
75565
75580
  var InternalBuilder = class {
75566
75581
  constructor(client, knex3, query) {
75567
75582
  // states the various situations in which we need a full mapped select statement
@@ -75806,21 +75821,33 @@ var InternalBuilder = class {
75806
75821
  const document = relationship.from?.split(".")[0] || "";
75807
75822
  return query.andWhere(`${document}.fieldName`, "=", relationship.column);
75808
75823
  }
75809
- addRelationshipForFilter(query, filterKey, whereCb) {
75824
+ addRelationshipForFilter(query, allowEmptyRelationships2, filterKey, whereCb) {
75810
75825
  const mainKnex = this.knex;
75811
75826
  const { relationships, endpoint, tableAliases: aliases } = this.query;
75812
75827
  const tableName = endpoint.entityId;
75813
75828
  const fromAlias = aliases?.[tableName] || tableName;
75814
- const matches2 = (possibleTable) => filterKey.startsWith(`${possibleTable}`);
75829
+ const matches2 = (value) => filterKey.match(new RegExp(`^${value}\\.`));
75815
75830
  if (!relationships) {
75816
75831
  return query;
75817
75832
  }
75818
75833
  for (const relationship of relationships) {
75819
75834
  const relatedTableName = relationship.tableName;
75820
75835
  const toAlias = aliases?.[relatedTableName] || relatedTableName;
75821
- if ((matches2(relatedTableName) || matches2(toAlias)) && relationship.to && relationship.tableName) {
75822
- let subQuery = mainKnex.select(mainKnex.raw(1)).from({ [toAlias]: relatedTableName });
75836
+ const matchesTableName = matches2(relatedTableName) || matches2(toAlias);
75837
+ const matchesRelationName = matches2(relationship.column);
75838
+ if ((matchesTableName || matchesRelationName) && relationship.to && relationship.tableName) {
75839
+ const joinTable = mainKnex.select(mainKnex.raw(1)).from({ [toAlias]: relatedTableName });
75840
+ let subQuery = joinTable.clone();
75823
75841
  const manyToMany = validateManyToMany(relationship);
75842
+ let updatedKey;
75843
+ if (!matchesTableName) {
75844
+ updatedKey = filterKey.replace(
75845
+ new RegExp(`^${relationship.column}.`),
75846
+ `${aliases[relationship.tableName]}.`
75847
+ );
75848
+ } else {
75849
+ updatedKey = filterKey;
75850
+ }
75824
75851
  if (manyToMany) {
75825
75852
  const throughAlias = aliases?.[manyToMany.through] || relationship.through;
75826
75853
  let throughTable = this.tableNameWithSchema(manyToMany.through, {
@@ -75843,17 +75870,35 @@ var InternalBuilder = class {
75843
75870
  if (this.client === "sqlite3" /* SQL_LITE */) {
75844
75871
  subQuery = this.addJoinFieldCheck(subQuery, manyToMany);
75845
75872
  }
75873
+ query = query.where((q2) => {
75874
+ q2.whereExists(whereCb(updatedKey, subQuery));
75875
+ if (allowEmptyRelationships2) {
75876
+ q2.orWhereNotExists(
75877
+ joinTable.clone().innerJoin(throughTable, function() {
75878
+ this.on(
75879
+ `${fromAlias}.${manyToMany.fromPrimary}`,
75880
+ "=",
75881
+ `${throughAlias}.${manyToMany.from}`
75882
+ );
75883
+ })
75884
+ );
75885
+ }
75886
+ });
75846
75887
  } else {
75888
+ const toKey = `${toAlias}.${relationship.to}`;
75889
+ const foreignKey = `${fromAlias}.${relationship.from}`;
75847
75890
  subQuery = subQuery.where(
75848
- `${toAlias}.${relationship.to}`,
75891
+ toKey,
75849
75892
  "=",
75850
- mainKnex.raw(
75851
- this.quotedIdentifier(`${fromAlias}.${relationship.from}`)
75852
- )
75893
+ mainKnex.raw(this.quotedIdentifier(foreignKey))
75853
75894
  );
75895
+ query = query.where((q2) => {
75896
+ q2.whereExists(whereCb(updatedKey, subQuery.clone()));
75897
+ if (allowEmptyRelationships2) {
75898
+ q2.orWhereNotExists(subQuery);
75899
+ }
75900
+ });
75854
75901
  }
75855
- query = query.whereExists(whereCb(subQuery));
75856
- break;
75857
75902
  }
75858
75903
  }
75859
75904
  return query;
@@ -75873,7 +75918,7 @@ var InternalBuilder = class {
75873
75918
  const alias = aliases?.[name];
75874
75919
  return alias || name;
75875
75920
  }
75876
- function iterate(structure, fn, complexKeyFn) {
75921
+ function iterate(structure, operation, fn, complexKeyFn) {
75877
75922
  const handleRelationship = (q2, key, value) => {
75878
75923
  const [filterTableName, ...otherProperties] = key.split(".");
75879
75924
  const property = otherProperties.join(".");
@@ -75908,9 +75953,14 @@ var InternalBuilder = class {
75908
75953
  if (allOr) {
75909
75954
  query = query.or;
75910
75955
  }
75911
- query = builder.addRelationshipForFilter(query, updatedKey, (q2) => {
75912
- return handleRelationship(q2, updatedKey, value);
75913
- });
75956
+ query = builder.addRelationshipForFilter(
75957
+ query,
75958
+ allowEmptyRelationships[operation],
75959
+ updatedKey,
75960
+ (updatedKey2, q2) => {
75961
+ return handleRelationship(q2, updatedKey2, value);
75962
+ }
75963
+ );
75914
75964
  }
75915
75965
  }
75916
75966
  }
@@ -75938,7 +75988,7 @@ var InternalBuilder = class {
75938
75988
  return `[${value.join(",")}]`;
75939
75989
  }
75940
75990
  if (this.client === "pg" /* POSTGRES */) {
75941
- iterate(mode, (q2, key, value) => {
75991
+ iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
75942
75992
  const wrap = any ? "" : "'";
75943
75993
  const op = any ? "\\?| array" : "@>";
75944
75994
  const fieldNames = key.split(/\./g);
@@ -75953,7 +76003,7 @@ var InternalBuilder = class {
75953
76003
  });
75954
76004
  } else if (this.client === "mysql2" /* MY_SQL */ || this.client === "mariadb" /* MARIADB */) {
75955
76005
  const jsonFnc = any ? "JSON_OVERLAPS" : "JSON_CONTAINS";
75956
- iterate(mode, (q2, key, value) => {
76006
+ iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
75957
76007
  return q2[rawFnc](
75958
76008
  `${not}COALESCE(${jsonFnc}(${key}, '${stringifyArray(
75959
76009
  value
@@ -75962,7 +76012,7 @@ var InternalBuilder = class {
75962
76012
  });
75963
76013
  } else {
75964
76014
  const andOr = mode === filters?.containsAny ? " OR " : " AND ";
75965
- iterate(mode, (q2, key, value) => {
76015
+ iterate(mode, "contains" /* CONTAINS */, (q2, key, value) => {
75966
76016
  let statement = "";
75967
76017
  const identifier = this.quotedIdentifier(key);
75968
76018
  for (let i in value) {
@@ -76009,6 +76059,7 @@ var InternalBuilder = class {
76009
76059
  const fnc = allOr ? "orWhereIn" : "whereIn";
76010
76060
  iterate(
76011
76061
  filters.oneOf,
76062
+ "oneOf" /* ONE_OF */,
76012
76063
  (q2, key, array) => {
76013
76064
  if (this.client === "oracledb" /* ORACLE */) {
76014
76065
  key = this.convertClobs(key);
@@ -76031,7 +76082,7 @@ var InternalBuilder = class {
76031
76082
  );
76032
76083
  }
76033
76084
  if (filters.string) {
76034
- iterate(filters.string, (q2, key, value) => {
76085
+ iterate(filters.string, "string" /* STRING */, (q2, key, value) => {
76035
76086
  const fnc = allOr ? "orWhere" : "where";
76036
76087
  if (this.client === "pg" /* POSTGRES */) {
76037
76088
  return q2[fnc](key, "ilike", `${value}%`);
@@ -76044,10 +76095,10 @@ var InternalBuilder = class {
76044
76095
  });
76045
76096
  }
76046
76097
  if (filters.fuzzy) {
76047
- iterate(filters.fuzzy, like);
76098
+ iterate(filters.fuzzy, "fuzzy" /* FUZZY */, like);
76048
76099
  }
76049
76100
  if (filters.range) {
76050
- iterate(filters.range, (q2, key, value) => {
76101
+ iterate(filters.range, "range" /* RANGE */, (q2, key, value) => {
76051
76102
  const isEmptyObject = (val) => {
76052
76103
  return val && Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype;
76053
76104
  };
@@ -76095,7 +76146,7 @@ var InternalBuilder = class {
76095
76146
  });
76096
76147
  }
76097
76148
  if (filters.equal) {
76098
- iterate(filters.equal, (q2, key, value) => {
76149
+ iterate(filters.equal, "equal" /* EQUAL */, (q2, key, value) => {
76099
76150
  const fnc = allOr ? "orWhereRaw" : "whereRaw";
76100
76151
  if (this.client === "mssql" /* MS_SQL */) {
76101
76152
  return q2[fnc](
@@ -76115,7 +76166,7 @@ var InternalBuilder = class {
76115
76166
  });
76116
76167
  }
76117
76168
  if (filters.notEqual) {
76118
- iterate(filters.notEqual, (q2, key, value) => {
76169
+ iterate(filters.notEqual, "notEqual" /* NOT_EQUAL */, (q2, key, value) => {
76119
76170
  const fnc = allOr ? "orWhereRaw" : "whereRaw";
76120
76171
  if (this.client === "mssql" /* MS_SQL */) {
76121
76172
  return q2[fnc](
@@ -76136,13 +76187,13 @@ var InternalBuilder = class {
76136
76187
  });
76137
76188
  }
76138
76189
  if (filters.empty) {
76139
- iterate(filters.empty, (q2, key) => {
76190
+ iterate(filters.empty, "empty" /* EMPTY */, (q2, key) => {
76140
76191
  const fnc = allOr ? "orWhereNull" : "whereNull";
76141
76192
  return q2[fnc](key);
76142
76193
  });
76143
76194
  }
76144
76195
  if (filters.notEmpty) {
76145
- iterate(filters.notEmpty, (q2, key) => {
76196
+ iterate(filters.notEmpty, "notEmpty" /* NOT_EMPTY */, (q2, key) => {
76146
76197
  const fnc = allOr ? "orWhereNotNull" : "whereNotNull";
76147
76198
  return q2[fnc](key);
76148
76199
  });