Added Joins #2

Merged
jusax23 merged 6 commits from dev into main 2023-02-15 15:06:53 +01:00
4 changed files with 181 additions and 10 deletions
Showing only changes of commit 580988e2c0 - Show all commits

View file

@ -1,7 +1,7 @@
import { Attribute, Table } from "./db"; import { Attribute, Table } from "./db";
import { Handler } from "./defaultHandler"; import { Handler } from "./defaultHandler";
import { QueryBuilder } from "./query"; import { QueryBuilder } from "./query";
import { allModifierInput, onAction, primaryData, serializeReturn } from "./types"; import { allModifierInput, joinElements, joinType, onAction, primaryData, serializeReturn } from "./types";
export class Datatype { export class Datatype {
type: string; type: string;
@ -42,11 +42,62 @@ export class Aggregation {
return handler.aggregations[this.t as keyof typeof handler.aggregations](handler, this.a); return handler.aggregations[this.t as keyof typeof handler.aggregations](handler, this.a);
} }
} }
export class Joins { export interface Joins {
serialize(handler: Handler): QueryBuilder
serialize(handler: Handler): QueryBuilder { }
return new QueryBuilder(); export class joinNatural implements Joins{
tables: joinElements[];
type: joinType;
constructor(tables:joinElements[], type: joinType){
this.tables = tables;
this.type = type;
} }
serialize(handler: Handler): QueryBuilder {
return handler.joins.natural(handler,this);
}
}
export class onJoin implements Joins{
tableA: joinElements;
tableB: joinElements;
type: joinType;
on: BooleanModifier;
constructor(tableA: joinElements, tableB: joinElements, type: joinType, on: BooleanModifier){
this.tableA = tableA;
this.tableB = tableB;
this.type = type;
this.on = on;
}
serialize(handler: Handler): QueryBuilder {
return handler.joins.on(handler,this);
}
}
export class usingJoin implements Joins{
tableA: joinElements;
tableB: joinElements;
type: joinType;
using: Attribute[];
constructor(tableA: joinElements, tableB: joinElements, type: joinType, using: Attribute[]){
this.tableA = tableA;
this.tableB = tableB;
this.type = type;
this.using = using;
}
serialize(handler: Handler): QueryBuilder {
return handler.joins.using(handler,this);
}
}
export class joinCross implements Joins{
tables: joinElements[];
constructor(tables:joinElements[]){
this.tables = tables;
}
serialize(handler: Handler): QueryBuilder {
return handler.joins.cross(handler,this);
}
} }
export interface Constraint { export interface Constraint {

View file

@ -1,7 +1,7 @@
import { Attribute, DB, Table } from "./db" import { Attribute, DB, Table } from "./db"
import { Aggregation, checkConstraint, Constraint, Datatype, foreignConstraint, Modifier, uniqueConstraint } from "./dbStructure" import { Aggregation, checkConstraint, joinCross, Datatype, foreignConstraint, Modifier, joinNatural, onJoin, uniqueConstraint, usingJoin } from "./dbStructure"
import { insertQuery, Query, QueryBuilder, removeQuery, selectQuery, updateQuery } from "./query" import { insertQuery, Query, QueryBuilder, removeQuery, selectQuery, updateQuery } from "./query"
import { allModifierInput, onAction, primaryData, serializeReturn } from "./types" import { allModifierInput, joinType, onAction, primaryData } from "./types"
export class Handler { export class Handler {
async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) { async syncDB(db: DB, handler: Handler, deleteInDB: boolean = false) {
@ -237,7 +237,14 @@ export class Handler {
const builder = new QueryBuilder(); const builder = new QueryBuilder();
builder.addCode("select "); builder.addCode("select ");
builder.append(joinArg(", ")(handler, q.attr)); builder.append(joinArg(", ")(handler, q.attr));
builder.addCode(` from ${q.from == null ? 'DUAL' : q.from.serialize(handler)}`); builder.addCode(` from `);
if(q.from == null){
builder.addCode(" DUAL");
}else if (q.from instanceof Table){
builder.addCode(q.from.serialize(handler));
}else{
builder.append(q.from.serialize(handler));
}
if (q.whereD) { if (q.whereD) {
builder.addCode(" where "); builder.addCode(" where ");
builder.append(q.whereD.serialize(handler)); builder.append(q.whereD.serialize(handler));
@ -305,7 +312,7 @@ export class Handler {
} }
return qb; return qb;
}, },
remove: (handler: Handler, q: removeQuery): QueryBuilder =>{ remove: (handler: Handler, q: removeQuery): QueryBuilder => {
const qb = new QueryBuilder(); const qb = new QueryBuilder();
qb.addCode("DELETE FROM "); qb.addCode("DELETE FROM ");
qb.addCode(q.table.serialize(handler)); qb.addCode(q.table.serialize(handler));
@ -527,6 +534,91 @@ export class Handler {
max: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "max(" + a.toString(handler) + ")" }]), max: (handler: Handler, a: Attribute): QueryBuilder => new QueryBuilder([{ data: "max(" + a.toString(handler) + ")" }]),
} }
joins = {
natural: (handler: Handler, j: joinNatural) => {
const qb = new QueryBuilder();
for (let i = 0; i < j.tables.length; i++) {
const t = j.tables[i];
if (t instanceof Table) qb.addCode(t.serialize(handler));
else {
qb.addCode("(");
qb.append(t.serialize(handler));
qb.addCode(")");
}
if (i + 1 < j.tables.length) {
qb.addCode(" natural ");
if (j.type == joinType.left) qb.addCode("left");
if (j.type == joinType.right) qb.addCode("right");
if (j.type == joinType.full) qb.addCode("full");
qb.addCode(" join ");
}
}
return qb;
},
using: (handler: Handler, j: usingJoin) => {
const qb = new QueryBuilder();
if (j.tableA instanceof Table) qb.addCode(j.tableA.serialize(handler));
else {
qb.addCode("(");
qb.append(j.tableA.serialize(handler));
qb.addCode(")");
}
qb.addCode(" ");
if (j.type == joinType.left) qb.addCode("left ");
if (j.type == joinType.right) qb.addCode("right ");
if (j.type == joinType.full) qb.addCode("full ");
qb.addCode("join ");
if (j.tableA instanceof Table) qb.addCode(j.tableA.serialize(handler));
else {
qb.addCode("(");
qb.append(j.tableA.serialize(handler));
qb.addCode(")");
}
qb.addCode(" using (");
qb.addCodeCommaSeperated(j.using.map(t => t.serialize(handler)));
qb.addCode(")");
return qb;
},
on: (handler: Handler, j: onJoin) => {
const qb = new QueryBuilder();
if (j.tableA instanceof Table) qb.addCode(j.tableA.serialize(handler));
else {
qb.addCode("(");
qb.append(j.tableA.serialize(handler));
qb.addCode(")");
}
qb.addCode(" ");
if (j.type == joinType.left) qb.addCode("left ");
if (j.type == joinType.right) qb.addCode("right ");
if (j.type == joinType.full) qb.addCode("full ");
qb.addCode("join ");
if (j.tableA instanceof Table) qb.addCode(j.tableA.serialize(handler));
else {
qb.addCode("(");
qb.append(j.tableA.serialize(handler));
qb.addCode(")");
}
qb.addCode(" on (");
qb.append(j.on.serialize(handler));
qb.addCode(")");
return qb;
},
cross: (handler: Handler, j: joinCross) => {
const qb = new QueryBuilder();
for (let i = 0; i < j.tables.length; i++) {
const t = j.tables[i];
if (t instanceof Table) qb.addCode(t.serialize(handler));
else {
qb.addCode("(");
qb.append(t.serialize(handler));
qb.addCode(")");
}
if (i + 1 < j.tables.length) qb.addCode(" cross join ");
}
return qb;
}
}
modifiers = { modifiers = {
and: joinArg("and"), and: joinArg("and"),
or: joinArg("or"), or: joinArg("or"),

View file

@ -1,7 +1,7 @@
import { Attribute, Table } from "./db"; import { Attribute, Table } from "./db";
import { Aggregation, BooleanModifier, checkConstraint, Datatype, foreignConstraint, NumberModifier, StringModifier, uniqueConstraint } from "./dbStructure"; import { Aggregation, BooleanModifier, checkConstraint, Datatype, foreignConstraint, joinCross, joinNatural, usingJoin, onJoin, NumberModifier, StringModifier, uniqueConstraint } from "./dbStructure";
import { insertQuery, removeQuery, selectQuery, updateQuery } from "./query"; import { insertQuery, removeQuery, selectQuery, updateQuery } from "./query";
import { allModifierInput, selectElements, selectFromElements } from "./types"; import { allModifierInput, joinType, selectElements, selectFromElements } from "./types";
//modifiers //modifiers
export const and = (...args: BooleanModifier[]) => new BooleanModifier("and", args); export const and = (...args: BooleanModifier[]) => new BooleanModifier("and", args);
@ -28,6 +28,25 @@ export const avg = (a: Attribute) => new Aggregation("avg", a);
export const min = (a: Attribute) => new Aggregation("min", a); export const min = (a: Attribute) => new Aggregation("min", a);
export const max = (a: Attribute) => new Aggregation("max", a); export const max = (a: Attribute) => new Aggregation("max", a);
//join
export const crossJoin = (...tables: Table[]) => new joinCross(tables);
export const naturalJoin = (...tables: Table[]) => new joinNatural(tables, joinType.inner);
export const leftNaturalJoin = (...tables: Table[]) => new joinNatural(tables, joinType.left);
export const rightNaturalJoin = (...tables: Table[]) => new joinNatural(tables, joinType.right);
export const fullNaturalJoin = (...tables: Table[]) => new joinNatural(tables, joinType.full);
export const innerJoinUsing = (tableA: Table, tableB: Table, ...using: Attribute[]) => new usingJoin(tableA, tableB, joinType.inner, using);
export const leftJoinUsing = (tableA: Table, tableB: Table, ...using: Attribute[]) => new usingJoin(tableA, tableB, joinType.left, using);
export const rightJoinUsing = (tableA: Table, tableB: Table, ...using: Attribute[]) => new usingJoin(tableA, tableB, joinType.right, using);
export const fullJoinUsing = (tableA: Table, tableB: Table, ...using: Attribute[]) => new usingJoin(tableA, tableB, joinType.full, using);
export const innerJoinOn = (tableA: Table, tableB: Table, on: BooleanModifier) => new onJoin(tableA, tableB, joinType.inner, on);
export const leftJoinOn = (tableA: Table, tableB: Table, on: BooleanModifier) => new onJoin(tableA, tableB, joinType.left, on);
export const rightJoinOn = (tableA: Table, tableB: Table, on: BooleanModifier) => new onJoin(tableA, tableB, joinType.right, on);
export const fullJoinOn = (tableA: Table, tableB: Table, on: BooleanModifier) => new onJoin(tableA, tableB, joinType.full, on);
//query //query
export const select = (args: selectElements[], from: selectFromElements) => new selectQuery(args, from); export const select = (args: selectElements[], from: selectFromElements) => new selectQuery(args, from);
export const insert = (...attrs: Attribute[]) => new insertQuery(attrs); export const insert = (...attrs: Attribute[]) => new insertQuery(attrs);

View file

@ -7,6 +7,7 @@ export type allModifierInput = primaryData | Modifier | selectQuery | Attribute
export type selectElements = primaryData | Attribute | Aggregation | selectQuery export type selectElements = primaryData | Attribute | Aggregation | selectQuery
export type selectFromElements = Table | Joins | null; export type selectFromElements = Table | Joins | null;
export type joinElements = Table | Joins;
export type serializeReturn = [string, primaryData[]]; export type serializeReturn = [string, primaryData[]];
@ -48,3 +49,11 @@ export enum onAction {
setNull, setNull,
setDefault setDefault
} }
export enum joinType {
inner,
left,
right,
full,
cross
}