Files
supabase/apps/studio/data/table-rows/table-rows.sql.ts
T
2026-03-05 20:05:22 +08:00

93 lines
2.8 KiB
TypeScript

import { Query } from '@supabase/pg-meta/src/query'
import { GetTableRowsCountArgs } from './table-rows-count-query'
import { COUNT_ESTIMATE_SQL, THRESHOLD_COUNT } from './table-rows-constants'
import { formatFilterValue } from './utils'
export { COUNT_ESTIMATE_SQL, THRESHOLD_COUNT }
/**
* [Joshen] Initially check reltuples from pg_class for an estimate of row count on the table
* - If reltuples = -1, table never been analyzed, assume small table -> return exact count
* - If reltuples exceeds threshold, return estimate count
* - Else return exact count
*/
export const getTableRowsCountSql = ({
table,
filters = [],
enforceExactCount = false,
isUsingReadReplica = false,
}: GetTableRowsCountArgs & { isUsingReadReplica?: boolean }) => {
if (!table) return ``
if (enforceExactCount) {
const query = new Query()
let queryChains = query.from(table.name, table.schema ?? undefined).count()
filters
.filter((x) => x.value && x.value !== '')
.forEach((x) => {
const value = formatFilterValue(table, x)
queryChains = queryChains.filter(x.column, x.operator, value)
})
return `select (${queryChains.toSql().slice(0, -1)}), false as is_estimate;`
} else {
const selectQuery = new Query()
let selectQueryChains = selectQuery.from(table.name, table.schema ?? undefined).select('*')
filters
.filter((x) => x.value && x.value != '')
.forEach((x) => {
const value = formatFilterValue(table, x)
selectQueryChains = selectQueryChains.filter(x.column, x.operator, value)
})
const selectBaseSql = selectQueryChains.toSql()
const countQuery = new Query()
let countQueryChains = countQuery.from(table.name, table.schema ?? undefined).count()
filters
.filter((x) => x.value && x.value != '')
.forEach((x) => {
const value = formatFilterValue(table, x)
countQueryChains = countQueryChains.filter(x.column, x.operator, value)
})
const countBaseSql = countQueryChains.toSql().slice(0, -1)
if (isUsingReadReplica) {
const sql = `
with approximation as (
select reltuples as estimate
from pg_class
where oid = ${table.id}
)
select
case
when estimate > ${THRESHOLD_COUNT} then (select -1)
else (${countBaseSql})
end as count,
estimate > ${THRESHOLD_COUNT} as is_estimate
from approximation;
`.trim()
return sql
} else {
const sql = `
${COUNT_ESTIMATE_SQL}
with approximation as (
select reltuples as estimate
from pg_class
where oid = ${table.id}
)
select
case
when estimate > ${THRESHOLD_COUNT} then ${filters.length > 0 ? `pg_temp.count_estimate('${selectBaseSql.replaceAll("'", "''")}')` : 'estimate'}
else (${countBaseSql})
end as count,
estimate > ${THRESHOLD_COUNT} as is_estimate
from approximation;
`.trim()
return sql
}
}
}