@budibase/backend-core 2.33.14 → 3.0.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 +469 -483
- 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/constants/misc.d.ts +2 -1
- package/dist/src/constants/misc.js +1 -0
- package/dist/src/constants/misc.js.map +1 -1
- package/dist/src/environment.d.ts +1 -0
- package/dist/src/environment.js +1 -1
- package/dist/src/environment.js.map +1 -1
- package/dist/src/security/permissions.d.ts +1 -8
- package/dist/src/security/permissions.js +6 -14
- package/dist/src/security/permissions.js.map +1 -1
- package/dist/src/security/roles.d.ts +5 -5
- package/dist/src/security/roles.js +36 -21
- package/dist/src/security/roles.js.map +1 -1
- package/dist/src/sql/sql.js +48 -27
- package/dist/src/sql/sql.js.map +1 -1
- package/dist/tests/core/utilities/mocks/licenses.d.ts +2 -0
- package/dist/tests/core/utilities/mocks/licenses.js +9 -1
- package/dist/tests/core/utilities/mocks/licenses.js.map +1 -1
- package/package.json +4 -4
- package/src/constants/misc.ts +1 -0
- package/src/environment.ts +2 -0
- package/src/security/permissions.ts +5 -9
- package/src/security/roles.ts +36 -15
- package/src/security/tests/permissions.spec.ts +4 -3
- package/src/sql/sql.ts +57 -30
- package/tests/core/utilities/mocks/licenses.ts +8 -0
package/src/sql/sql.ts
CHANGED
|
@@ -179,12 +179,6 @@ class InternalBuilder {
|
|
|
179
179
|
return this.table.schema[column]
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
-
private supportsILike(): boolean {
|
|
183
|
-
return !(
|
|
184
|
-
this.client === SqlClient.ORACLE || this.client === SqlClient.SQL_LITE
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
182
|
private quoteChars(): [string, string] {
|
|
189
183
|
const wrapped = this.knexClient.wrapIdentifier("foo", {})
|
|
190
184
|
return [wrapped[0], wrapped[wrapped.length - 1]]
|
|
@@ -216,8 +210,30 @@ class InternalBuilder {
|
|
|
216
210
|
return formatter.wrap(value, false)
|
|
217
211
|
}
|
|
218
212
|
|
|
219
|
-
private
|
|
220
|
-
|
|
213
|
+
private castIntToString(identifier: string | Knex.Raw): Knex.Raw {
|
|
214
|
+
switch (this.client) {
|
|
215
|
+
case SqlClient.ORACLE: {
|
|
216
|
+
return this.knex.raw("to_char(??)", [identifier])
|
|
217
|
+
}
|
|
218
|
+
case SqlClient.POSTGRES: {
|
|
219
|
+
return this.knex.raw("??::TEXT", [identifier])
|
|
220
|
+
}
|
|
221
|
+
case SqlClient.MY_SQL:
|
|
222
|
+
case SqlClient.MARIADB: {
|
|
223
|
+
return this.knex.raw("CAST(?? AS CHAR)", [identifier])
|
|
224
|
+
}
|
|
225
|
+
case SqlClient.SQL_LITE: {
|
|
226
|
+
// Technically sqlite can actually represent numbers larger than a 64bit
|
|
227
|
+
// int as a string, but it does it using scientific notation (e.g.
|
|
228
|
+
// "1e+20") which is not what we want. Given that the external SQL
|
|
229
|
+
// databases are limited to supporting only 64bit ints, we settle for
|
|
230
|
+
// that here.
|
|
231
|
+
return this.knex.raw("printf('%d', ??)", [identifier])
|
|
232
|
+
}
|
|
233
|
+
case SqlClient.MS_SQL: {
|
|
234
|
+
return this.knex.raw("CONVERT(NVARCHAR, ??)", [identifier])
|
|
235
|
+
}
|
|
236
|
+
}
|
|
221
237
|
}
|
|
222
238
|
|
|
223
239
|
// Unfortuantely we cannot rely on knex's identifier escaping because it trims
|
|
@@ -512,7 +528,7 @@ class InternalBuilder {
|
|
|
512
528
|
if (!matchesTableName) {
|
|
513
529
|
updatedKey = filterKey.replace(
|
|
514
530
|
new RegExp(`^${relationship.column}.`),
|
|
515
|
-
`${aliases
|
|
531
|
+
`${aliases?.[relationship.tableName] || relationship.tableName}.`
|
|
516
532
|
)
|
|
517
533
|
} else {
|
|
518
534
|
updatedKey = filterKey
|
|
@@ -1074,24 +1090,36 @@ class InternalBuilder {
|
|
|
1074
1090
|
)
|
|
1075
1091
|
}
|
|
1076
1092
|
} else {
|
|
1077
|
-
|
|
1093
|
+
if (this.client === SqlClient.ORACLE) {
|
|
1094
|
+
const field = this.convertClobs(`${tableName}.${aggregation.field}`)
|
|
1095
|
+
query = query.select(
|
|
1096
|
+
this.knex.raw(`COUNT(??) as ??`, [field, aggregation.name])
|
|
1097
|
+
)
|
|
1098
|
+
} else {
|
|
1099
|
+
query = query.count(`${aggregation.field} as ${aggregation.name}`)
|
|
1100
|
+
}
|
|
1078
1101
|
}
|
|
1079
1102
|
} else {
|
|
1080
|
-
const
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1103
|
+
const fieldSchema = this.getFieldSchema(aggregation.field)
|
|
1104
|
+
if (!fieldSchema) {
|
|
1105
|
+
// This should not happen in practice.
|
|
1106
|
+
throw new Error(
|
|
1107
|
+
`field schema missing for aggregation target: ${aggregation.field}`
|
|
1108
|
+
)
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
let aggregate = this.knex.raw("??(??)", [
|
|
1112
|
+
this.knex.raw(op),
|
|
1113
|
+
this.rawQuotedIdentifier(`${tableName}.${aggregation.field}`),
|
|
1114
|
+
])
|
|
1115
|
+
|
|
1116
|
+
if (fieldSchema.type === FieldType.BIGINT) {
|
|
1117
|
+
aggregate = this.castIntToString(aggregate)
|
|
1094
1118
|
}
|
|
1119
|
+
|
|
1120
|
+
query = query.select(
|
|
1121
|
+
this.knex.raw("?? as ??", [aggregate, aggregation.name])
|
|
1122
|
+
)
|
|
1095
1123
|
}
|
|
1096
1124
|
}
|
|
1097
1125
|
return query
|
|
@@ -1434,7 +1462,8 @@ class InternalBuilder {
|
|
|
1434
1462
|
schema.constraints?.presence === true ||
|
|
1435
1463
|
schema.type === FieldType.FORMULA ||
|
|
1436
1464
|
schema.type === FieldType.AUTO ||
|
|
1437
|
-
schema.type === FieldType.LINK
|
|
1465
|
+
schema.type === FieldType.LINK ||
|
|
1466
|
+
schema.type === FieldType.AI
|
|
1438
1467
|
) {
|
|
1439
1468
|
continue
|
|
1440
1469
|
}
|
|
@@ -1556,7 +1585,7 @@ class InternalBuilder {
|
|
|
1556
1585
|
query = this.addFilters(query, filters, { relationship: true })
|
|
1557
1586
|
|
|
1558
1587
|
// handle relationships with a CTE for all others
|
|
1559
|
-
if (relationships?.length) {
|
|
1588
|
+
if (relationships?.length && aggregations.length === 0) {
|
|
1560
1589
|
const mainTable =
|
|
1561
1590
|
this.query.tableAliases?.[this.query.endpoint.entityId] ||
|
|
1562
1591
|
this.query.endpoint.entityId
|
|
@@ -1571,10 +1600,8 @@ class InternalBuilder {
|
|
|
1571
1600
|
// add JSON aggregations attached to the CTE
|
|
1572
1601
|
return this.addJsonRelationships(cte, tableName, relationships)
|
|
1573
1602
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
return query
|
|
1577
|
-
}
|
|
1603
|
+
|
|
1604
|
+
return query
|
|
1578
1605
|
}
|
|
1579
1606
|
|
|
1580
1607
|
update(opts: QueryOptions): Knex.QueryBuilder {
|
|
@@ -102,6 +102,14 @@ export const useAppBuilders = () => {
|
|
|
102
102
|
return useFeature(Feature.APP_BUILDERS)
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
export const useBudibaseAI = () => {
|
|
106
|
+
return useFeature(Feature.BUDIBASE_AI)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const useAICustomConfigs = () => {
|
|
110
|
+
return useFeature(Feature.AI_CUSTOM_CONFIGS)
|
|
111
|
+
}
|
|
112
|
+
|
|
105
113
|
// QUOTAS
|
|
106
114
|
|
|
107
115
|
export const setAutomationLogsQuota = (value: number) => {
|