@budibase/backend-core 2.29.0 → 2.29.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.
package/dist/index.js CHANGED
@@ -54802,6 +54802,20 @@ var SWITCHABLE_TYPES = {
54802
54802
  ["number" /* NUMBER */]: ["number" /* NUMBER */, "boolean" /* BOOLEAN */]
54803
54803
  };
54804
54804
 
54805
+ // ../shared-core/src/constants/rows.ts
54806
+ var CONSTANT_INTERNAL_ROW_COLS = [
54807
+ "_id",
54808
+ "_rev",
54809
+ "type",
54810
+ "createdAt",
54811
+ "updatedAt",
54812
+ "tableId"
54813
+ ];
54814
+ var CONSTANT_EXTERNAL_ROW_COLS = ["_id", "_rev", "tableId"];
54815
+ function isInternalColumnName(name) {
54816
+ return CONSTANT_INTERNAL_ROW_COLS.includes(name);
54817
+ }
54818
+
54805
54819
  // ../shared-core/src/constants/index.ts
54806
54820
  var OperatorOptions = {
54807
54821
  Equals: {
@@ -55217,10 +55231,15 @@ var search = (docs, query) => {
55217
55231
  if (query.sort) {
55218
55232
  result = sort(result, query.sort, query.sortOrder || "ascending" /* ASCENDING */);
55219
55233
  }
55234
+ let totalRows = result.length;
55220
55235
  if (query.limit) {
55221
55236
  result = limit(result, query.limit.toString());
55222
55237
  }
55223
- return result;
55238
+ const response = { rows: result };
55239
+ if (query.countRows) {
55240
+ response.totalRows = totalRows;
55241
+ }
55242
+ return response;
55224
55243
  };
55225
55244
  var runQuery = (docs, query) => {
55226
55245
  if (!docs || !Array.isArray(docs)) {
@@ -56728,20 +56747,6 @@ var DatabaseImpl = class _DatabaseImpl {
56728
56747
  }
56729
56748
  };
56730
56749
 
56731
- // src/db/constants.ts
56732
- var CONSTANT_INTERNAL_ROW_COLS = [
56733
- "_id",
56734
- "_rev",
56735
- "type",
56736
- "createdAt",
56737
- "updatedAt",
56738
- "tableId"
56739
- ];
56740
- var CONSTANT_EXTERNAL_ROW_COLS = ["_id", "_rev", "tableId"];
56741
- function isInternalColumnName(name) {
56742
- return CONSTANT_INTERNAL_ROW_COLS.includes(name);
56743
- }
56744
-
56745
56750
  // src/db/db.ts
56746
56751
  function getDB(dbName, opts) {
56747
56752
  return new DDInstrumentedDatabase(new DatabaseImpl(dbName, opts));
@@ -67496,7 +67501,7 @@ function parseFilters(filters) {
67496
67501
  }
67497
67502
  function generateSelectStatement(json, knex3) {
67498
67503
  const { resource, meta } = json;
67499
- if (!resource) {
67504
+ if (!resource || !resource.fields || resource.fields.length === 0) {
67500
67505
  return "*";
67501
67506
  }
67502
67507
  const schema = meta?.table?.schema;
@@ -67743,12 +67748,26 @@ var InternalBuilder = class {
67743
67748
  }
67744
67749
  return query;
67745
67750
  }
67751
+ addDistinctCount(query, json) {
67752
+ const table = json.meta.table;
67753
+ const primary = table.primary;
67754
+ const aliases = json.tableAliases;
67755
+ const aliased = table.name && aliases?.[table.name] ? aliases[table.name] : table.name;
67756
+ if (!primary) {
67757
+ throw new Error("SQL counting requires primary key to be supplied");
67758
+ }
67759
+ return query.countDistinct(`${aliased}.${primary[0]} as total`);
67760
+ }
67746
67761
  addSorting(query, json) {
67747
- let { sort: sort2, paginate } = json;
67762
+ let { sort: sort2 } = json;
67748
67763
  const table = json.meta.table;
67764
+ const primaryKey = table.primary;
67749
67765
  const tableName = getTableName(table);
67750
67766
  const aliases = json.tableAliases;
67751
67767
  const aliased = tableName && aliases?.[tableName] ? aliases[tableName] : table?.name;
67768
+ if (!Array.isArray(primaryKey)) {
67769
+ throw new Error("Sorting requires primary key to be specified for table");
67770
+ }
67752
67771
  if (sort2 && Object.keys(sort2 || {}).length > 0) {
67753
67772
  for (let [key, value] of Object.entries(sort2)) {
67754
67773
  const direction = value.direction === "ascending" /* ASCENDING */ ? "asc" : "desc";
@@ -67758,9 +67777,8 @@ var InternalBuilder = class {
67758
67777
  }
67759
67778
  query = query.orderBy(`${aliased}.${key}`, direction, nulls);
67760
67779
  }
67761
- } else if (this.client === "mssql" /* MS_SQL */ && paginate?.limit) {
67762
- query = query.orderBy(`${aliased}.${table?.primary[0]}`);
67763
67780
  }
67781
+ query = query.orderBy(`${aliased}.${primaryKey[0]}`);
67764
67782
  return query;
67765
67783
  }
67766
67784
  tableNameWithSchema(tableName, opts) {
@@ -67828,18 +67846,17 @@ var InternalBuilder = class {
67828
67846
  });
67829
67847
  }
67830
67848
  }
67831
- return query.limit(BASE_LIMIT);
67849
+ return query;
67832
67850
  }
67833
67851
  knexWithAlias(knex3, endpoint, aliases) {
67834
67852
  const tableName = endpoint.entityId;
67835
67853
  const tableAlias = aliases?.[tableName];
67836
- const query = knex3(
67854
+ return knex3(
67837
67855
  this.tableNameWithSchema(tableName, {
67838
67856
  alias: tableAlias,
67839
67857
  schema: endpoint.schema
67840
67858
  })
67841
67859
  );
67842
- return query;
67843
67860
  }
67844
67861
  create(knex3, json, opts) {
67845
67862
  const { endpoint, body: body2 } = json;
@@ -67883,18 +67900,14 @@ var InternalBuilder = class {
67883
67900
  }
67884
67901
  return query.upsert(parsedBody);
67885
67902
  }
67886
- read(knex3, json, limit2) {
67887
- let { endpoint, resource, filters, paginate, relationships, tableAliases } = json;
67903
+ read(knex3, json, opts = {}) {
67904
+ let { endpoint, filters, paginate, relationships, tableAliases } = json;
67905
+ const { limits } = opts;
67906
+ const counting = endpoint.operation === "COUNT" /* COUNT */;
67888
67907
  const tableName = endpoint.entityId;
67889
- if (!resource) {
67890
- resource = { fields: [] };
67891
- }
67892
- let selectStatement = "*";
67893
- if (resource.fields && resource.fields.length > 0) {
67894
- selectStatement = generateSelectStatement(json, knex3);
67895
- }
67896
- let foundLimit = limit2 || BASE_LIMIT;
67908
+ let query = this.knexWithAlias(knex3, endpoint, tableAliases);
67897
67909
  let foundOffset = null;
67910
+ let foundLimit = limits?.query || limits?.base;
67898
67911
  if (paginate && paginate.page && paginate.limit) {
67899
67912
  const page = paginate.page <= 1 ? 0 : paginate.page - 1;
67900
67913
  const offset = page * paginate.limit;
@@ -67906,20 +67919,28 @@ var InternalBuilder = class {
67906
67919
  } else if (paginate && paginate.limit) {
67907
67920
  foundLimit = paginate.limit;
67908
67921
  }
67909
- let query = this.knexWithAlias(knex3, endpoint, tableAliases);
67910
- query = query.limit(foundLimit);
67911
- if (foundOffset) {
67912
- query = query.offset(foundOffset);
67922
+ if (!counting) {
67923
+ if (foundLimit != null) {
67924
+ query = query.limit(foundLimit);
67925
+ }
67926
+ if (foundOffset != null) {
67927
+ query = query.offset(foundOffset);
67928
+ }
67929
+ query = this.addSorting(query, json);
67913
67930
  }
67914
67931
  query = this.addFilters(query, filters, json.meta.table, {
67915
67932
  aliases: tableAliases
67916
67933
  });
67917
- query = this.addSorting(query, json);
67918
67934
  const alias = tableAliases?.[tableName] || tableName;
67919
67935
  let preQuery = knex3({
67936
+ // the typescript definition for the knex constructor doesn't support this
67937
+ // syntax, but it is the only way to alias a pre-query result as part of
67938
+ // a query - there is an alias dictionary type, but it assumes it can only
67939
+ // be a table name, not a pre-query
67920
67940
  [alias]: query
67921
- }).select(selectStatement);
67922
- if (this.client !== "mssql" /* MS_SQL */) {
67941
+ });
67942
+ preQuery = !counting ? preQuery.select(generateSelectStatement(json, knex3)) : this.addDistinctCount(preQuery, json);
67943
+ if (this.client !== "mssql" /* MS_SQL */ && !counting) {
67923
67944
  preQuery = this.addSorting(preQuery, json);
67924
67945
  }
67925
67946
  query = this.addRelationships(
@@ -67929,6 +67950,9 @@ var InternalBuilder = class {
67929
67950
  endpoint.schema,
67930
67951
  tableAliases
67931
67952
  );
67953
+ if (limits?.base) {
67954
+ query = query.limit(limits.base);
67955
+ }
67932
67956
  return this.addFilters(query, filters, json.meta.table, {
67933
67957
  relationship: true,
67934
67958
  aliases: tableAliases
@@ -67966,6 +67990,18 @@ var SqlQueryBuilder = class extends sqlTable_default {
67966
67990
  super(client);
67967
67991
  this.limit = limit2;
67968
67992
  }
67993
+ convertToNative(query, opts = {}) {
67994
+ const sqlClient = this.getSqlClient();
67995
+ if (opts?.disableBindings) {
67996
+ return { sql: query.toString() };
67997
+ } else {
67998
+ let native = getNativeSql(query);
67999
+ if (sqlClient === "sqlite3" /* SQL_LITE */) {
68000
+ native = convertBooleans(native);
68001
+ }
68002
+ return native;
68003
+ }
68004
+ }
67969
68005
  /**
67970
68006
  * @param json The JSON query DSL which is to be converted to SQL.
67971
68007
  * @param opts extra options which are to be passed into the query builder, e.g. disableReturning
@@ -67988,7 +68024,15 @@ var SqlQueryBuilder = class extends sqlTable_default {
67988
68024
  query = builder.create(client, json, opts);
67989
68025
  break;
67990
68026
  case "READ" /* READ */:
67991
- query = builder.read(client, json, this.limit);
68027
+ query = builder.read(client, json, {
68028
+ limits: {
68029
+ query: this.limit,
68030
+ base: BASE_LIMIT
68031
+ }
68032
+ });
68033
+ break;
68034
+ case "COUNT" /* COUNT */:
68035
+ query = builder.read(client, json);
67992
68036
  break;
67993
68037
  case "UPDATE" /* UPDATE */:
67994
68038
  query = builder.update(client, json, opts);
@@ -68009,15 +68053,7 @@ var SqlQueryBuilder = class extends sqlTable_default {
68009
68053
  default:
68010
68054
  throw `Operation type is not supported by SQL query builder`;
68011
68055
  }
68012
- if (opts?.disableBindings) {
68013
- return { sql: query.toString() };
68014
- } else {
68015
- let native = getNativeSql(query);
68016
- if (sqlClient === "sqlite3" /* SQL_LITE */) {
68017
- native = convertBooleans(native);
68018
- }
68019
- return native;
68020
- }
68056
+ return this.convertToNative(query, opts);
68021
68057
  }
68022
68058
  async getReturningRow(queryFn, json) {
68023
68059
  if (!json.extra || !json.extra.idFilter) {
@@ -68084,6 +68120,9 @@ var SqlQueryBuilder = class extends sqlTable_default {
68084
68120
  await this.getReturningRow(queryFn, this.checkLookupKeys(id, json))
68085
68121
  );
68086
68122
  }
68123
+ if (operation === "COUNT" /* COUNT */) {
68124
+ return results;
68125
+ }
68087
68126
  if (operation !== "READ" /* READ */) {
68088
68127
  return row;
68089
68128
  }