Add queue tables, quote SQL identifiers (v1.3.0)

- isQueue table option adds queue columns and a (status, available_at)
  index; BunSQLite.queue exposes add, claim, complete, fail and
  release_stale with atomic claims
- Set busy_timeout on connections so workers in separate processes wait
  instead of failing with SQLITE_BUSY
- Quote table and column names with backticks in generated SQL, so
  reserved words (to, order, group) work and unknown columns error
  instead of matching as string literals
- Tests for queue ops, multi-process claims and reserved-word names

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-18 16:29:14 +01:00
co-authored by Claude Opus 5.5
parent 07807cb19d
commit 938a1da71d
45 changed files with 1524 additions and 115 deletions
+13 -13
View File
@@ -2,7 +2,7 @@ import { isUndefined } from "lodash";
import sqlGenGrabConcatStr from "./sql-generator-grab-concat-str";
import sqlGenGenJoinStr from "./sql-generator-gen-join-str";
import sqlGenGrabSelectFieldSQL from "./sql-generator-grab-select-field-sql";
import { sqlIdent, sqlJoinType, sqlOperator } from "./sql-safe";
import { sqlName, sqlJoinType, sqlOperator } from "./sql-safe";
export default function sqlGenGenQueryStr(params) {
let str = "SELECT";
const genObject = params.genObject;
@@ -40,9 +40,9 @@ export default function sqlGenGenQueryStr(params) {
const countSubQuery = genObject.countSubQueries[i];
if (!countSubQuery)
continue;
const countTable = sqlIdent(countSubQuery.table, "table name");
const countTable = sqlName(countSubQuery.table, "table name");
const tableAlias = countSubQuery.table_alias
? sqlIdent(countSubQuery.table_alias, "alias")
? sqlName(countSubQuery.table_alias, "alias")
: undefined;
let subQStr = `(SELECT COUNT(*)`;
subQStr += ` FROM ${countTable}${tableAlias ? ` ${tableAlias}` : ""}`;
@@ -51,19 +51,19 @@ export default function sqlGenGenQueryStr(params) {
const csqSrc = countSubQuery.srcTrgMap[j];
if (!csqSrc)
continue;
subQStr += ` ${tableAlias || countTable}.${sqlIdent(csqSrc.src, "field name")}`;
subQStr += ` ${tableAlias || countTable}.${sqlName(csqSrc.src, "field name")}`;
if (typeof csqSrc.trg == "string") {
subQStr += ` = ?`;
sqlSearhValues.push(csqSrc.trg);
}
else if (typeof csqSrc.trg == "object") {
subQStr += ` = ${sqlIdent(csqSrc.trg.table, "table name")}.${sqlIdent(csqSrc.trg.field, "field name")}`;
subQStr += ` = ${sqlName(csqSrc.trg.table, "table name")}.${sqlName(csqSrc.trg.field, "field name")}`;
}
if (j < countSubQuery.srcTrgMap.length - 1) {
subQStr += ` AND `;
}
}
subQStr += ` )) AS ${sqlIdent(countSubQuery.alias, "alias")}`;
subQStr += ` )) AS ${sqlName(countSubQuery.alias, "alias")}`;
countSqls.push(subQStr);
}
str += `, ${countSqls.join(",")}`;
@@ -74,13 +74,13 @@ export default function sqlGenGenQueryStr(params) {
.flat()
.filter((j) => !isUndefined(j))
.map((joinObj) => {
const joinTableName = sqlIdent(joinObj.alias ? joinObj.alias : joinObj.tableName, "join table name");
const joinTableName = sqlName(joinObj.alias ? joinObj.alias : joinObj.tableName, "join table name");
if (existingJoinTableNames.includes(joinTableName))
return null;
existingJoinTableNames.push(joinTableName);
if (joinObj.group_concat) {
return sqlGenGrabConcatStr({
field: `${joinTableName}.${sqlIdent(joinObj.group_concat.field, "field name")}`,
field: `${joinTableName}.${sqlName(joinObj.group_concat.field, "field name")}`,
alias: joinObj.group_concat.alias,
separator: joinObj.group_concat.separator,
distinct: joinObj.group_concat.distinct,
@@ -90,9 +90,9 @@ export default function sqlGenGenQueryStr(params) {
return joinObj.selectFields
.map((selectField) => {
if (typeof selectField != "object") {
return `${joinTableName}.${sqlIdent(selectField, "field name")}`;
return `${joinTableName}.${sqlName(selectField, "field name")}`;
}
const field = `${joinTableName}.${sqlIdent(selectField.field, "field name")}`;
const field = `${joinTableName}.${sqlName(selectField.field, "field name")}`;
if (selectField.group_concat &&
selectField.alias) {
return sqlGenGrabConcatStr({
@@ -122,7 +122,7 @@ export default function sqlGenGenQueryStr(params) {
aliasSelectField = `DISTINCT ${field}`;
}
if (selectField.alias)
aliasSelectField += ` AS ${sqlIdent(selectField.alias, "alias")}`;
aliasSelectField += ` AS ${sqlName(selectField.alias, "alias")}`;
return aliasSelectField;
})
.join(",");
@@ -145,11 +145,11 @@ export default function sqlGenGenQueryStr(params) {
.flat()
.filter((j) => !isUndefined(j))
.map((join) => {
const joinTable = sqlIdent(join.tableName, "table name");
const joinTable = sqlName(join.tableName, "table name");
return (sqlJoinType(join.joinType) +
" " +
(join.alias
? `${joinTable} ${sqlIdent(join.alias, "alias")}`
? `${joinTable} ${sqlName(join.alias, "alias")}`
: joinTable) +
" ON " +
(() => {