re-jigging things to get counting working properly again.
This commit is contained in:
parent
a97b24658f
commit
2aa911b217
|
@ -114,7 +114,7 @@ function generateSelectStatement(
|
||||||
): (string | Knex.Raw)[] | "*" {
|
): (string | Knex.Raw)[] | "*" {
|
||||||
const { resource, meta } = json
|
const { resource, meta } = json
|
||||||
|
|
||||||
if (!resource) {
|
if (!resource || !resource.fields || resource.fields.length === 0) {
|
||||||
return "*"
|
return "*"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,14 +410,32 @@ class InternalBuilder {
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addDistinctCount(
|
||||||
|
query: Knex.QueryBuilder,
|
||||||
|
json: QueryJson
|
||||||
|
): Knex.QueryBuilder {
|
||||||
|
const table = json.meta.table
|
||||||
|
const primary = table.primary
|
||||||
|
const aliases = json.tableAliases
|
||||||
|
const aliased =
|
||||||
|
table.name && aliases?.[table.name] ? aliases[table.name] : table.name
|
||||||
|
if (!primary) {
|
||||||
|
throw new Error("SQL counting requires primary key to be supplied")
|
||||||
|
}
|
||||||
|
return query.countDistinct(`${aliased}.${primary[0]} as total`)
|
||||||
|
}
|
||||||
|
|
||||||
addSorting(query: Knex.QueryBuilder, json: QueryJson): Knex.QueryBuilder {
|
addSorting(query: Knex.QueryBuilder, json: QueryJson): Knex.QueryBuilder {
|
||||||
let { sort } = json
|
let { sort } = json
|
||||||
const table = json.meta.table
|
const table = json.meta.table
|
||||||
const mainPrimaryKey = table.primary![0]
|
const primaryKey = table.primary
|
||||||
const tableName = getTableName(table)
|
const tableName = getTableName(table)
|
||||||
const aliases = json.tableAliases
|
const aliases = json.tableAliases
|
||||||
const aliased =
|
const aliased =
|
||||||
tableName && aliases?.[tableName] ? aliases[tableName] : table?.name
|
tableName && aliases?.[tableName] ? aliases[tableName] : table?.name
|
||||||
|
if (!Array.isArray(primaryKey)) {
|
||||||
|
throw new Error("Sorting requires primary key to be specified for table")
|
||||||
|
}
|
||||||
if (sort && Object.keys(sort || {}).length > 0) {
|
if (sort && Object.keys(sort || {}).length > 0) {
|
||||||
for (let [key, value] of Object.entries(sort)) {
|
for (let [key, value] of Object.entries(sort)) {
|
||||||
const direction =
|
const direction =
|
||||||
|
@ -432,7 +450,7 @@ class InternalBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// always add sorting by the primary key - make sure result is deterministic
|
// always add sorting by the primary key - make sure result is deterministic
|
||||||
query = query.orderBy(`${aliased}.${mainPrimaryKey}`)
|
query = query.orderBy(`${aliased}.${primaryKey[0]}`)
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,25 +618,13 @@ class InternalBuilder {
|
||||||
json: QueryJson,
|
json: QueryJson,
|
||||||
opts: {
|
opts: {
|
||||||
limits?: { base: number; query: number }
|
limits?: { base: number; query: number }
|
||||||
disableSorting?: boolean
|
|
||||||
} = {}
|
} = {}
|
||||||
): Knex.QueryBuilder {
|
): Knex.QueryBuilder {
|
||||||
let { endpoint, resource, filters, paginate, relationships, tableAliases } =
|
let { endpoint, filters, paginate, relationships, tableAliases } = json
|
||||||
json
|
const { limits } = opts
|
||||||
const { limits, disableSorting } = opts
|
const counting = endpoint.operation === Operation.COUNT
|
||||||
|
|
||||||
const tableName = endpoint.entityId
|
const tableName = endpoint.entityId
|
||||||
// select all if not specified
|
|
||||||
if (!resource) {
|
|
||||||
resource = { fields: [] }
|
|
||||||
}
|
|
||||||
let selectStatement: string | (string | Knex.Raw)[] = "*"
|
|
||||||
// handle select
|
|
||||||
if (resource.fields && resource.fields.length > 0) {
|
|
||||||
// select the resources as the format "table.columnName" - this is what is provided
|
|
||||||
// by the resource builder further up
|
|
||||||
selectStatement = generateSelectStatement(json, knex)
|
|
||||||
}
|
|
||||||
// start building the query
|
// start building the query
|
||||||
let query = this.knexWithAlias(knex, endpoint, tableAliases)
|
let query = this.knexWithAlias(knex, endpoint, tableAliases)
|
||||||
// handle pagination
|
// handle pagination
|
||||||
|
@ -650,7 +656,7 @@ class InternalBuilder {
|
||||||
})
|
})
|
||||||
// add sorting to pre-query
|
// add sorting to pre-query
|
||||||
// no point in sorting when counting
|
// no point in sorting when counting
|
||||||
if (!disableSorting) {
|
if (!counting) {
|
||||||
query = this.addSorting(query, json)
|
query = this.addSorting(query, json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,9 +668,13 @@ 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,
|
||||||
})
|
})
|
||||||
preQuery = preQuery.select(selectStatement)
|
if (!counting) {
|
||||||
|
preQuery = preQuery.select(generateSelectStatement(json, knex))
|
||||||
|
} else {
|
||||||
|
preQuery = this.addDistinctCount(preQuery, json)
|
||||||
|
}
|
||||||
// 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 && !disableSorting) {
|
if (this.client !== SqlClient.MS_SQL && !counting) {
|
||||||
preQuery = this.addSorting(preQuery, json)
|
preQuery = this.addSorting(preQuery, json)
|
||||||
}
|
}
|
||||||
// handle joins
|
// handle joins
|
||||||
|
@ -688,17 +698,6 @@ class InternalBuilder {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
count(knex: Knex, json: QueryJson) {
|
|
||||||
const readQuery = this.read(knex, json, {
|
|
||||||
disableSorting: true,
|
|
||||||
})
|
|
||||||
// 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)
|
||||||
|
@ -781,7 +780,8 @@ class SqlQueryBuilder extends SqlTableQueryBuilder {
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
case Operation.COUNT:
|
case Operation.COUNT:
|
||||||
query = builder.count(client, json)
|
// read without any limits to count
|
||||||
|
query = builder.read(client, json)
|
||||||
break
|
break
|
||||||
case Operation.UPDATE:
|
case Operation.UPDATE:
|
||||||
query = builder.update(client, json, opts)
|
query = builder.update(client, json, opts)
|
||||||
|
|
Loading…
Reference in New Issue