Base implementation of counting (plumbing).

This commit is contained in:
mike12345567 2024-06-14 14:35:14 +01:00
parent d47c7d9227
commit 7491021ca0
4 changed files with 66 additions and 26 deletions

View File

@ -12,6 +12,7 @@ import {
SortOrder,
SortType,
SqlClient,
SqlQuery,
Table,
} from "@budibase/types"
import {
@ -101,12 +102,29 @@ function buildTableMap(tables: Table[]) {
return tableMap
}
async function runSqlQuery(json: QueryJson, tables: Table[]) {
function runSqlQuery(json: QueryJson, tables: Table[]): Promise<Row[]>
function runSqlQuery(
json: QueryJson,
tables: Table[],
opts: { countTotalRows: boolean }
): Promise<number>
async function runSqlQuery(
json: QueryJson,
tables: Table[],
opts?: { countTotalRows?: boolean }
) {
const alias = new AliasTables(tables.map(table => table.name))
return await alias.queryWithAliasing(json, async json => {
const query = builder._query(json, {
disableReturning: true,
})
const processSQLQuery = async (json: QueryJson) => {
let query: SqlQuery | SqlQuery[]
if (opts?.countTotalRows) {
query = builder._count(json, {
disableReturning: true,
})
} else {
query = builder._query(json, {
disableReturning: true,
})
}
if (Array.isArray(query)) {
throw new Error("SQS cannot currently handle multiple queries")
@ -125,7 +143,12 @@ async function runSqlQuery(json: QueryJson, tables: Table[]) {
const db = context.getAppDB()
return await db.sql<Row>(sql, bindings)
})
}
if (opts?.countTotalRows) {
return await alias.countWithAliasing(json, processSQLQuery)
} else {
return await alias.queryWithAliasing(json, processSQLQuery)
}
}
export async function search(
@ -204,8 +227,11 @@ export async function search(
)
// check for pagination final row
let nextRow: Row | undefined
let nextRow: Row | undefined, rowCount: number | undefined
if (paginate && params.limit && processed.length > params.limit) {
// get the total count of rows
rowCount = await runSqlQuery(request, allTables, { countTotalRows: true })
// remove the extra row that confirmed if there is another row to move to
nextRow = processed.pop()
}
@ -226,14 +252,10 @@ export async function search(
const response: SearchResponse<Row> = {
rows: finalRows,
}
const prevLimit = request.paginate!.limit
request.paginate = {
limit: 1,
page: bookmark * prevLimit + 1,
}
const hasNextPage = !!nextRow
response.hasNextPage = hasNextPage
if (hasNextPage) {
response.totalRows = rowCount
response.bookmark = bookmark + 1
}
return response

View File

@ -65,7 +65,7 @@ export default class AliasTables {
this.charSeq = new CharSequence()
}
isAliasingEnabled(json: QueryJson, datasource: Datasource) {
isAliasingEnabled(json: QueryJson, datasource?: Datasource) {
const operation = json.endpoint.operation
const fieldLength = json.resource?.fields?.length
if (
@ -75,6 +75,10 @@ export default class AliasTables {
) {
return false
}
// SQS - doesn't have a datasource
if (!datasource) {
return true
}
try {
const sqlClient = getSQLClient(datasource)
const isWrite = WRITE_OPERATIONS.includes(operation)
@ -173,7 +177,7 @@ export default class AliasTables {
const isSqs = datasourceId === SQS_DATASOURCE_INTERNAL
let aliasingEnabled: boolean, datasource: Datasource | undefined
if (isSqs) {
aliasingEnabled = true
aliasingEnabled = this.isAliasingEnabled(json)
} else {
datasource = await datasources.get(datasourceId)
aliasingEnabled = this.isAliasingEnabled(json, datasource)
@ -239,4 +243,17 @@ export default class AliasTables {
return response
}
}
// handles getting the count out of the query
async countWithAliasing(
json: QueryJson,
queryFn?: (json: QueryJson) => Promise<DatasourcePlusQueryResponse>
): Promise<number> {
let response = await this.queryWithAliasing(json, queryFn)
if (response && response.length === 1 && "total" in response[0]) {
return response[0].total
} else {
throw new Error("Unable to count rows in query - no count response")
}
}
}

View File

@ -8,6 +8,7 @@ export enum Operation {
READ = "READ",
UPDATE = "UPDATE",
DELETE = "DELETE",
COUNT = "COUNT",
BULK_CREATE = "BULK_CREATE",
CREATE_TABLE = "CREATE_TABLE",
UPDATE_TABLE = "UPDATE_TABLE",

View File

@ -3495,10 +3495,10 @@
dependencies:
lodash "^4.17.21"
"@koa/cors@^3.1.0":
version "3.4.3"
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-3.4.3.tgz#d669ee6e8d6e4f0ec4a7a7b0a17e7a3ed3752ebb"
integrity sha512-WPXQUaAeAMVaLTEFpoq3T2O1C+FstkjJnDQqy95Ck1UdILajsRhu6mhJ8H2f4NFPRBoCNN+qywTJfq/gGki5mw==
"@koa/cors@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd"
integrity sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==
dependencies:
vary "^1.1.2"
@ -5817,10 +5817,10 @@
"@types/koa-compose" "*"
"@types/node" "*"
"@types/koa__cors@^3.1.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-3.3.1.tgz#0ec7543c4c620fd23451bfdd3e21b9a6aadedccd"
integrity sha512-aFGYhTFW7651KhmZZ05VG0QZJre7QxBxDj2LF1lf6GA/wSXEfKVAJxiQQWzRV4ZoMzQIO8vJBXKsUcRuvYK9qw==
"@types/koa__cors@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-5.0.0.tgz#74567a045b599266e2cd3940cef96cedecc2ef1f"
integrity sha512-LCk/n25Obq5qlernGOK/2LUwa/2YJb2lxHUkkvYFDOpLXlVI6tKcdfCHRBQnOY4LwH6el5WOLs6PD/a8Uzau6g==
dependencies:
"@types/koa" "*"
@ -16343,10 +16343,10 @@ node-source-walk@^5.0.0:
dependencies:
"@babel/parser" "^7.0.0"
nodemailer@6.7.2:
version "6.7.2"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.2.tgz#44b2ad5f7ed71b7067f7a21c4fedabaec62b85e0"
integrity sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q==
nodemailer@6.9.13:
version "6.9.13"
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.13.tgz#5b292bf1e92645f4852ca872c56a6ba6c4a3d3d6"
integrity sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==
nodemailer@6.9.9:
version "6.9.9"