1
0
Fork 0
mirror of synced 2024-07-13 02:05:54 +12:00

Changing how counting occurs in SQL layer.

This commit is contained in:
mike12345567 2024-06-19 14:56:06 +01:00
parent aab100b130
commit 1056efdbf6

View file

@ -595,19 +595,23 @@ class InternalBuilder {
return query.upsert(parsedBody) return query.upsert(parsedBody)
} }
read(knex: Knex, json: QueryJson, limit: number): Knex.QueryBuilder { read(
knex: Knex,
json: QueryJson,
limits?: { base?: number; query?: number }
): Knex.QueryBuilder {
let { endpoint, resource, filters, paginate, relationships, tableAliases } = let { endpoint, resource, filters, paginate, relationships, tableAliases } =
json json
const counting = endpoint.operation === Operation.COUNT
const tableName = endpoint.entityId const tableName = endpoint.entityId
const counting = endpoint.operation === Operation.COUNT
// select all if not specified // select all if not specified
if (!resource) { if (!resource) {
resource = { fields: [] } resource = { fields: [] }
} }
let selectStatement: string | (string | Knex.Raw)[] = "*" let selectStatement: string | (string | Knex.Raw)[] = "*"
// handle select // handle select
if (!counting && resource.fields && resource.fields.length > 0) { if (resource.fields && resource.fields.length > 0) {
// select the resources as the format "table.columnName" - this is what is provided // select the resources as the format "table.columnName" - this is what is provided
// by the resource builder further up // by the resource builder further up
selectStatement = generateSelectStatement(json, knex) selectStatement = generateSelectStatement(json, knex)
@ -616,7 +620,7 @@ class InternalBuilder {
let query = this.knexWithAlias(knex, endpoint, tableAliases) let query = this.knexWithAlias(knex, endpoint, tableAliases)
// handle pagination // handle pagination
let foundOffset: number | null = null let foundOffset: number | null = null
let foundLimit = limit || BASE_LIMIT let foundLimit = limits?.query || limits?.base
if (paginate && paginate.page && paginate.limit) { if (paginate && paginate.page && paginate.limit) {
// @ts-ignore // @ts-ignore
const page = paginate.page <= 1 ? 0 : paginate.page - 1 const page = paginate.page <= 1 ? 0 : paginate.page - 1
@ -629,12 +633,12 @@ class InternalBuilder {
} else if (paginate && paginate.limit) { } else if (paginate && paginate.limit) {
foundLimit = paginate.limit foundLimit = paginate.limit
} }
// always add the found limit, unless counting // add the found limit if supplied
if (!counting) { if (foundLimit) {
query = query.limit(foundLimit) query = query.limit(foundLimit)
} }
// add overall pagination // add overall pagination
if (!counting && foundOffset) { if (foundOffset) {
query = query.offset(foundOffset) query = query.offset(foundOffset)
} }
// add filters to the query (where) // add filters to the query (where)
@ -642,9 +646,11 @@ class InternalBuilder {
aliases: tableAliases, aliases: tableAliases,
}) })
// add sorting to pre-query // add sorting to pre-query
// no point in sorting when counting
if (!counting) { if (!counting) {
query = this.addSorting(query, json) query = this.addSorting(query, json)
} }
const alias = tableAliases?.[tableName] || tableName const alias = tableAliases?.[tableName] || tableName
let preQuery: Knex.QueryBuilder = knex({ let preQuery: Knex.QueryBuilder = knex({
// the typescript definition for the knex constructor doesn't support this // the typescript definition for the knex constructor doesn't support this
@ -653,11 +659,7 @@ class InternalBuilder {
// be a table name, not a pre-query // be a table name, not a pre-query
[alias]: query as any, [alias]: query as any,
}) })
if (counting) { preQuery = preQuery.select(selectStatement)
preQuery = preQuery.count("* as total")
} else {
preQuery = preQuery.select(selectStatement)
}
// have to add after as well (this breaks MS-SQL) // have to add after as well (this breaks MS-SQL)
if (this.client !== SqlClient.MS_SQL && !counting) { if (this.client !== SqlClient.MS_SQL && !counting) {
preQuery = this.addSorting(preQuery, json) preQuery = this.addSorting(preQuery, json)
@ -672,8 +674,9 @@ class InternalBuilder {
) )
// add a base limit over the whole query // add a base limit over the whole query
if (!counting) { // if counting we can't set this limit
query = query.limit(BASE_LIMIT) if (limits?.base) {
query = query.limit(limits.base)
} }
return this.addFilters(query, filters, json.meta.table, { return this.addFilters(query, filters, json.meta.table, {
@ -682,6 +685,15 @@ class InternalBuilder {
}) })
} }
count(knex: Knex, json: QueryJson) {
const readQuery = this.read(knex, json)
// have to alias the sub-query, this is a requirement for my-sql and ms-sql
// without this we get an error "Every derived table must have its own alias"
return knex({
subquery: readQuery as any,
}).count("* as total")
}
update(knex: Knex, json: QueryJson, opts: QueryOptions): Knex.QueryBuilder { update(knex: Knex, json: QueryJson, opts: QueryOptions): Knex.QueryBuilder {
const { endpoint, body, filters, tableAliases } = json const { endpoint, body, filters, tableAliases } = json
let query = this.knexWithAlias(knex, endpoint, tableAliases) let query = this.knexWithAlias(knex, endpoint, tableAliases)
@ -756,8 +768,13 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
query = builder.create(client, json, opts) query = builder.create(client, json, opts)
break break
case Operation.READ: case Operation.READ:
query = builder.read(client, json, {
query: this.limit,
base: BASE_LIMIT,
})
break
case Operation.COUNT: case Operation.COUNT:
query = builder.read(client, json, this.limit) query = builder.count(client, json)
break break
case Operation.UPDATE: case Operation.UPDATE:
query = builder.update(client, json, opts) query = builder.update(client, json, opts)