import sqlEqualityParser from "./sql-equality-parser"; import { sqlIdent } from "./sql-safe"; /** * # SQL Gen Operator Gen * @description Generates an SQL condition for a single field. Literal values * are always returned in `params` to be bound, never inlined. */ export default function sqlGenOperatorGen({ fieldName, value, equality, queryObj, isValueFieldValue, }) { if (queryObj.nullValue || equality == "IS NULL") { return { str: `${fieldName} IS NULL`, params: [] }; } if (queryObj.notNullValue || equality == "IS NOT NULL") { return { str: `${fieldName} IS NOT NULL`, params: [] }; } const finalValue = isValueFieldValue ? String(value) : "?"; const params = isValueFieldValue ? [] : [value ?? ""]; const wrappedValue = isValueFieldValue ? `'%' || ${value} || '%'` : "?"; const wrappedParams = isValueFieldValue ? [] : [`%${value ?? ""}%`]; switch (equality) { case "MATCH": case "MATCH_BOOLEAN": case "FULLTEXT": { const matchValue = queryObj.vectorFunction && !isValueFieldValue ? `${sqlIdent(queryObj.vectorFunction, "vector function")}(?)` : finalValue; return { str: `${fieldName} MATCH ${matchValue}`, params }; } case "LIKE_LOWER": return { str: `LOWER(${fieldName}) LIKE LOWER(${wrappedValue})`, params: wrappedParams, }; case "LIKE_LOWER_RAW": return { str: `LOWER(${fieldName}) LIKE LOWER(${finalValue})`, params, }; case "LIKE": return { str: `${fieldName} LIKE ${wrappedValue}`, params: wrappedParams, }; case "LIKE_RAW": return { str: `${fieldName} LIKE ${finalValue}`, params }; case "NOT_LIKE_LOWER": return { str: `LOWER(${fieldName}) NOT LIKE LOWER(${wrappedValue})`, params: wrappedParams, }; case "NOT_LIKE_LOWER_RAW": return { str: `LOWER(${fieldName}) NOT LIKE LOWER(${finalValue})`, params, }; case "NOT LIKE": return { str: `${fieldName} NOT LIKE ${wrappedValue}`, params: wrappedParams, }; case "NOT LIKE_RAW": return { str: `${fieldName} NOT LIKE ${finalValue}`, params }; case "REGEXP": /** * SQLite has no built-in REGEXP function. This only works when * an extension providing `regexp()` is loaded. */ return { str: `LOWER(${fieldName}) REGEXP LOWER(${finalValue})`, params, }; case "NOT EQUAL": return { str: `${fieldName} != ${finalValue}`, params }; case "IS NOT": return { str: `${fieldName} IS NOT ${finalValue}`, params }; case "IN": case "NOT IN": return { str: `${fieldName} ${equality} (${finalValue})`, params }; case "BETWEEN": case "NOT BETWEEN": throw new Error(`\`${equality}\` on \`${fieldName}\` requires an array of two values`); case undefined: return { str: `${fieldName} = ${finalValue}`, params }; default: return { str: `${fieldName} ${sqlEqualityParser(equality)} ${finalValue}`, params, }; } }