- Add bun test suite: SQL generator and value unit tests, plus MariaDB integration tests gated on BUN_MARIADB_TEST_DB - schema: add --dry-run and require confirmation (or --yes) before dropping tables/columns; block unapproved destructive statements - Always AND targetId with the query, regardless of searchOperator - Initialize lazily on first call; init throws instead of exiting - Generate IN (?, ?, ...) lists for IN / NOT IN - Share value binding between insert and update (booleans, embeddings, function values, "" -> NULL for non-text columns) - Keep Buffers and convert BigInt/Date without a JSON round-trip - DbSQL: report success for empty SELECT results - Run update() in a transaction with row locking - Key the client cache on the full connection config - Consolidate identifier quoting, drop dead code, merge column lookup - Read CLI version from package.json, pin @types/bun, chmod CLI on compile - Rebuild dist Co-Authored-By: Claude Opus 5.5 <[email protected]>
113 lines
4.2 KiB
JavaScript
113 lines
4.2 KiB
JavaScript
import sqlGenOperatorGen from "./sql-gen-operator-gen";
|
|
import { columnRef, sqlLogicalOperator, sqlRawComparison, } from "./sql-identifier";
|
|
export default function sqlGenGenSearchStr({ queryObj, join, field, table_name, }) {
|
|
let sqlSearhValues = [];
|
|
const finalFieldName = (() => {
|
|
if (queryObj?.tableName) {
|
|
return columnRef(String(field), queryObj.tableName);
|
|
}
|
|
if (join) {
|
|
return columnRef(String(field), table_name);
|
|
}
|
|
return columnRef(String(field));
|
|
})();
|
|
let str = `${finalFieldName}=?`;
|
|
function grabValue(val) {
|
|
if (val === undefined || val === null)
|
|
return;
|
|
const isFieldRef = Boolean(typeof val == "object" && val.fieldName && val.tableName);
|
|
const valueString = typeof val == "string" || typeof val == "number"
|
|
? val
|
|
: isFieldRef
|
|
? columnRef(val.fieldName, val.tableName)
|
|
: val.value;
|
|
const valueEquality = typeof val == "object"
|
|
? val.equality || queryObj.equality
|
|
: queryObj.equality;
|
|
return sqlGenOperatorGen({
|
|
queryObj,
|
|
equality: valueEquality,
|
|
fieldName: finalFieldName,
|
|
value: valueString ?? "",
|
|
isValueFieldValue: isFieldRef,
|
|
});
|
|
}
|
|
const listEquality = queryObj.equality == "IN" || queryObj.equality == "NOT IN"
|
|
? queryObj.equality
|
|
: undefined;
|
|
if (listEquality &&
|
|
!queryObj.nullValue &&
|
|
!queryObj.notNullValue &&
|
|
queryObj.value !== undefined &&
|
|
queryObj.value !== null) {
|
|
const rawValues = Array.isArray(queryObj.value)
|
|
? queryObj.value
|
|
: [queryObj.value];
|
|
const listValues = rawValues
|
|
.map((val) => val !== null && typeof val == "object" ? val.value : val)
|
|
.filter((val) => val !== undefined && val !== null);
|
|
if (listValues.length === 0) {
|
|
// Empty IN () is invalid SQL: IN matches nothing, NOT IN matches everything
|
|
str = listEquality == "IN" ? "1 = 0" : "1 = 1";
|
|
}
|
|
else {
|
|
str = `${finalFieldName} ${listEquality} (${listValues.map(() => "?").join(",")})`;
|
|
sqlSearhValues.push(...listValues);
|
|
}
|
|
}
|
|
else if (Array.isArray(queryObj.value)) {
|
|
const strArray = [];
|
|
queryObj.value.forEach((val) => {
|
|
const operatorStrParam = grabValue(val);
|
|
if (!operatorStrParam?.str)
|
|
return;
|
|
strArray.push(operatorStrParam.str);
|
|
if (operatorStrParam.param !== undefined) {
|
|
sqlSearhValues.push(operatorStrParam.param);
|
|
}
|
|
});
|
|
str =
|
|
"(" +
|
|
strArray.join(` ${sqlLogicalOperator(queryObj.operator)} `) +
|
|
")";
|
|
}
|
|
else if (queryObj.value !== null && typeof queryObj.value == "object") {
|
|
const operatorStrParam = grabValue(queryObj.value);
|
|
if (operatorStrParam?.str) {
|
|
str = operatorStrParam.str;
|
|
if (operatorStrParam.param !== undefined) {
|
|
sqlSearhValues.push(operatorStrParam.param);
|
|
}
|
|
}
|
|
}
|
|
else if (queryObj.raw_equality &&
|
|
queryObj.value !== undefined &&
|
|
queryObj.value !== null) {
|
|
str = `${finalFieldName} ${sqlRawComparison(queryObj.raw_equality)} ?`;
|
|
sqlSearhValues.push(queryObj.value);
|
|
}
|
|
else if (queryObj.between) {
|
|
str = `${finalFieldName} BETWEEN ? AND ?`;
|
|
sqlSearhValues.push(queryObj.between.min, queryObj.between.max);
|
|
}
|
|
else if (queryObj.not_between) {
|
|
str = `${finalFieldName} NOT BETWEEN ? AND ?`;
|
|
sqlSearhValues.push(queryObj.not_between.min, queryObj.not_between.max);
|
|
}
|
|
else {
|
|
const operatorStrParam = sqlGenOperatorGen({
|
|
equality: queryObj.equality,
|
|
fieldName: finalFieldName,
|
|
value: queryObj.value ?? undefined,
|
|
queryObj,
|
|
});
|
|
if (operatorStrParam.str) {
|
|
str = operatorStrParam.str;
|
|
}
|
|
if (operatorStrParam.param !== undefined) {
|
|
sqlSearhValues.push(operatorStrParam.param);
|
|
}
|
|
}
|
|
return { str, values: sqlSearhValues };
|
|
}
|