@devscast/queryzen
Version:
QueryZen : TypeScript SQL Query Builder inspired by Doctrine DBAL
2 lines (1 loc) • 13.8 kB
JavaScript
var b=(u=>(u.NULL="NULL",u.INTEGER="INTEGER",u.STRING="STRING",u.LARGE_OBJECT="LARGE_OBJECT",u.BOOLEAN="BOOLEAN",u.BINARY="BINARY",u.ASCII="ASCII",u))(b||{});var E=(s=>(s.INTEGER="INTEGER",s.STRING="STRING",s.ASCII="ASCII",s.BINARY="BINARY",s))(E||{});(t=>{function e(r){switch(r){case"INTEGER":return"INTEGER";case"STRING":return"STRING";case"ASCII":return"ASCII";case"BINARY":return"BINARY"}}t.toElementParameterType=e})(E||={});var S=(r=>(r[r.ORDINARY=0]="ORDINARY",r[r.SKIP_LOCKED=1]="SKIP_LOCKED",r))(S||{}),y=class{constructor(t){this.conflictResolutionMode=t}};var m=class e extends Error{constructor(t){super(`Operation "${t}" is not supported by platform.`),this.name="NotSupported",Object.setPrototypeOf(this,e.prototype)}static new(t){return new e(t)}};var x=class{constructor(t,r,i){this.platform=t;this.forUpdateSQL=r;this.skipLockedSQL=i}buildSQL(t){let r=["SELECT"];t.distinct&&r.push("DISTINCT"),r.push(t.columns.join(", "));let i=t.from;i.length>0&&r.push(`FROM ${i.join(", ")}`);let s=t.where;s!==null&&r.push(`WHERE ${s}`);let n=t.groupBy;n.length>0&&r.push(`GROUP BY ${n.join(", ")}`);let o=t.having;o!==null&&r.push(`HAVING ${o}`);let u=t.orderBy;u.length>0&&r.push(`ORDER BY ${u.join(", ")}`);let p=r.join(" "),d=t.limit;d.isDefined()&&(p=this.platform.modifyLimitQuery(p,d.getMaxResults(),d.getFirstResult()));let U=t.forUpdate;if(U!==null){if(this.forUpdateSQL===null)throw m.new("FOR UPDATE");if(p+=` ${this.forUpdateSQL}`,U.conflictResolutionMode===1){if(this.skipLockedSQL===null)throw m.new("SKIP LOCKED");p+=` ${this.skipLockedSQL}`}}return p}};var L=(r=>(r[r.ALL=0]="ALL",r[r.DISTINCT=1]="DISTINCT",r))(L||{});var T=class{constructor(t){this.platform=t}buildSQL(t){let r=[];for(let o of t.unionParts)o.type!==null&&r.push(o.type===0?this.platform.getUnionAllSQL():this.platform.getUnionDistinctSQL()),r.push(this.platform.getUnionSelectPartSQL(String(o.query)));let i=t.orderBy;i.length>0&&r.push(`ORDER BY ${i.join(", ")}`);let s=r.join(" "),n=t.limit;return n.isDefined()&&(s=this.platform.modifyLimitQuery(s,n.getMaxResults(),n.getFirstResult())),s}};var R=class{buildSQL(t,...r){let i=[];for(let s of[t,...r]){let n=[s.name];s.columns&&s.columns.length>0&&n.push(` (${s.columns.join(", ")})`),n.push(` AS (${s.query})`),i.push(n.join(""))}return`WITH ${i.join(", ")}`}};var N=class{quoteSingleIdentifier(t){return`"${t.replace(/"/g,'""')}"`}modifyLimitQuery(t,r,i=0){if(i<0)throw new Error(`Offset must be a positive integer or zero, ${i} given.`);return this.doModifyLimitQuery(t,r,i)}doModifyLimitQuery(t,r,i){return r!==null&&(t+=` LIMIT ${r}`),i>0&&(t+=` OFFSET ${i}`),t}quoteStringLiteral(t){return`'${t.replace(/'/g,"''")}'`}getUnionSelectPartSQL(t){return`(${t})`}getUnionAllSQL(){return"UNION ALL"}getUnionDistinctSQL(){return"UNION"}createSelectSQLBuilder(){return new x(this,"FOR UPDATE","SKIP LOCKED")}createUnionSQLBuilder(){return new T(this)}createWithSQLBuilder(){return new R}};var I=class extends N{doModifyLimitQuery(t,r,i){return r!==null?(t+=` LIMIT ${r}`,i>0&&(t+=` OFFSET ${i}`)):i>0&&(t+=` LIMIT 18446744073709551615 OFFSET ${i}`),t}quoteSingleIdentifier(t){return`\`${t.replace(/`/g,"``")}\``}};var h=class extends I{};var l=class e extends Error{constructor(t){super(t),this.name="QueryException",Object.setPrototypeOf(this,e.prototype)}};var w=class{name;query;columns;constructor(t,r,i){if(i!==null&&i.length===0)throw new l(`Columns defined in CTE "${t}" should not be an empty array.`);this.name=t,this.query=r,this.columns=i}};var P=class e extends l{static new(t,r){let i=`The given alias "${t}" is not unique in FROM and JOIN clause table. The currently registered aliases are: ${r.join(", ")}.`;return new e(i)}};var C=class e extends l{static new(t,r){let i=`The given alias "${t}" is not part of any FROM or JOIN clause table. The currently registered aliases are: ${r.join(", ")}.`;return new e(i)}};var a=class e{constructor(t,r,...i){this.type=t;this.parts=[r,...i]}static TYPE_AND="AND";static TYPE_OR="OR";parts;static and(t,...r){return new e("AND",t,...r)}static or(t,...r){return new e("OR",t,...r)}with(t,...r){let i=[...this.parts,t,...r].filter(o=>o!==void 0);if(i.length===0)throw new Error("CompositeExpression.with() requires at least one part");let[s,...n]=i;if(s===void 0)throw new Error("CompositeExpression.with() requires at least one valid part");return new e(this.type,s,...n)}getType(){return this.type}count(){return this.parts.length}toString(){return this.parts.length===1?String(this.parts[0]):`(${this.parts.map(String).join(`) ${this.type} (`)})`}};var v=class e{constructor(t=new h){this.platform=t}static EQ="=";static NEQ="<>";static LT="<";static LTE="<=";static GT=">";static GTE=">=";and(t,...r){return a.and(t,...r)}or(t,...r){return a.or(t,...r)}comparison(t,r,i){return`${t} ${r} ${i}`}eq(t,r){return this.comparison(t,e.EQ,r)}neq(t,r){return this.comparison(t,e.NEQ,r)}lt(t,r){return this.comparison(t,e.LT,r)}lte(t,r){return this.comparison(t,e.LTE,r)}gt(t,r){return this.comparison(t,e.GT,r)}gte(t,r){return this.comparison(t,e.GTE,r)}isNull(t){return`${t} IS NULL`}isNotNull(t){return`${t} IS NOT NULL`}like(t,r,i){return this.comparison(t,"LIKE",r)+(i?` ESCAPE ${i}`:"")}notLike(t,r,i){return this.comparison(t,"NOT LIKE",r)+(i?` ESCAPE ${i}`:"")}in(t,r){let i=Array.isArray(r)?r:[r];return this.comparison(t,"IN",`(${i.join(", ")})`)}notIn(t,r){let i=Array.isArray(r)?r:[r];return this.comparison(t,"NOT IN",`(${i.join(", ")})`)}literal(t){return this.platform.quoteStringLiteral(t)}};var O=class{constructor(t,r=null){this.table=t;this.alias=r}};var g=class e{constructor(t,r,i,s){this.type=t;this.table=r;this.alias=i;this.condition=s}static inner(t,r,i){return new e("INNER",t,r,i)}static left(t,r,i){return new e("LEFT",t,r,i)}static right(t,r,i){return new e("RIGHT",t,r,i)}};var c=class{constructor(t,r=0){this.maxResults=t;this.firstResult=r}isDefined(){return this.maxResults!==null||this.firstResult!==0}getMaxResults(){return this.maxResults}getFirstResult(){return this.firstResult}};var Q=class{constructor(t,r,i,s,n,o,u,p,d){this.distinct=t;this.columns=r;this.from=i;this.where=s;this.groupBy=n;this.having=o;this.orderBy=u;this.limit=p;this.forUpdate=d}};var f=class{constructor(t,r=null){this.query=t;this.type=r}};var A=class{constructor(t,r,i){this.unionParts=t;this.orderBy=r;this.limit=i}};var _=(r=>(r.NAMED="named",r.POSITIONAL="positional",r))(_||{}),B=class{constructor(t=new h){this.platform=t}sql=null;params=[];types={};type=0;boundCounter=0;firstResult=0;maxResults=null;table=null;unionParts=[];commonTableExpressions=[];_select=[];_distinct=!1;_from=[];_join={};_set=[];_where=null;_groupBy=[];_having=null;_orderBy=[];_forUpdate=null;_values={};expr(){return new v(this.platform)}getSQL(){if(this.sql!==null)return this.sql;switch(this.type){case 1:return this.sql=this.getSQLForInsert(),this.sql;case 3:return this.sql=this.getSQLForDelete(),this.sql;case 2:return this.sql=this.getSQLForUpdate(),this.sql;case 0:return this.sql=this.getSQLForSelect(),this.sql;case 4:return this.sql=this.getSQLForUnion(),this.sql}}setParameter(t,r,i="STRING"){return this.params[t]=r,this.types[t]=i,this}setParameters(t,r={}){return this.params=t,this.types=r,this}getParameters(){return this.params}getParameter(t){return this.params[t]??null}getParameterTypes(){return this.types}getParameterType(t){return this.types[t]??"STRING"}setFirstResult(t){return this.firstResult=t,this.sql=null,this}getFirstResult(){return this.firstResult}setMaxResults(t){return this.maxResults=t,this.sql=null,this}getMaxResults(){return this.maxResults}forUpdate(t=0){return this._forUpdate=new y(t),this.sql=null,this}union(t){return this.type=4,this.unionParts=[new f(t)],this.sql=null,this}addUnion(t,r=1){if(this.type=4,this.unionParts.length===0)throw new l("No initial UNION part set, use union() to set one first.");return this.unionParts.push(new f(t,r)),this.sql=null,this}with(t,r,i=null){return this.commonTableExpressions.push(new w(t,r,i)),this.sql=null,this}select(...t){return this.type=0,this._select=t,this.sql=null,this}distinct(t=!0){return this._distinct=t,this.sql=null,this}addSelect(t,...r){return this.type=0,this._select.push(t,...r),this.sql=null,this}delete(t){return this.type=3,this.table=t,this.sql=null,this}update(t){return this.type=2,this.table=t,this.sql=null,this}insert(t){return this.type=1,this.table=t,this.sql=null,this}insertWith(t,r,i="positional"){if(!r||Object.keys(r).length===0)throw new l("Insufficient data given for insert operation. Data cannot be empty.");this.insert(t);for(let s of Object.keys(r)){let n=r[s],o=i==="named"?this.createNamedParameter(n,s,"STRING"):this.createPositionalParameter(n,"STRING");this.setValue(s,o)}return this}updateWith(t,r,i="positional"){if(!r||Object.keys(r).length===0)throw new l("Insufficient data given for update operation. Data cannot be empty.");this.update(t);for(let s of Object.keys(r)){let n=r[s],o=i==="named"?this.createNamedParameter(n,s,"STRING"):this.createPositionalParameter(n,"STRING");this.set(s,o)}return this}from(t,r=null){return this._from.push(new O(t,r)),this.sql=null,this}join(t,r,i,s=null){return this.innerJoin(t,r,i,s)}innerJoin(t,r,i,s=null){return this._join[t]=this._join[t]??[],this._join[t].push(g.inner(r,i,s)),this.sql=null,this}leftJoin(t,r,i,s=null){return this._join[t]=this._join[t]??[],this._join[t].push(g.left(r,i,s)),this.sql=null,this}rightJoin(t,r,i,s=null){return this._join[t]=this._join[t]??[],this._join[t].push(g.right(r,i,s)),this.sql=null,this}set(t,r){return this._set.push(`${t} = ${r}`),this.sql=null,this}where(t,...r){return this._where=this.createPredicate(t,...r),this.sql=null,this}andWhere(t,...r){return this._where=this.appendToPredicate(this._where,a.TYPE_AND,t,...r),this.sql=null,this}orWhere(t,...r){return this._where=this.appendToPredicate(this._where,a.TYPE_OR,t,...r),this.sql=null,this}groupBy(t,...r){return this._groupBy=[t,...r],this.sql=null,this}addGroupBy(t,...r){return this._groupBy.push(t,...r),this.sql=null,this}setValue(t,r){return this._values[t]=r,this}values(t){return this._values=t,this.sql=null,this}having(t,...r){return this._having=this.createPredicate(t,...r),this.sql=null,this}andHaving(t,...r){return this._having=this.appendToPredicate(this._having,a.TYPE_AND,t,...r),this.sql=null,this}orHaving(t,...r){return this._having=this.appendToPredicate(this._having,a.TYPE_OR,t,...r),this.sql=null,this}orderBy(t,r){let i=r?`${t} ${r}`:t;return this._orderBy=[i],this.sql=null,this}addOrderBy(t,r){let i=r?`${t} ${r}`:t;return this._orderBy.push(i),this.sql=null,this}resetWhere(){return this._where=null,this.sql=null,this}resetGroupBy(){return this._groupBy=[],this.sql=null,this}resetHaving(){return this._having=null,this.sql=null,this}resetOrderBy(){return this._orderBy=[],this.sql=null,this}toString(){return this.getSQL()}createNamedParameter(t,r=null,i="STRING"){return r===null?(this.boundCounter++,r=`:dcValue${this.boundCounter}`):r=r.startsWith(":")?r:`:${r}`,this.setParameter(r.substring(1),t,i),r}createPositionalParameter(t,r="STRING"){return this.setParameter(this.boundCounter,t,r),this.boundCounter++,"?"}createPredicate(t,...r){return r.length===0?t:new a("AND",t,...r)}appendToPredicate(t,r,...i){if(t instanceof a&&t.getType()===r){if(i.length===0)return t;let[o,...u]=i;return o===void 0?t:t.with(o,...u.filter(p=>p!==void 0))}if(t!==null)i.unshift(t);else if(i.length===1){if(i[0]===void 0)throw new Error("Predicate cannot be undefined");return i[0]}let[s,...n]=i;if(s===void 0)throw new Error("Predicate cannot be undefined");return new a(r,s,...n.filter(o=>o!==void 0))}getSQLForSelect(){if(this._select.length===0)throw new l("No SELECT expressions given. Please use select() or addSelect().");let t=[];if(this.commonTableExpressions.length>0&&this.platform){let[r,...i]=this.commonTableExpressions;if(!r)throw new Error("CommonTableExpression cannot be undefined");t.push(this.platform.createWithSQLBuilder().buildSQL(r,...i.filter(s=>s!==void 0)))}return this.platform&&t.push(this.platform.createSelectSQLBuilder().buildSQL(new Q(this._distinct,this._select,this.getFromClauses(),this._where!==null?this._where.toString():null,this._groupBy,this._having!==null?this._having.toString():null,this._orderBy,new c(this.maxResults,this.firstResult),this._forUpdate))),t.join(" ")}getFromClauses(){let t=[],r=new Set;for(let i of this._from){let s,n;i.alias===null||i.alias===i.table?(s=i.table,n=i.table):(s=`${i.table} ${i.alias}`,n=i.alias),r.add(n),t.push(s+this.getSQLForJoins(n,r))}return this.verifyAllAliasesAreKnown(r),t}verifyAllAliasesAreKnown(t){for(let r in this._join)if(!t.has(r))throw C.new(r,Array.from(t.keys()))}getSQLForInsert(){return`INSERT INTO ${this.table} (${Object.keys(this._values).join(", ")}) VALUES(${Object.values(this._values).join(", ")})`}getSQLForDelete(){let t=`DELETE FROM ${this.table}`;return this._where!==null&&(t+=` WHERE ${this._where}`),t}getSQLForUpdate(){let t=`UPDATE ${this.table} SET ${this._set.join(", ")}`;return this._where!==null&&(t+=` WHERE ${this._where}`),t}getSQLForUnion(){if(this.unionParts.length<2)throw new l("Insufficient UNION parts given, need at least 2. Please use union() and addUnion() to set enough UNION parts.");return this.platform.createUnionSQLBuilder().buildSQL(new A(this.unionParts,this._orderBy,new c(this.maxResults,this.firstResult)))}getSQLForJoins(t,r){let i="";if(!this._join[t])return i;for(let s of this._join[t]){if(r.has(s.alias))throw P.new(s.alias,Array.from(r.keys()));i+=` ${s.type} JOIN ${s.table} ${s.alias}`,s.condition!==null&&(i+=` ON ${s.condition}`),r.add(s.alias)}for(let s of this._join[t])i+=this.getSQLForJoins(s.alias,r);return i}};export{E as ArrayParameterType,S as ConflictResolutionMode,b as ParameterType,_ as PlaceHolder,B as QueryBuilder,L as UnionType};