Major version update. Refactor sql generator function. Add core select directives like SUM, MIN, MAX, etc

This commit is contained in:
Benjamin Toby 2026-04-18 07:24:01 +01:00
parent 0a3320ff83
commit f3f1c42699
23 changed files with 1275 additions and 662 deletions

41
dist/types/index.d.ts vendored
View File

@ -711,6 +711,17 @@ export type TableSelectFieldsObject<T extends {
}> = {
fieldName: keyof T;
alias?: string;
count?: {
alias?: string;
};
sum?: TableSelectFieldsBasicDirective;
max?: TableSelectFieldsBasicDirective;
min?: TableSelectFieldsBasicDirective;
average?: TableSelectFieldsBasicDirective;
group_concat?: Omit<GroupConcatObject, "field">;
};
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<Table extends string = string, Field extends o
alias?: string;
tableName: Table;
match?: ServerQueryParamsJoinMatchObject<Field> | ServerQueryParamsJoinMatchObject<Field>[];
selectFields?: (keyof Field | {
field: keyof Field;
alias?: string;
count?: boolean;
})[];
selectFields?: (keyof Field | SelectFieldObject<Field>)[];
omitFields?: (keyof Field | {
field: keyof Field;
alias?: string;
@ -810,14 +817,22 @@ export type ServerQueryParamsJoin<Table extends string = string, Field extends o
/**
* 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 extends object = {
[key: string]: any;
}> = {
field: keyof Field;
alias?: string;
count?: boolean;
};
/**
* Defines how a root-table field maps to a join-table field in an `ON` clause.

View File

@ -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

View File

@ -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 {};

View File

@ -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}`;
})()}`;
}

View File

@ -0,0 +1,22 @@
import type { ServerQueryParam, TableSelectFieldsObject } from "../types";
type Param<T extends {
[key: string]: any;
} = {
[key: string]: any;
}> = {
genObject?: ServerQueryParam<T>;
selectFields?: (keyof T | TableSelectFieldsObject<T>)[];
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<T>): {
str: string;
values: any[];
};
export {};

View File

@ -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 };
}

View File

@ -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<ArrayBuffer> | Buffer<ArrayBuffer>)[];
};
export {};

View File

@ -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 };
}

View File

@ -0,0 +1,7 @@
type Param = {
field: string;
alias: string;
separator?: string;
};
export default function sqlGenGrabConcatStr({ alias, field, separator, }: Param): string;
export {};

View File

@ -0,0 +1,4 @@
export default function sqlGenGrabConcatStr({ alias, field, separator = ",", }) {
let gc = `GROUP_CONCAT(${field}, '${separator}') AS ${alias}`;
return gc;
}

View File

@ -0,0 +1,16 @@
import type { TableSelectFieldsObject } from "../types";
type Param<T extends {
[key: string]: any;
} = {
[key: string]: any;
}> = {
selectFields: (keyof T | TableSelectFieldsObject<T>)[];
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<T>): string;
export {};

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
import type { ServerQueryParam } from "../types";
import type { ServerQueryParam, SQLInsertGenValueType } from "../types";
type Param<T extends {
[key: string]: any;
} = {
@ -11,7 +11,7 @@ type Param<T extends {
};
type Return = {
string: string;
values: (string | number)[];
values: SQLInsertGenValueType[];
};
/**
* # SQL Query Generator

View File

@ -1,5 +1,5 @@
import { isUndefined } from "lodash";
import sqlGenOperatorGen from "./sql-gen-operator-gen";
import sqlGenGenSearchStr from "./sql-generator-gen-search-str";
import sqlGenGenQueryStr from "./sql-generator-gen-query-str";
/**
* # SQL Query Generator
* @description Generates an SQL Query for node module `mysql` or `serverless-mysql`
@ -8,126 +8,6 @@ export default function sqlGenerator({ tableName, genObject, dbFullName, count }
const finalQuery = genObject?.query ? genObject.query : undefined;
const queryKeys = finalQuery ? Object.keys(finalQuery) : undefined;
const sqlSearhValues = [];
const finalDbName = dbFullName ? `${dbFullName}.` : "";
/**
* # Generate Query
*/
function genSqlSrchStr({ queryObj, join, field, }) {
const finalFieldName = (() => {
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<T>({
// 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;
// })();

View File

@ -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",

View File

@ -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<GroupConcatObject, "field">;
};
export type TableSelectFieldsBasicDirective = {
alias: string;
};
/**
@ -882,14 +894,7 @@ export type ServerQueryParamsJoin<
match?:
| ServerQueryParamsJoinMatchObject<Field>
| ServerQueryParamsJoinMatchObject<Field>[];
selectFields?: (
| keyof Field
| {
field: keyof Field;
alias?: string;
count?: boolean;
}
)[];
selectFields?: (keyof Field | SelectFieldObject<Field>)[];
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 extends object = { [key: string]: any }> = {
field: keyof Field;
alias?: string;
count?: boolean;
};
/**

View File

@ -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;
};
/**

View File

@ -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
}`;
})()}`;
}

View File

@ -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<T extends { [key: string]: any } = { [key: string]: any }> = {
genObject?: ServerQueryParam<T>;
selectFields?: (keyof T | TableSelectFieldsObject<T>)[];
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<T>) {
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<T>({
selectFields: genObject.selectFields,
append_table_names: true,
table_name,
});
} else {
str += sqlGenGrabSelectFieldSQL<T>({
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 };
}

View File

@ -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 };
}

View File

@ -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;
}

View File

@ -0,0 +1,55 @@
import type { TableSelectFieldsObject } from "../types";
import sqlGenGrabConcatStr from "./sql-generator-grab-concat-str";
type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
selectFields: (keyof T | TableSelectFieldsObject<T>)[];
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<T>) {
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;
}

View File

@ -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<T extends { [key: string]: any } = { [key: string]: any }> = {
genObject?: ServerQueryParam<T>;
@ -18,7 +15,7 @@ type Param<T extends { [key: string]: any } = { [key: string]: any }> = {
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<T>({
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<T>({
// 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;
// })();