diff --git a/dist/types/index.d.ts b/dist/types/index.d.ts index 4ed6d84..08285be 100644 --- a/dist/types/index.d.ts +++ b/dist/types/index.d.ts @@ -711,6 +711,17 @@ export type TableSelectFieldsObject = { fieldName: keyof T; alias?: string; + count?: { + alias?: string; + }; + sum?: TableSelectFieldsBasicDirective; + max?: TableSelectFieldsBasicDirective; + min?: TableSelectFieldsBasicDirective; + average?: TableSelectFieldsBasicDirective; + group_concat?: Omit; +}; +export type TableSelectFieldsBasicDirective = { + alias: string; }; /** * Value wrapper used when a query condition needs per-value metadata such as a @@ -793,11 +804,7 @@ export type ServerQueryParamsJoin | ServerQueryParamsJoinMatchObject[]; - selectFields?: (keyof Field | { - field: keyof Field; - alias?: string; - count?: boolean; - })[]; + selectFields?: (keyof Field | SelectFieldObject)[]; omitFields?: (keyof Field | { field: keyof Field; alias?: string; @@ -810,14 +817,22 @@ export type ServerQueryParamsJoin
= { + field: keyof Field; + alias?: string; + count?: boolean; }; /** * Defines how a root-table field maps to a join-table field in an `ON` clause. diff --git a/dist/utils/sql-gen-operator-gen.d.ts b/dist/utils/sql-gen-operator-gen.d.ts index d8535ef..d6adb66 100644 --- a/dist/utils/sql-gen-operator-gen.d.ts +++ b/dist/utils/sql-gen-operator-gen.d.ts @@ -1,7 +1,7 @@ -import type { ServerQueryEqualities, ServerQueryObject } from "../types"; +import type { ServerQueryEqualities, ServerQueryObject, SQLInsertGenValueType } from "../types"; type Params = { fieldName: string; - value?: string; + value?: SQLInsertGenValueType; equality?: (typeof ServerQueryEqualities)[number]; queryObj: ServerQueryObject<{ [key: string]: any; @@ -10,7 +10,7 @@ type Params = { }; type Return = { str?: string; - param?: string; + param?: SQLInsertGenValueType; }; /** * # SQL Gen Operator Gen diff --git a/dist/utils/sql-generator-gen-join-str.d.ts b/dist/utils/sql-generator-gen-join-str.d.ts new file mode 100644 index 0000000..869b9f6 --- /dev/null +++ b/dist/utils/sql-generator-gen-join-str.d.ts @@ -0,0 +1,8 @@ +import type { ServerQueryParamsJoin, ServerQueryParamsJoinMatchObject } from "../types"; +type Param = { + mtch: ServerQueryParamsJoinMatchObject; + join: ServerQueryParamsJoin; + table_name: string; +}; +export default function sqlGenGenJoinStr({ join, mtch, table_name }: Param): string; +export {}; diff --git a/dist/utils/sql-generator-gen-join-str.js b/dist/utils/sql-generator-gen-join-str.js new file mode 100644 index 0000000..8b754e4 --- /dev/null +++ b/dist/utils/sql-generator-gen-join-str.js @@ -0,0 +1,33 @@ +export default function sqlGenGenJoinStr({ join, mtch, table_name }) { + if (mtch.__batch) { + let btch_mtch = ``; + btch_mtch += `(`; + for (let i = 0; i < mtch.__batch.matches.length; i++) { + const __mtch = mtch.__batch.matches[i]; + btch_mtch += `${sqlGenGenJoinStr({ join, mtch: __mtch, table_name })}`; + if (i < mtch.__batch.matches.length - 1) { + btch_mtch += ` ${mtch.__batch.operator || "OR"} `; + } + } + btch_mtch += `)`; + return btch_mtch; + } + return `${typeof mtch.source == "object" ? mtch.source.tableName : table_name}.${typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source}=${(() => { + if (mtch.targetLiteral) { + if (typeof mtch.targetLiteral == "number") { + return `${mtch.targetLiteral}`; + } + return `'${mtch.targetLiteral}'`; + } + if (join.alias) { + return `${typeof mtch.target == "object" + ? mtch.target.tableName + : join.alias}.${typeof mtch.target == "object" + ? mtch.target.fieldName + : mtch.target}`; + } + return `${typeof mtch.target == "object" + ? mtch.target.tableName + : join.tableName}.${typeof mtch.target == "object" ? mtch.target.fieldName : mtch.target}`; + })()}`; +} diff --git a/dist/utils/sql-generator-gen-query-str.d.ts b/dist/utils/sql-generator-gen-query-str.d.ts new file mode 100644 index 0000000..886d00a --- /dev/null +++ b/dist/utils/sql-generator-gen-query-str.d.ts @@ -0,0 +1,22 @@ +import type { ServerQueryParam, TableSelectFieldsObject } from "../types"; +type Param = { + genObject?: ServerQueryParam; + selectFields?: (keyof T | TableSelectFieldsObject)[]; + append_table_names?: boolean; + table_name: string; + full_text_match_str?: string; + full_text_search_str?: string; +}; +export default function sqlGenGenQueryStr(params: Param): { + str: string; + values: any[]; +}; +export {}; diff --git a/dist/utils/sql-generator-gen-query-str.js b/dist/utils/sql-generator-gen-query-str.js new file mode 100644 index 0000000..5acfc78 --- /dev/null +++ b/dist/utils/sql-generator-gen-query-str.js @@ -0,0 +1,160 @@ +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"; +export default function sqlGenGenQueryStr(params) { + let str = "SELECT"; + const genObject = params.genObject; + const table_name = params.table_name; + const full_text_match_str = params.full_text_match_str; + const full_text_search_str = params.full_text_search_str; + let sqlSearhValues = []; + if (genObject?.select_sql) { + str += ` ${genObject.select_sql}`; + } + else if (genObject?.selectFields?.[0]) { + if (genObject.join) { + str += sqlGenGrabSelectFieldSQL({ + selectFields: genObject.selectFields, + append_table_names: true, + table_name, + }); + } + else { + str += sqlGenGrabSelectFieldSQL({ + selectFields: genObject.selectFields, + table_name, + }); + } + } + else { + if (genObject?.join) { + str += ` ${table_name}.*`; + } + else { + str += " *"; + } + } + if (genObject?.countSubQueries) { + let countSqls = []; + for (let i = 0; i < genObject.countSubQueries.length; i++) { + const countSubQuery = genObject.countSubQueries[i]; + if (!countSubQuery) + continue; + const tableAlias = countSubQuery.table_alias; + let subQStr = `(SELECT COUNT(*)`; + subQStr += ` FROM ${countSubQuery.table}${tableAlias ? ` ${tableAlias}` : ""}`; + subQStr += ` WHERE (`; + for (let j = 0; j < countSubQuery.srcTrgMap.length; j++) { + const csqSrc = countSubQuery.srcTrgMap[j]; + if (!csqSrc) + continue; + subQStr += ` ${tableAlias || countSubQuery.table}.${csqSrc.src}`; + if (typeof csqSrc.trg == "string") { + subQStr += ` = ?`; + sqlSearhValues.push(csqSrc.trg); + } + else if (typeof csqSrc.trg == "object") { + subQStr += ` = ${csqSrc.trg.table}.${csqSrc.trg.field}`; + } + if (j < countSubQuery.srcTrgMap.length - 1) { + subQStr += ` AND `; + } + } + subQStr += ` )) AS ${countSubQuery.alias}`; + countSqls.push(subQStr); + } + str += `, ${countSqls.join(",")}`; + } + if (genObject?.join) { + const existingJoinTableNames = [table_name]; + str += + "," + + genObject.join + .flat() + .filter((j) => !isUndefined(j)) + .map((joinObj) => { + const joinTableName = joinObj.alias + ? joinObj.alias + : joinObj.tableName; + if (existingJoinTableNames.includes(joinTableName)) + return null; + existingJoinTableNames.push(joinTableName); + if (joinObj.group_concat) { + return sqlGenGrabConcatStr({ + field: `${joinTableName}.${joinObj.group_concat.field}`, + alias: joinObj.group_concat.alias, + separator: joinObj.group_concat.separator, + }); + } + else if (joinObj.selectFields) { + return joinObj.selectFields + .map((selectField) => { + if (typeof selectField == "string") { + return `${joinTableName}.${selectField}`; + } + else if (typeof selectField == "object") { + let aliasSelectField = selectField.count + ? `COUNT(${joinTableName}.${selectField.field})` + : `${joinTableName}.${selectField.field}`; + if (selectField.alias) + aliasSelectField += ` AS ${selectField.alias}`; + return aliasSelectField; + } + }) + .join(","); + } + else { + return `${joinTableName}.*`; + } + }) + .filter((_) => Boolean(_)) + .join(","); + } + if (genObject?.fullTextSearch && + full_text_match_str && + full_text_search_str) { + str += `, ${full_text_match_str} AS ${genObject.fullTextSearch.scoreAlias}`; + sqlSearhValues.push(full_text_search_str); + } + str += ` FROM ${table_name}`; + if (genObject?.join) { + str += + " " + + genObject.join + .flat() + .filter((j) => !isUndefined(j)) + .map((join) => { + return (join.joinType + + " " + + (join.alias + ? `${join.tableName}` + " " + join.alias + : `${join.tableName}`) + + " ON " + + (() => { + if (Array.isArray(join.match)) { + return ("(" + + join.match + .map((mtch) => sqlGenGenJoinStr({ + mtch, + join, + table_name, + })) + .join(join.operator + ? ` ${join.operator} ` + : " AND ") + + ")"); + } + else if (typeof join.match == "object") { + return sqlGenGenJoinStr({ + mtch: join.match, + join, + table_name, + }); + } + })()); + }) + .join(" "); + } + return { str, values: sqlSearhValues }; +} diff --git a/dist/utils/sql-generator-gen-search-str.d.ts b/dist/utils/sql-generator-gen-search-str.d.ts new file mode 100644 index 0000000..307085e --- /dev/null +++ b/dist/utils/sql-generator-gen-search-str.d.ts @@ -0,0 +1,12 @@ +import type { ServerQueryParamsJoin, ServerQueryQueryObject } from "../types"; +type Param = { + queryObj: ServerQueryQueryObject[string]; + join?: (ServerQueryParamsJoin | ServerQueryParamsJoin[] | undefined)[]; + field?: string; + table_name: string; +}; +export default function sqlGenGenSearchStr({ queryObj, join, field, table_name, }: Param): { + str: string; + values: (string | number | Float32Array | Buffer)[]; +}; +export {}; diff --git a/dist/utils/sql-generator-gen-search-str.js b/dist/utils/sql-generator-gen-search-str.js new file mode 100644 index 0000000..0ff0e6c --- /dev/null +++ b/dist/utils/sql-generator-gen-search-str.js @@ -0,0 +1,81 @@ +import sqlGenOperatorGen from "./sql-gen-operator-gen"; +export default function sqlGenGenSearchStr({ queryObj, join, field, table_name, }) { + let sqlSearhValues = []; + const finalFieldName = (() => { + if (queryObj?.tableName) { + return `${queryObj.tableName}.${field}`; + } + if (join) { + return `${table_name}.${field}`; + } + return field; + })(); + let str = `${finalFieldName}=?`; + function grabValue(val) { + const valueParsed = val; + if (!valueParsed) + return; + const valueString = typeof valueParsed == "string" || typeof valueParsed == "number" + ? valueParsed + : valueParsed + ? valueParsed.fieldName && valueParsed.tableName + ? `${valueParsed.tableName}.${valueParsed.fieldName}` + : valueParsed.value + : undefined; + const valueEquality = typeof valueParsed == "object" + ? valueParsed.equality || queryObj.equality + : queryObj.equality; + const operatorStrParam = sqlGenOperatorGen({ + queryObj, + equality: valueEquality, + fieldName: finalFieldName || "", + value: valueString || "", + isValueFieldValue: Boolean(typeof valueParsed == "object" && + valueParsed.fieldName && + valueParsed.tableName), + }); + return operatorStrParam; + } + if (Array.isArray(queryObj.value)) { + const strArray = []; + queryObj.value.forEach((val) => { + const operatorStrParam = grabValue(val); + if (!operatorStrParam) + return; + if (operatorStrParam.str && operatorStrParam.param) { + strArray.push(operatorStrParam.str); + sqlSearhValues.push(operatorStrParam.param); + } + else if (operatorStrParam.str) { + strArray.push(operatorStrParam.str); + } + }); + str = "(" + strArray.join(` ${queryObj.operator || "AND"} `) + ")"; + } + else if (typeof queryObj.value == "object") { + const operatorStrParam = grabValue(queryObj.value); + if (operatorStrParam?.str) { + str = operatorStrParam.str; + if (operatorStrParam.param) { + sqlSearhValues.push(operatorStrParam.param); + } + } + } + else { + const valueParsed = queryObj.value ? queryObj.value : undefined; + const operatorStrParam = sqlGenOperatorGen({ + equality: queryObj.equality, + fieldName: finalFieldName || "", + value: valueParsed, + queryObj, + }); + if (operatorStrParam.str && operatorStrParam.param) { + str = operatorStrParam.str; + sqlSearhValues.push(operatorStrParam.param); + } + else if (operatorStrParam.str) { + str = operatorStrParam.str; + } + } + return { str, values: sqlSearhValues }; +} diff --git a/dist/utils/sql-generator-grab-concat-str.d.ts b/dist/utils/sql-generator-grab-concat-str.d.ts new file mode 100644 index 0000000..9955643 --- /dev/null +++ b/dist/utils/sql-generator-grab-concat-str.d.ts @@ -0,0 +1,7 @@ +type Param = { + field: string; + alias: string; + separator?: string; +}; +export default function sqlGenGrabConcatStr({ alias, field, separator, }: Param): string; +export {}; diff --git a/dist/utils/sql-generator-grab-concat-str.js b/dist/utils/sql-generator-grab-concat-str.js new file mode 100644 index 0000000..099b0a1 --- /dev/null +++ b/dist/utils/sql-generator-grab-concat-str.js @@ -0,0 +1,4 @@ +export default function sqlGenGrabConcatStr({ alias, field, separator = ",", }) { + let gc = `GROUP_CONCAT(${field}, '${separator}') AS ${alias}`; + return gc; +} diff --git a/dist/utils/sql-generator-grab-select-field-sql.d.ts b/dist/utils/sql-generator-grab-select-field-sql.d.ts new file mode 100644 index 0000000..83d13cc --- /dev/null +++ b/dist/utils/sql-generator-grab-select-field-sql.d.ts @@ -0,0 +1,16 @@ +import type { TableSelectFieldsObject } from "../types"; +type Param = { + selectFields: (keyof T | TableSelectFieldsObject)[]; + append_table_names?: boolean; + table_name: string; +}; +export default function sqlGenGrabSelectFieldSQL({ selectFields, append_table_names, table_name }: Param): string; +export {}; diff --git a/dist/utils/sql-generator-grab-select-field-sql.js b/dist/utils/sql-generator-grab-select-field-sql.js new file mode 100644 index 0000000..6772388 --- /dev/null +++ b/dist/utils/sql-generator-grab-select-field-sql.js @@ -0,0 +1,42 @@ +import sqlGenGrabConcatStr from "./sql-generator-grab-concat-str"; +export default function sqlGenGrabSelectFieldSQL({ selectFields, append_table_names, table_name }) { + let str = ""; + str += ` ${selectFields + ?.map((fld) => { + let fld_str = ``; + const final_fld_name = typeof fld == "object" + ? append_table_names + ? `${table_name}.${String(fld)}` + : `${String(fld.fieldName)}` + : `${String(fld)}`; + if (typeof fld == "object") { + const fld_name = `${String(fld.fieldName)}`; + if (fld.count) { + fld_str += `COUNT(${fld_name})`; + if (fld.count.alias) { + fld_str += ` AS ${fld.count.alias}`; + } + } + else if (fld.sum) { + fld_str += `SUM(${fld_name}) AS ${fld.sum.alias}`; + } + else if (fld.group_concat) { + fld_str += sqlGenGrabConcatStr({ + field: fld_name, + alias: fld.group_concat.alias, + separator: fld.group_concat.separator, + }); + } + else { + fld_str += + final_fld_name + (fld.alias ? ` as ${fld.alias}` : ``); + } + } + else { + fld_str += final_fld_name; + } + return fld_str; + }) + .join(",")}`; + return str; +} diff --git a/dist/utils/sql-generator.d.ts b/dist/utils/sql-generator.d.ts index 30f714a..b6eea8f 100644 --- a/dist/utils/sql-generator.d.ts +++ b/dist/utils/sql-generator.d.ts @@ -1,4 +1,4 @@ -import type { ServerQueryParam } from "../types"; +import type { ServerQueryParam, SQLInsertGenValueType } from "../types"; type Param { - if (queryObj?.tableName) { - return `${finalDbName}${queryObj.tableName}.${field}`; - } - if (join) { - return `${finalDbName}${tableName}.${field}`; - } - return field; - })(); - let str = `${finalFieldName}=?`; - function grabValue(val) { - const valueParsed = val; - if (!valueParsed) - return; - const valueString = typeof valueParsed == "string" || typeof valueParsed == "number" - ? valueParsed - : valueParsed - ? valueParsed.fieldName && valueParsed.tableName - ? `${valueParsed.tableName}.${valueParsed.fieldName}` - : valueParsed.value?.toString() - : undefined; - const valueEquality = typeof valueParsed == "object" - ? valueParsed.equality || queryObj.equality - : queryObj.equality; - const operatorStrParam = sqlGenOperatorGen({ - queryObj, - equality: valueEquality, - fieldName: finalFieldName || "", - value: valueString?.toString() || "", - isValueFieldValue: Boolean(typeof valueParsed == "object" && - valueParsed.fieldName && - valueParsed.tableName), - }); - return operatorStrParam; - } - if (Array.isArray(queryObj.value)) { - const strArray = []; - queryObj.value.forEach((val) => { - const operatorStrParam = grabValue(val); - if (!operatorStrParam) - return; - if (operatorStrParam.str && operatorStrParam.param) { - strArray.push(operatorStrParam.str); - sqlSearhValues.push(operatorStrParam.param); - } - else if (operatorStrParam.str) { - strArray.push(operatorStrParam.str); - } - }); - str = "(" + strArray.join(` ${queryObj.operator || "AND"} `) + ")"; - } - else if (typeof queryObj.value == "object") { - const operatorStrParam = grabValue(queryObj.value); - if (operatorStrParam?.str) { - str = operatorStrParam.str; - if (operatorStrParam.param) { - sqlSearhValues.push(operatorStrParam.param); - } - } - } - else { - const valueParsed = queryObj.value - ? String(queryObj.value) - : undefined; - const operatorStrParam = sqlGenOperatorGen({ - equality: queryObj.equality, - fieldName: finalFieldName || "", - value: valueParsed, - queryObj, - }); - if (operatorStrParam.str && operatorStrParam.param) { - str = operatorStrParam.str; - sqlSearhValues.push(operatorStrParam.param); - } - else if (operatorStrParam.str) { - str = operatorStrParam.str; - } - } - return str; - } - function generateJoinStr(mtch, join) { - if (mtch.__batch) { - let btch_mtch = ``; - btch_mtch += `(`; - for (let i = 0; i < mtch.__batch.matches.length; i++) { - const __mtch = mtch.__batch.matches[i]; - btch_mtch += `${generateJoinStr(__mtch, join)}`; - if (i < mtch.__batch.matches.length - 1) { - btch_mtch += ` ${mtch.__batch.operator || "OR"} `; - } - } - btch_mtch += `)`; - return btch_mtch; - } - return `${finalDbName}${typeof mtch.source == "object" ? mtch.source.tableName : tableName}.${typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source}=${(() => { - if (mtch.targetLiteral) { - if (typeof mtch.targetLiteral == "number") { - return `${mtch.targetLiteral}`; - } - return `'${mtch.targetLiteral}'`; - } - if (join.alias) { - return `${finalDbName}${typeof mtch.target == "object" - ? mtch.target.tableName - : join.alias}.${typeof mtch.target == "object" - ? mtch.target.fieldName - : mtch.target}`; - } - return `${finalDbName}${typeof mtch.target == "object" - ? mtch.target.tableName - : join.tableName}.${typeof mtch.target == "object" - ? mtch.target.fieldName - : mtch.target}`; - })()}`; - } let fullTextMatchStr = genObject?.fullTextSearch ? ` MATCH(${genObject.fullTextSearch.fields .map((f) => genObject.join ? `${tableName}.${String(f)}` : `${String(f)}`) @@ -139,151 +19,14 @@ export default function sqlGenerator({ tableName, genObject, dbFullName, count } .map((t) => `${t}`) .join(" ") : undefined; - let queryString = (() => { - let str = "SELECT"; - if (genObject?.select_sql) { - str += ` ${genObject.select_sql}`; - } - else if (genObject?.selectFields?.[0]) { - if (genObject.join) { - str += ` ${genObject.selectFields - ?.map((fld) => typeof fld == "object" - ? `${finalDbName}${tableName}.${fld.fieldName.toString()}` + - (fld.alias ? ` as ${fld.alias}` : ``) - : `${finalDbName}${tableName}.${String(fld)}`) - .join(",")}`; - } - else { - str += ` ${genObject.selectFields - ?.map((fld) => typeof fld == "object" - ? `${fld.fieldName.toString()}` + - (fld.alias ? ` as ${fld.alias}` : ``) - : fld) - .join(",")}`; - } - } - else { - if (genObject?.join) { - str += ` ${finalDbName}${tableName}.*`; - } - else { - str += " *"; - } - } - if (genObject?.countSubQueries) { - let countSqls = []; - for (let i = 0; i < genObject.countSubQueries.length; i++) { - const countSubQuery = genObject.countSubQueries[i]; - if (!countSubQuery) - continue; - const tableAlias = countSubQuery.table_alias; - let subQStr = `(SELECT COUNT(*)`; - subQStr += ` FROM ${countSubQuery.table}${tableAlias ? ` ${tableAlias}` : ""}`; - subQStr += ` WHERE (`; - for (let j = 0; j < countSubQuery.srcTrgMap.length; j++) { - const csqSrc = countSubQuery.srcTrgMap[j]; - if (!csqSrc) - continue; - subQStr += ` ${tableAlias || countSubQuery.table}.${csqSrc.src}`; - if (typeof csqSrc.trg == "string") { - subQStr += ` = ?`; - sqlSearhValues.push(csqSrc.trg); - } - else if (typeof csqSrc.trg == "object") { - subQStr += ` = ${csqSrc.trg.table}.${csqSrc.trg.field}`; - } - if (j < countSubQuery.srcTrgMap.length - 1) { - subQStr += ` AND `; - } - } - subQStr += ` )) AS ${countSubQuery.alias}`; - countSqls.push(subQStr); - } - str += `, ${countSqls.join(",")}`; - } - if (genObject?.join) { - const existingJoinTableNames = [tableName]; - str += - "," + - genObject.join - .flat() - .filter((j) => !isUndefined(j)) - .map((joinObj) => { - const joinTableName = joinObj.alias - ? joinObj.alias - : joinObj.tableName; - if (existingJoinTableNames.includes(joinTableName)) - return null; - existingJoinTableNames.push(joinTableName); - if (joinObj.group_concat) { - let group_concat = `GROUP_CONCAT(${joinTableName}.${joinObj.group_concat.field}, '${joinObj.group_concat.separator || ","}') AS ${joinObj.group_concat.alias}`; - return group_concat; - } - else if (joinObj.selectFields) { - return joinObj.selectFields - .map((selectField) => { - if (typeof selectField == "string") { - return `${finalDbName}${joinTableName}.${selectField}`; - } - else if (typeof selectField == "object") { - let aliasSelectField = selectField.count - ? `COUNT(${finalDbName}${joinTableName}.${selectField.field})` - : `${finalDbName}${joinTableName}.${selectField.field}`; - if (selectField.alias) - aliasSelectField += ` AS ${selectField.alias}`; - return aliasSelectField; - } - }) - .join(","); - } - else { - return `${finalDbName}${joinTableName}.*`; - } - }) - .filter((_) => Boolean(_)) - .join(","); - } - if (genObject?.fullTextSearch && - fullTextMatchStr && - fullTextSearchStr) { - str += `, ${fullTextMatchStr} AS ${genObject.fullTextSearch.scoreAlias}`; - sqlSearhValues.push(fullTextSearchStr); - } - str += ` FROM ${finalDbName}${tableName}`; - if (genObject?.join) { - str += - " " + - genObject.join - .flat() - .filter((j) => !isUndefined(j)) - .map((join) => { - return (join.joinType + - " " + - (join.alias - ? `${finalDbName}${join.tableName}` + - " " + - join.alias - : `${finalDbName}${join.tableName}`) + - " ON " + - (() => { - if (Array.isArray(join.match)) { - return ("(" + - join.match - .map((mtch) => generateJoinStr(mtch, join)) - .join(join.operator - ? ` ${join.operator} ` - : " AND ") + - ")"); - } - else if (typeof join.match == "object") { - return generateJoinStr(join.match, join); - } - })()); - }) - .join(" "); - } - return str; - })(); + let { str: queryString, values } = sqlGenGenQueryStr({ + table_name: tableName, + append_table_names: true, + full_text_match_str: fullTextMatchStr, + full_text_search_str: fullTextSearchStr, + genObject, + }); + sqlSearhValues.push(...values); const sqlSearhString = queryKeys?.map((field) => { const queryObj = finalQuery?.[field]; if (!queryObj) @@ -294,22 +37,28 @@ export default function sqlGenerator({ tableName, genObject, dbFullName, count } const subSearchString = subSearchKeys.map((_field) => { const newSubQueryObj = subQueryGroup?.[_field]; if (newSubQueryObj) { - return genSqlSrchStr({ + const { str, values } = sqlGenGenSearchStr({ queryObj: newSubQueryObj, field: newSubQueryObj.fieldName || _field, join: genObject?.join, + table_name: tableName, }); + sqlSearhValues.push(...values); + return str; } }); return ("(" + subSearchString.join(` ${queryObj.operator || "AND"} `) + ")"); } - return genSqlSrchStr({ + const { str, values } = sqlGenGenSearchStr({ queryObj, field: queryObj.fieldName || field, join: genObject?.join, + table_name: tableName, }); + sqlSearhValues.push(...values); + return str; }); const cleanedUpSearchStr = sqlSearhString?.filter((str) => typeof str == "string"); const isSearchStr = cleanedUpSearchStr?.[0] && cleanedUpSearchStr.find((str) => str); @@ -360,7 +109,7 @@ export default function sqlGenerator({ tableName, genObject, dbFullName, count } orderFields.push(genObject.fullTextSearch.scoreAlias); } else if (genObject?.join) { - orderFields.push(`${finalDbName}${tableName}.${String(order.field)}`); + orderFields.push(`${tableName}.${String(order.field)}`); } else { orderFields.push(order.field); @@ -398,3 +147,157 @@ export default function sqlGenerator({ tableName, genObject, dbFullName, count } values: sqlSearhValues, }; } +// let queryString = (() => { +// let str = "SELECT"; +// if (genObject?.select_sql) { +// str += ` ${genObject.select_sql}`; +// } else if (genObject?.selectFields?.[0]) { +// if (genObject.join) { +// str += sqlGenGrabSelectFieldSQL({ +// selectFields: genObject.selectFields, +// append_table_names: true, +// table_name: tableName, +// }); +// } else { +// str += sqlGenGrabSelectFieldSQL({ +// selectFields: genObject.selectFields, +// table_name: tableName, +// }); +// } +// } else { +// if (genObject?.join) { +// str += ` ${tableName}.*`; +// } else { +// str += " *"; +// } +// } +// if (genObject?.countSubQueries) { +// let countSqls: string[] = []; +// for (let i = 0; i < genObject.countSubQueries.length; i++) { +// const countSubQuery = genObject.countSubQueries[i]; +// if (!countSubQuery) continue; +// const tableAlias = countSubQuery.table_alias; +// let subQStr = `(SELECT COUNT(*)`; +// subQStr += ` FROM ${countSubQuery.table}${ +// tableAlias ? ` ${tableAlias}` : "" +// }`; +// subQStr += ` WHERE (`; +// for (let j = 0; j < countSubQuery.srcTrgMap.length; j++) { +// const csqSrc = countSubQuery.srcTrgMap[j]; +// if (!csqSrc) continue; +// subQStr += ` ${tableAlias || countSubQuery.table}.${ +// csqSrc.src +// }`; +// if (typeof csqSrc.trg == "string") { +// subQStr += ` = ?`; +// sqlSearhValues.push(csqSrc.trg); +// } else if (typeof csqSrc.trg == "object") { +// subQStr += ` = ${csqSrc.trg.table}.${csqSrc.trg.field}`; +// } +// if (j < countSubQuery.srcTrgMap.length - 1) { +// subQStr += ` AND `; +// } +// } +// subQStr += ` )) AS ${countSubQuery.alias}`; +// countSqls.push(subQStr); +// } +// str += `, ${countSqls.join(",")}`; +// } +// if (genObject?.join) { +// const existingJoinTableNames: string[] = [tableName]; +// str += +// "," + +// genObject.join +// .flat() +// .filter((j) => !isUndefined(j)) +// .map((joinObj) => { +// const joinTableName = joinObj.alias +// ? joinObj.alias +// : joinObj.tableName; +// if (existingJoinTableNames.includes(joinTableName)) +// return null; +// existingJoinTableNames.push(joinTableName); +// if (joinObj.group_concat) { +// return sqlGenGrabConcatStr({ +// field: `${joinTableName}.${joinObj.group_concat.field}`, +// alias: joinObj.group_concat.alias, +// separator: joinObj.group_concat.separator, +// }); +// } else if (joinObj.selectFields) { +// return joinObj.selectFields +// .map((selectField) => { +// if (typeof selectField == "string") { +// return `${joinTableName}.${selectField}`; +// } else if (typeof selectField == "object") { +// let aliasSelectField = selectField.count +// ? `COUNT(${joinTableName}.${selectField.field})` +// : `${joinTableName}.${selectField.field}`; +// if (selectField.alias) +// aliasSelectField += ` AS ${selectField.alias}`; +// return aliasSelectField; +// } +// }) +// .join(","); +// } else { +// return `${joinTableName}.*`; +// } +// }) +// .filter((_) => Boolean(_)) +// .join(","); +// } +// if ( +// genObject?.fullTextSearch && +// fullTextMatchStr && +// fullTextSearchStr +// ) { +// str += `, ${fullTextMatchStr} AS ${genObject.fullTextSearch.scoreAlias}`; +// sqlSearhValues.push(fullTextSearchStr); +// } +// str += ` FROM ${tableName}`; +// if (genObject?.join) { +// str += +// " " + +// genObject.join +// .flat() +// .filter((j) => !isUndefined(j)) +// .map((join) => { +// return ( +// join.joinType + +// " " + +// (join.alias +// ? `${join.tableName}` + " " + join.alias +// : `${join.tableName}`) + +// " ON " + +// (() => { +// if (Array.isArray(join.match)) { +// return ( +// "(" + +// join.match +// .map((mtch) => +// sqlGenGenJoinStr({ +// mtch, +// join, +// table_name: tableName, +// }), +// ) +// .join( +// join.operator +// ? ` ${join.operator} ` +// : " AND ", +// ) + +// ")" +// ); +// } else if (typeof join.match == "object") { +// return sqlGenGenJoinStr({ +// mtch: join.match, +// join, +// table_name: tableName, +// }); +// } +// })() +// ); +// }) +// .join(" "); +// } +// return str; +// })(); diff --git a/package.json b/package.json index ef41719..137c8fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@moduletrace/bun-sqlite", - "version": "1.0.43", + "version": "1.1.0", "description": "SQLite manager for Bun", "author": "Benjamin Toby", "main": "dist/index.js", diff --git a/src/types/index.ts b/src/types/index.ts index e1277fa..2e30a8a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -782,6 +782,18 @@ export type TableSelectFieldsObject< > = { fieldName: keyof T; alias?: string; + count?: { + alias?: string; + }; + sum?: TableSelectFieldsBasicDirective; + max?: TableSelectFieldsBasicDirective; + min?: TableSelectFieldsBasicDirective; + average?: TableSelectFieldsBasicDirective; + group_concat?: Omit; +}; + +export type TableSelectFieldsBasicDirective = { + alias: string; }; /** @@ -882,14 +894,7 @@ export type ServerQueryParamsJoin< match?: | ServerQueryParamsJoinMatchObject | ServerQueryParamsJoinMatchObject[]; - selectFields?: ( - | keyof Field - | { - field: keyof Field; - alias?: string; - count?: boolean; - } - )[]; + selectFields?: (keyof Field | SelectFieldObject)[]; omitFields?: ( | keyof Field | { @@ -906,14 +911,22 @@ export type ServerQueryParamsJoin< /** * Concatenate multiple matches from another table */ - group_concat?: { - field: string; - alias: string; - /** - * Separator. Default `,` - */ - separator?: string; - }; + group_concat?: GroupConcatObject; +}; + +export type GroupConcatObject = { + field: string; + alias: string; + /** + * Separator. Default `,` + */ + separator?: string; +}; + +export type SelectFieldObject = { + field: keyof Field; + alias?: string; + count?: boolean; }; /** diff --git a/src/utils/sql-gen-operator-gen.ts b/src/utils/sql-gen-operator-gen.ts index b064c4a..3ffd445 100644 --- a/src/utils/sql-gen-operator-gen.ts +++ b/src/utils/sql-gen-operator-gen.ts @@ -1,9 +1,13 @@ -import type { ServerQueryEqualities, ServerQueryObject } from "../types"; +import type { + ServerQueryEqualities, + ServerQueryObject, + SQLInsertGenValueType, +} from "../types"; import sqlEqualityParser from "./sql-equality-parser"; type Params = { fieldName: string; - value?: string; + value?: SQLInsertGenValueType; equality?: (typeof ServerQueryEqualities)[number]; queryObj: ServerQueryObject< { @@ -16,7 +20,7 @@ type Params = { type Return = { str?: string; - param?: string; + param?: SQLInsertGenValueType; }; /** diff --git a/src/utils/sql-generator-gen-join-str.ts b/src/utils/sql-generator-gen-join-str.ts new file mode 100644 index 0000000..f7c513e --- /dev/null +++ b/src/utils/sql-generator-gen-join-str.ts @@ -0,0 +1,64 @@ +import type { + ServerQueryParamsJoin, + ServerQueryParamsJoinMatchObject, +} from "../types"; + +type Param = { + mtch: ServerQueryParamsJoinMatchObject; + join: ServerQueryParamsJoin; + table_name: string; +}; + +export default function sqlGenGenJoinStr({ join, mtch, table_name }: Param) { + if (mtch.__batch) { + let btch_mtch = ``; + btch_mtch += `(`; + + for (let i = 0; i < mtch.__batch.matches.length; i++) { + const __mtch = mtch.__batch.matches[ + i + ] as ServerQueryParamsJoinMatchObject; + btch_mtch += `${sqlGenGenJoinStr({ join, mtch: __mtch, table_name })}`; + if (i < mtch.__batch.matches.length - 1) { + btch_mtch += ` ${mtch.__batch.operator || "OR"} `; + } + } + + btch_mtch += `)`; + + return btch_mtch; + } + + return `${ + typeof mtch.source == "object" ? mtch.source.tableName : table_name + }.${ + typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source + }=${(() => { + if (mtch.targetLiteral) { + if (typeof mtch.targetLiteral == "number") { + return `${mtch.targetLiteral}`; + } + return `'${mtch.targetLiteral}'`; + } + + if (join.alias) { + return `${ + typeof mtch.target == "object" + ? mtch.target.tableName + : join.alias + }.${ + typeof mtch.target == "object" + ? mtch.target.fieldName + : mtch.target + }`; + } + + return `${ + typeof mtch.target == "object" + ? mtch.target.tableName + : join.tableName + }.${ + typeof mtch.target == "object" ? mtch.target.fieldName : mtch.target + }`; + })()}`; +} diff --git a/src/utils/sql-generator-gen-query-str.ts b/src/utils/sql-generator-gen-query-str.ts new file mode 100644 index 0000000..cfd3c01 --- /dev/null +++ b/src/utils/sql-generator-gen-query-str.ts @@ -0,0 +1,199 @@ +import { isUndefined } from "lodash"; +import type { ServerQueryParam, TableSelectFieldsObject } from "../types"; +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"; + +type Param = { + genObject?: ServerQueryParam; + selectFields?: (keyof T | TableSelectFieldsObject)[]; + append_table_names?: boolean; + table_name: string; + full_text_match_str?: string; + full_text_search_str?: string; +}; + +export default function sqlGenGenQueryStr< + T extends { [key: string]: any } = { [key: string]: any }, +>(params: Param) { + let str = "SELECT"; + + const genObject = params.genObject; + const table_name = params.table_name; + const full_text_match_str = params.full_text_match_str; + const full_text_search_str = params.full_text_search_str; + + let sqlSearhValues: any[] = []; + + if (genObject?.select_sql) { + str += ` ${genObject.select_sql}`; + } else if (genObject?.selectFields?.[0]) { + if (genObject.join) { + str += sqlGenGrabSelectFieldSQL({ + selectFields: genObject.selectFields, + append_table_names: true, + table_name, + }); + } else { + str += sqlGenGrabSelectFieldSQL({ + selectFields: genObject.selectFields, + table_name, + }); + } + } else { + if (genObject?.join) { + str += ` ${table_name}.*`; + } else { + str += " *"; + } + } + + if (genObject?.countSubQueries) { + let countSqls: string[] = []; + + for (let i = 0; i < genObject.countSubQueries.length; i++) { + const countSubQuery = genObject.countSubQueries[i]; + if (!countSubQuery) continue; + + const tableAlias = countSubQuery.table_alias; + + let subQStr = `(SELECT COUNT(*)`; + + subQStr += ` FROM ${countSubQuery.table}${ + tableAlias ? ` ${tableAlias}` : "" + }`; + + subQStr += ` WHERE (`; + + for (let j = 0; j < countSubQuery.srcTrgMap.length; j++) { + const csqSrc = countSubQuery.srcTrgMap[j]; + if (!csqSrc) continue; + + subQStr += ` ${tableAlias || countSubQuery.table}.${ + csqSrc.src + }`; + + if (typeof csqSrc.trg == "string") { + subQStr += ` = ?`; + sqlSearhValues.push(csqSrc.trg); + } else if (typeof csqSrc.trg == "object") { + subQStr += ` = ${csqSrc.trg.table}.${csqSrc.trg.field}`; + } + + if (j < countSubQuery.srcTrgMap.length - 1) { + subQStr += ` AND `; + } + } + + subQStr += ` )) AS ${countSubQuery.alias}`; + countSqls.push(subQStr); + } + + str += `, ${countSqls.join(",")}`; + } + + if (genObject?.join) { + const existingJoinTableNames: string[] = [table_name]; + + str += + "," + + genObject.join + .flat() + .filter((j) => !isUndefined(j)) + .map((joinObj) => { + const joinTableName = joinObj.alias + ? joinObj.alias + : joinObj.tableName; + + if (existingJoinTableNames.includes(joinTableName)) + return null; + existingJoinTableNames.push(joinTableName); + + if (joinObj.group_concat) { + return sqlGenGrabConcatStr({ + field: `${joinTableName}.${joinObj.group_concat.field}`, + alias: joinObj.group_concat.alias, + separator: joinObj.group_concat.separator, + }); + } else if (joinObj.selectFields) { + return joinObj.selectFields + .map((selectField) => { + if (typeof selectField == "string") { + return `${joinTableName}.${selectField}`; + } else if (typeof selectField == "object") { + let aliasSelectField = selectField.count + ? `COUNT(${joinTableName}.${selectField.field})` + : `${joinTableName}.${selectField.field}`; + if (selectField.alias) + aliasSelectField += ` AS ${selectField.alias}`; + return aliasSelectField; + } + }) + .join(","); + } else { + return `${joinTableName}.*`; + } + }) + .filter((_) => Boolean(_)) + .join(","); + } + + if ( + genObject?.fullTextSearch && + full_text_match_str && + full_text_search_str + ) { + str += `, ${full_text_match_str} AS ${genObject.fullTextSearch.scoreAlias}`; + sqlSearhValues.push(full_text_search_str); + } + + str += ` FROM ${table_name}`; + + if (genObject?.join) { + str += + " " + + genObject.join + .flat() + .filter((j) => !isUndefined(j)) + .map((join) => { + return ( + join.joinType + + " " + + (join.alias + ? `${join.tableName}` + " " + join.alias + : `${join.tableName}`) + + " ON " + + (() => { + if (Array.isArray(join.match)) { + return ( + "(" + + join.match + .map((mtch) => + sqlGenGenJoinStr({ + mtch, + join, + table_name, + }), + ) + .join( + join.operator + ? ` ${join.operator} ` + : " AND ", + ) + + ")" + ); + } else if (typeof join.match == "object") { + return sqlGenGenJoinStr({ + mtch: join.match, + join, + table_name, + }); + } + })() + ); + }) + .join(" "); + } + + return { str, values: sqlSearhValues }; +} diff --git a/src/utils/sql-generator-gen-search-str.ts b/src/utils/sql-generator-gen-search-str.ts new file mode 100644 index 0000000..12022d2 --- /dev/null +++ b/src/utils/sql-generator-gen-search-str.ts @@ -0,0 +1,113 @@ +import type { + ServerQueryParamsJoin, + ServerQueryQueryObject, + ServerQueryValuesObject, +} from "../types"; +import sqlGenOperatorGen from "./sql-gen-operator-gen"; + +type Param = { + queryObj: ServerQueryQueryObject[string]; + join?: (ServerQueryParamsJoin | ServerQueryParamsJoin[] | undefined)[]; + field?: string; + table_name: string; +}; + +export default function sqlGenGenSearchStr({ + queryObj, + join, + field, + table_name, +}: Param) { + let sqlSearhValues = []; + + const finalFieldName = (() => { + if (queryObj?.tableName) { + return `${queryObj.tableName}.${field}`; + } + if (join) { + return `${table_name}.${field}`; + } + return field; + })(); + + let str = `${finalFieldName}=?`; + + function grabValue(val?: string | number | ServerQueryValuesObject | null) { + const valueParsed = val; + + if (!valueParsed) return; + + const valueString = + typeof valueParsed == "string" || typeof valueParsed == "number" + ? valueParsed + : valueParsed + ? valueParsed.fieldName && valueParsed.tableName + ? `${valueParsed.tableName}.${valueParsed.fieldName}` + : valueParsed.value + : undefined; + + const valueEquality = + typeof valueParsed == "object" + ? valueParsed.equality || queryObj.equality + : queryObj.equality; + + const operatorStrParam = sqlGenOperatorGen({ + queryObj, + equality: valueEquality, + fieldName: finalFieldName || "", + value: valueString || "", + isValueFieldValue: Boolean( + typeof valueParsed == "object" && + valueParsed.fieldName && + valueParsed.tableName, + ), + }); + + return operatorStrParam; + } + + if (Array.isArray(queryObj.value)) { + const strArray: string[] = []; + + queryObj.value.forEach((val) => { + const operatorStrParam = grabValue(val); + + if (!operatorStrParam) return; + + if (operatorStrParam.str && operatorStrParam.param) { + strArray.push(operatorStrParam.str); + sqlSearhValues.push(operatorStrParam.param); + } else if (operatorStrParam.str) { + strArray.push(operatorStrParam.str); + } + }); + + str = "(" + strArray.join(` ${queryObj.operator || "AND"} `) + ")"; + } else if (typeof queryObj.value == "object") { + const operatorStrParam = grabValue(queryObj.value); + if (operatorStrParam?.str) { + str = operatorStrParam.str; + if (operatorStrParam.param) { + sqlSearhValues.push(operatorStrParam.param); + } + } + } else { + const valueParsed = queryObj.value ? queryObj.value : undefined; + + const operatorStrParam = sqlGenOperatorGen({ + equality: queryObj.equality, + fieldName: finalFieldName || "", + value: valueParsed, + queryObj, + }); + + if (operatorStrParam.str && operatorStrParam.param) { + str = operatorStrParam.str; + sqlSearhValues.push(operatorStrParam.param); + } else if (operatorStrParam.str) { + str = operatorStrParam.str; + } + } + + return { str, values: sqlSearhValues }; +} diff --git a/src/utils/sql-generator-grab-concat-str.ts b/src/utils/sql-generator-grab-concat-str.ts new file mode 100644 index 0000000..9d5242e --- /dev/null +++ b/src/utils/sql-generator-grab-concat-str.ts @@ -0,0 +1,14 @@ +type Param = { + field: string; + alias: string; + separator?: string; +}; + +export default function sqlGenGrabConcatStr({ + alias, + field, + separator = ",", +}: Param) { + let gc = `GROUP_CONCAT(${field}, '${separator}') AS ${alias}`; + return gc; +} diff --git a/src/utils/sql-generator-grab-select-field-sql.ts b/src/utils/sql-generator-grab-select-field-sql.ts new file mode 100644 index 0000000..1a85bf0 --- /dev/null +++ b/src/utils/sql-generator-grab-select-field-sql.ts @@ -0,0 +1,55 @@ +import type { TableSelectFieldsObject } from "../types"; +import sqlGenGrabConcatStr from "./sql-generator-grab-concat-str"; + +type Param = { + selectFields: (keyof T | TableSelectFieldsObject)[]; + append_table_names?: boolean; + table_name: string; +}; + +export default function sqlGenGrabSelectFieldSQL< + T extends { [key: string]: any } = { [key: string]: any }, +>({ selectFields, append_table_names, table_name }: Param) { + let str = ""; + + str += ` ${selectFields + ?.map((fld) => { + let fld_str = ``; + + const final_fld_name = + typeof fld == "object" + ? append_table_names + ? `${table_name}.${String(fld)}` + : `${String(fld.fieldName)}` + : `${String(fld)}`; + + if (typeof fld == "object") { + const fld_name = `${String(fld.fieldName)}`; + + if (fld.count) { + fld_str += `COUNT(${fld_name})`; + if (fld.count.alias) { + fld_str += ` AS ${fld.count.alias}`; + } + } else if (fld.sum) { + fld_str += `SUM(${fld_name}) AS ${fld.sum.alias}`; + } else if (fld.group_concat) { + fld_str += sqlGenGrabConcatStr({ + field: fld_name, + alias: fld.group_concat.alias, + separator: fld.group_concat.separator, + }); + } else { + fld_str += + final_fld_name + (fld.alias ? ` as ${fld.alias}` : ``); + } + } else { + fld_str += final_fld_name; + } + + return fld_str; + }) + .join(",")}`; + + return str; +} diff --git a/src/utils/sql-generator.ts b/src/utils/sql-generator.ts index a61eaf0..9b6511f 100644 --- a/src/utils/sql-generator.ts +++ b/src/utils/sql-generator.ts @@ -1,13 +1,10 @@ -import { isUndefined } from "lodash"; -import sqlGenOperatorGen from "./sql-gen-operator-gen"; import type { ServerQueryParam, ServerQueryParamOrder, - ServerQueryParamsJoin, - ServerQueryParamsJoinMatchObject, - ServerQueryQueryObject, - ServerQueryValuesObject, + SQLInsertGenValueType, } from "../types"; +import sqlGenGenSearchStr from "./sql-generator-gen-search-str"; +import sqlGenGenQueryStr from "./sql-generator-gen-query-str"; type Param = { genObject?: ServerQueryParam; @@ -18,7 +15,7 @@ type Param = { type Return = { string: string; - values: (string | number)[]; + values: SQLInsertGenValueType[]; }; /** @@ -32,176 +29,7 @@ export default function sqlGenerator< const queryKeys = finalQuery ? Object.keys(finalQuery) : undefined; - const sqlSearhValues: string[] = []; - - const finalDbName = dbFullName ? `${dbFullName}.` : ""; - - /** - * # Generate Query - */ - function genSqlSrchStr({ - queryObj, - join, - field, - }: { - queryObj: ServerQueryQueryObject[string]; - join?: (ServerQueryParamsJoin | ServerQueryParamsJoin[] | undefined)[]; - field?: string; - }) { - const finalFieldName = (() => { - if (queryObj?.tableName) { - return `${finalDbName}${queryObj.tableName}.${field}`; - } - if (join) { - return `${finalDbName}${tableName}.${field}`; - } - return field; - })(); - - let str = `${finalFieldName}=?`; - - function grabValue( - val?: string | number | ServerQueryValuesObject | null, - ) { - const valueParsed = val; - - if (!valueParsed) return; - - const valueString = - typeof valueParsed == "string" || typeof valueParsed == "number" - ? valueParsed - : valueParsed - ? valueParsed.fieldName && valueParsed.tableName - ? `${valueParsed.tableName}.${valueParsed.fieldName}` - : valueParsed.value?.toString() - : undefined; - - const valueEquality = - typeof valueParsed == "object" - ? valueParsed.equality || queryObj.equality - : queryObj.equality; - - const operatorStrParam = sqlGenOperatorGen({ - queryObj, - equality: valueEquality, - fieldName: finalFieldName || "", - value: valueString?.toString() || "", - isValueFieldValue: Boolean( - typeof valueParsed == "object" && - valueParsed.fieldName && - valueParsed.tableName, - ), - }); - - return operatorStrParam; - } - - if (Array.isArray(queryObj.value)) { - const strArray: string[] = []; - - queryObj.value.forEach((val) => { - const operatorStrParam = grabValue(val); - - if (!operatorStrParam) return; - - if (operatorStrParam.str && operatorStrParam.param) { - strArray.push(operatorStrParam.str); - sqlSearhValues.push(operatorStrParam.param); - } else if (operatorStrParam.str) { - strArray.push(operatorStrParam.str); - } - }); - - str = "(" + strArray.join(` ${queryObj.operator || "AND"} `) + ")"; - } else if (typeof queryObj.value == "object") { - const operatorStrParam = grabValue(queryObj.value); - if (operatorStrParam?.str) { - str = operatorStrParam.str; - if (operatorStrParam.param) { - sqlSearhValues.push(operatorStrParam.param); - } - } - } else { - const valueParsed = queryObj.value - ? String(queryObj.value) - : undefined; - - const operatorStrParam = sqlGenOperatorGen({ - equality: queryObj.equality, - fieldName: finalFieldName || "", - value: valueParsed, - queryObj, - }); - - if (operatorStrParam.str && operatorStrParam.param) { - str = operatorStrParam.str; - sqlSearhValues.push(operatorStrParam.param); - } else if (operatorStrParam.str) { - str = operatorStrParam.str; - } - } - - return str; - } - - function generateJoinStr( - mtch: ServerQueryParamsJoinMatchObject, - join: ServerQueryParamsJoin, - ) { - if (mtch.__batch) { - let btch_mtch = ``; - btch_mtch += `(`; - - for (let i = 0; i < mtch.__batch.matches.length; i++) { - const __mtch = mtch.__batch.matches[ - i - ] as ServerQueryParamsJoinMatchObject; - btch_mtch += `${generateJoinStr(__mtch, join)}`; - if (i < mtch.__batch.matches.length - 1) { - btch_mtch += ` ${mtch.__batch.operator || "OR"} `; - } - } - - btch_mtch += `)`; - - return btch_mtch; - } - - return `${finalDbName}${ - typeof mtch.source == "object" ? mtch.source.tableName : tableName - }.${ - typeof mtch.source == "object" ? mtch.source.fieldName : mtch.source - }=${(() => { - if (mtch.targetLiteral) { - if (typeof mtch.targetLiteral == "number") { - return `${mtch.targetLiteral}`; - } - return `'${mtch.targetLiteral}'`; - } - - if (join.alias) { - return `${finalDbName}${ - typeof mtch.target == "object" - ? mtch.target.tableName - : join.alias - }.${ - typeof mtch.target == "object" - ? mtch.target.fieldName - : mtch.target - }`; - } - - return `${finalDbName}${ - typeof mtch.target == "object" - ? mtch.target.tableName - : join.tableName - }.${ - typeof mtch.target == "object" - ? mtch.target.fieldName - : mtch.target - }`; - })()}`; - } + const sqlSearhValues: SQLInsertGenValueType[] = []; let fullTextMatchStr = genObject?.fullTextSearch ? ` MATCH(${genObject.fullTextSearch.fields @@ -218,179 +46,15 @@ export default function sqlGenerator< .join(" ") : undefined; - let queryString = (() => { - let str = "SELECT"; + let { str: queryString, values } = sqlGenGenQueryStr({ + table_name: tableName, + append_table_names: true, + full_text_match_str: fullTextMatchStr, + full_text_search_str: fullTextSearchStr, + genObject, + }); - if (genObject?.select_sql) { - str += ` ${genObject.select_sql}`; - } else if (genObject?.selectFields?.[0]) { - if (genObject.join) { - str += ` ${genObject.selectFields - ?.map((fld) => - typeof fld == "object" - ? `${finalDbName}${tableName}.${fld.fieldName.toString()}` + - (fld.alias ? ` as ${fld.alias}` : ``) - : `${finalDbName}${tableName}.${String(fld)}`, - ) - .join(",")}`; - } else { - str += ` ${genObject.selectFields - ?.map((fld) => - typeof fld == "object" - ? `${fld.fieldName.toString()}` + - (fld.alias ? ` as ${fld.alias}` : ``) - : fld, - ) - .join(",")}`; - } - } else { - if (genObject?.join) { - str += ` ${finalDbName}${tableName}.*`; - } else { - str += " *"; - } - } - - if (genObject?.countSubQueries) { - let countSqls: string[] = []; - - for (let i = 0; i < genObject.countSubQueries.length; i++) { - const countSubQuery = genObject.countSubQueries[i]; - if (!countSubQuery) continue; - - const tableAlias = countSubQuery.table_alias; - - let subQStr = `(SELECT COUNT(*)`; - - subQStr += ` FROM ${countSubQuery.table}${ - tableAlias ? ` ${tableAlias}` : "" - }`; - - subQStr += ` WHERE (`; - - for (let j = 0; j < countSubQuery.srcTrgMap.length; j++) { - const csqSrc = countSubQuery.srcTrgMap[j]; - if (!csqSrc) continue; - - subQStr += ` ${tableAlias || countSubQuery.table}.${ - csqSrc.src - }`; - - if (typeof csqSrc.trg == "string") { - subQStr += ` = ?`; - sqlSearhValues.push(csqSrc.trg); - } else if (typeof csqSrc.trg == "object") { - subQStr += ` = ${csqSrc.trg.table}.${csqSrc.trg.field}`; - } - - if (j < countSubQuery.srcTrgMap.length - 1) { - subQStr += ` AND `; - } - } - - subQStr += ` )) AS ${countSubQuery.alias}`; - countSqls.push(subQStr); - } - - str += `, ${countSqls.join(",")}`; - } - - if (genObject?.join) { - const existingJoinTableNames: string[] = [tableName]; - - str += - "," + - genObject.join - .flat() - .filter((j) => !isUndefined(j)) - .map((joinObj) => { - const joinTableName = joinObj.alias - ? joinObj.alias - : joinObj.tableName; - - if (existingJoinTableNames.includes(joinTableName)) - return null; - existingJoinTableNames.push(joinTableName); - - if (joinObj.group_concat) { - let group_concat = `GROUP_CONCAT(${joinTableName}.${joinObj.group_concat.field}, '${joinObj.group_concat.separator || ","}') AS ${joinObj.group_concat.alias}`; - return group_concat; - } else if (joinObj.selectFields) { - return joinObj.selectFields - .map((selectField) => { - if (typeof selectField == "string") { - return `${finalDbName}${joinTableName}.${selectField}`; - } else if (typeof selectField == "object") { - let aliasSelectField = selectField.count - ? `COUNT(${finalDbName}${joinTableName}.${selectField.field})` - : `${finalDbName}${joinTableName}.${selectField.field}`; - if (selectField.alias) - aliasSelectField += ` AS ${selectField.alias}`; - return aliasSelectField; - } - }) - .join(","); - } else { - return `${finalDbName}${joinTableName}.*`; - } - }) - .filter((_) => Boolean(_)) - .join(","); - } - - if ( - genObject?.fullTextSearch && - fullTextMatchStr && - fullTextSearchStr - ) { - str += `, ${fullTextMatchStr} AS ${genObject.fullTextSearch.scoreAlias}`; - sqlSearhValues.push(fullTextSearchStr); - } - - str += ` FROM ${finalDbName}${tableName}`; - - if (genObject?.join) { - str += - " " + - genObject.join - .flat() - .filter((j) => !isUndefined(j)) - .map((join) => { - return ( - join.joinType + - " " + - (join.alias - ? `${finalDbName}${join.tableName}` + - " " + - join.alias - : `${finalDbName}${join.tableName}`) + - " ON " + - (() => { - if (Array.isArray(join.match)) { - return ( - "(" + - join.match - .map((mtch) => - generateJoinStr(mtch, join), - ) - .join( - join.operator - ? ` ${join.operator} ` - : " AND ", - ) + - ")" - ); - } else if (typeof join.match == "object") { - return generateJoinStr(join.match, join); - } - })() - ); - }) - .join(" "); - } - - return str; - })(); + sqlSearhValues.push(...values); const sqlSearhString = queryKeys?.map((field) => { const queryObj = finalQuery?.[field]; @@ -404,11 +68,16 @@ export default function sqlGenerator< const newSubQueryObj = subQueryGroup?.[_field]; if (newSubQueryObj) { - return genSqlSrchStr({ + const { str, values } = sqlGenGenSearchStr({ queryObj: newSubQueryObj, field: newSubQueryObj.fieldName || _field, join: genObject?.join, + table_name: tableName, }); + + sqlSearhValues.push(...values); + + return str; } }); @@ -419,11 +88,16 @@ export default function sqlGenerator< ); } - return genSqlSrchStr({ + const { str, values } = sqlGenGenSearchStr({ queryObj, field: queryObj.fieldName || field, join: genObject?.join, + table_name: tableName, }); + + sqlSearhValues.push(...values); + + return str; }); const cleanedUpSearchStr = sqlSearhString?.filter( @@ -484,9 +158,7 @@ export default function sqlGenerator< if (genObject?.fullTextSearch && genObject.fullTextSearch.scoreAlias) { orderFields.push(genObject.fullTextSearch.scoreAlias); } else if (genObject?.join) { - orderFields.push( - `${finalDbName}${tableName}.${String(order.field)}`, - ); + orderFields.push(`${tableName}.${String(order.field)}`); } else { orderFields.push(order.field); } @@ -528,3 +200,179 @@ export default function sqlGenerator< values: sqlSearhValues, }; } + +// let queryString = (() => { +// let str = "SELECT"; + +// if (genObject?.select_sql) { +// str += ` ${genObject.select_sql}`; +// } else if (genObject?.selectFields?.[0]) { +// if (genObject.join) { +// str += sqlGenGrabSelectFieldSQL({ +// selectFields: genObject.selectFields, +// append_table_names: true, +// table_name: tableName, +// }); +// } else { +// str += sqlGenGrabSelectFieldSQL({ +// selectFields: genObject.selectFields, +// table_name: tableName, +// }); +// } +// } else { +// if (genObject?.join) { +// str += ` ${tableName}.*`; +// } else { +// str += " *"; +// } +// } + +// if (genObject?.countSubQueries) { +// let countSqls: string[] = []; + +// for (let i = 0; i < genObject.countSubQueries.length; i++) { +// const countSubQuery = genObject.countSubQueries[i]; +// if (!countSubQuery) continue; + +// const tableAlias = countSubQuery.table_alias; + +// let subQStr = `(SELECT COUNT(*)`; + +// subQStr += ` FROM ${countSubQuery.table}${ +// tableAlias ? ` ${tableAlias}` : "" +// }`; + +// subQStr += ` WHERE (`; + +// for (let j = 0; j < countSubQuery.srcTrgMap.length; j++) { +// const csqSrc = countSubQuery.srcTrgMap[j]; +// if (!csqSrc) continue; + +// subQStr += ` ${tableAlias || countSubQuery.table}.${ +// csqSrc.src +// }`; + +// if (typeof csqSrc.trg == "string") { +// subQStr += ` = ?`; +// sqlSearhValues.push(csqSrc.trg); +// } else if (typeof csqSrc.trg == "object") { +// subQStr += ` = ${csqSrc.trg.table}.${csqSrc.trg.field}`; +// } + +// if (j < countSubQuery.srcTrgMap.length - 1) { +// subQStr += ` AND `; +// } +// } + +// subQStr += ` )) AS ${countSubQuery.alias}`; +// countSqls.push(subQStr); +// } + +// str += `, ${countSqls.join(",")}`; +// } + +// if (genObject?.join) { +// const existingJoinTableNames: string[] = [tableName]; + +// str += +// "," + +// genObject.join +// .flat() +// .filter((j) => !isUndefined(j)) +// .map((joinObj) => { +// const joinTableName = joinObj.alias +// ? joinObj.alias +// : joinObj.tableName; + +// if (existingJoinTableNames.includes(joinTableName)) +// return null; +// existingJoinTableNames.push(joinTableName); + +// if (joinObj.group_concat) { +// return sqlGenGrabConcatStr({ +// field: `${joinTableName}.${joinObj.group_concat.field}`, +// alias: joinObj.group_concat.alias, +// separator: joinObj.group_concat.separator, +// }); +// } else if (joinObj.selectFields) { +// return joinObj.selectFields +// .map((selectField) => { +// if (typeof selectField == "string") { +// return `${joinTableName}.${selectField}`; +// } else if (typeof selectField == "object") { +// let aliasSelectField = selectField.count +// ? `COUNT(${joinTableName}.${selectField.field})` +// : `${joinTableName}.${selectField.field}`; +// if (selectField.alias) +// aliasSelectField += ` AS ${selectField.alias}`; +// return aliasSelectField; +// } +// }) +// .join(","); +// } else { +// return `${joinTableName}.*`; +// } +// }) +// .filter((_) => Boolean(_)) +// .join(","); +// } + +// if ( +// genObject?.fullTextSearch && +// fullTextMatchStr && +// fullTextSearchStr +// ) { +// str += `, ${fullTextMatchStr} AS ${genObject.fullTextSearch.scoreAlias}`; +// sqlSearhValues.push(fullTextSearchStr); +// } + +// str += ` FROM ${tableName}`; + +// if (genObject?.join) { +// str += +// " " + +// genObject.join +// .flat() +// .filter((j) => !isUndefined(j)) +// .map((join) => { +// return ( +// join.joinType + +// " " + +// (join.alias +// ? `${join.tableName}` + " " + join.alias +// : `${join.tableName}`) + +// " ON " + +// (() => { +// if (Array.isArray(join.match)) { +// return ( +// "(" + +// join.match +// .map((mtch) => +// sqlGenGenJoinStr({ +// mtch, +// join, +// table_name: tableName, +// }), +// ) +// .join( +// join.operator +// ? ` ${join.operator} ` +// : " AND ", +// ) + +// ")" +// ); +// } else if (typeof join.match == "object") { +// return sqlGenGenJoinStr({ +// mtch: join.match, +// join, +// table_name: tableName, +// }); +// } +// })() +// ); +// }) +// .join(" "); +// } + +// return str; +// })();