linxus fs fixes
This commit is contained in:
parent
ac23b70146
commit
0b7846fe67
292 changed files with 41947 additions and 41947 deletions
|
|
@ -1,268 +1,268 @@
|
|||
import type { QueryResultRow } from 'pg';
|
||||
import type { PostgreSQLClient } from './client';
|
||||
import type { WhereCondition, JoinCondition, OrderByCondition, QueryResult } from './types';
|
||||
|
||||
/**
|
||||
* PostgreSQL Query Builder
|
||||
*
|
||||
* Provides a fluent interface for building SQL queries
|
||||
*/
|
||||
export class PostgreSQLQueryBuilder {
|
||||
private queryType: 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | null = null;
|
||||
private selectColumns: string[] = [];
|
||||
private fromTable: string = '';
|
||||
private joins: JoinCondition[] = [];
|
||||
private whereConditions: WhereCondition[] = [];
|
||||
private groupByColumns: string[] = [];
|
||||
private havingConditions: WhereCondition[] = [];
|
||||
private orderByConditions: OrderByCondition[] = [];
|
||||
private limitCount: number | null = null;
|
||||
private offsetCount: number | null = null;
|
||||
private insertValues: Record<string, any> = {};
|
||||
private updateValues: Record<string, any> = {};
|
||||
|
||||
private readonly client: PostgreSQLClient;
|
||||
|
||||
constructor(client: PostgreSQLClient) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT statement
|
||||
*/
|
||||
select(columns: string | string[] = '*'): this {
|
||||
this.queryType = 'SELECT';
|
||||
this.selectColumns = Array.isArray(columns) ? columns : [columns];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* FROM clause
|
||||
*/
|
||||
from(table: string): this {
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* JOIN clause
|
||||
*/
|
||||
join(table: string, on: string, type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL' = 'INNER'): this {
|
||||
this.joins.push({ type, table, on });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* WHERE clause
|
||||
*/
|
||||
where(column: string, operator: string, value?: any): this {
|
||||
this.whereConditions.push({ column, operator: operator as any, value });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* GROUP BY clause
|
||||
*/
|
||||
groupBy(columns: string | string[]): this {
|
||||
this.groupByColumns = Array.isArray(columns) ? columns : [columns];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* ORDER BY clause
|
||||
*/
|
||||
orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): this {
|
||||
this.orderByConditions.push({ column, direction });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LIMIT clause
|
||||
*/
|
||||
limit(count: number): this {
|
||||
this.limitCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* OFFSET clause
|
||||
*/
|
||||
offset(count: number): this {
|
||||
this.offsetCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* INSERT statement
|
||||
*/
|
||||
insert(table: string): this {
|
||||
this.queryType = 'INSERT';
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* VALUES for INSERT
|
||||
*/
|
||||
values(data: Record<string, any>): this {
|
||||
this.insertValues = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* UPDATE statement
|
||||
*/
|
||||
update(table: string): this {
|
||||
this.queryType = 'UPDATE';
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SET for UPDATE
|
||||
*/
|
||||
set(data: Record<string, any>): this {
|
||||
this.updateValues = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE statement
|
||||
*/
|
||||
delete(table: string): this {
|
||||
this.queryType = 'DELETE';
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and execute the query
|
||||
*/
|
||||
async execute<T extends QueryResultRow = any>(): Promise<QueryResult<T>> {
|
||||
const { sql, params } = this.build();
|
||||
return await this.client.query<T>(sql, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the SQL query
|
||||
*/
|
||||
build(): { sql: string; params: any[] } {
|
||||
const params: any[] = [];
|
||||
let sql = '';
|
||||
|
||||
switch (this.queryType) {
|
||||
case 'SELECT':
|
||||
sql = this.buildSelectQuery(params);
|
||||
break;
|
||||
case 'INSERT':
|
||||
sql = this.buildInsertQuery(params);
|
||||
break;
|
||||
case 'UPDATE':
|
||||
sql = this.buildUpdateQuery(params);
|
||||
break;
|
||||
case 'DELETE':
|
||||
sql = this.buildDeleteQuery(params);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Query type not specified');
|
||||
}
|
||||
|
||||
return { sql, params };
|
||||
}
|
||||
|
||||
private buildSelectQuery(params: any[]): string {
|
||||
let sql = `SELECT ${this.selectColumns.join(', ')}`;
|
||||
|
||||
if (this.fromTable) {
|
||||
sql += ` FROM ${this.fromTable}`;
|
||||
}
|
||||
|
||||
// Add JOINs
|
||||
for (const join of this.joins) {
|
||||
sql += ` ${join.type} JOIN ${join.table} ON ${join.on}`;
|
||||
}
|
||||
|
||||
// Add WHERE
|
||||
if (this.whereConditions.length > 0) {
|
||||
sql += ' WHERE ' + this.buildWhereClause(this.whereConditions, params);
|
||||
}
|
||||
|
||||
// Add GROUP BY
|
||||
if (this.groupByColumns.length > 0) {
|
||||
sql += ` GROUP BY ${this.groupByColumns.join(', ')}`;
|
||||
}
|
||||
|
||||
// Add HAVING
|
||||
if (this.havingConditions.length > 0) {
|
||||
sql += ' HAVING ' + this.buildWhereClause(this.havingConditions, params);
|
||||
}
|
||||
|
||||
// Add ORDER BY
|
||||
if (this.orderByConditions.length > 0) {
|
||||
const orderBy = this.orderByConditions
|
||||
.map(order => `${order.column} ${order.direction}`)
|
||||
.join(', ');
|
||||
sql += ` ORDER BY ${orderBy}`;
|
||||
}
|
||||
|
||||
// Add LIMIT
|
||||
if (this.limitCount !== null) {
|
||||
sql += ` LIMIT $${params.length + 1}`;
|
||||
params.push(this.limitCount);
|
||||
}
|
||||
|
||||
// Add OFFSET
|
||||
if (this.offsetCount !== null) {
|
||||
sql += ` OFFSET $${params.length + 1}`;
|
||||
params.push(this.offsetCount);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private buildInsertQuery(params: any[]): string {
|
||||
const columns = Object.keys(this.insertValues);
|
||||
const placeholders = columns.map((_, i) => `$${params.length + i + 1}`);
|
||||
|
||||
params.push(...Object.values(this.insertValues));
|
||||
|
||||
return `INSERT INTO ${this.fromTable} (${columns.join(', ')}) VALUES (${placeholders.join(', ')})`;
|
||||
}
|
||||
|
||||
private buildUpdateQuery(params: any[]): string {
|
||||
const sets = Object.keys(this.updateValues).map((key, i) => {
|
||||
return `${key} = $${params.length + i + 1}`;
|
||||
});
|
||||
|
||||
params.push(...Object.values(this.updateValues));
|
||||
|
||||
let sql = `UPDATE ${this.fromTable} SET ${sets.join(', ')}`;
|
||||
|
||||
if (this.whereConditions.length > 0) {
|
||||
sql += ' WHERE ' + this.buildWhereClause(this.whereConditions, params);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private buildDeleteQuery(params: any[]): string {
|
||||
let sql = `DELETE FROM ${this.fromTable}`;
|
||||
|
||||
if (this.whereConditions.length > 0) {
|
||||
sql += ' WHERE ' + this.buildWhereClause(this.whereConditions, params);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private buildWhereClause(conditions: WhereCondition[], params: any[]): string {
|
||||
return conditions.map(condition => {
|
||||
if (condition.operator === 'IS NULL' || condition.operator === 'IS NOT NULL') {
|
||||
return `${condition.column} ${condition.operator}`;
|
||||
} else {
|
||||
params.push(condition.value);
|
||||
return `${condition.column} ${condition.operator} $${params.length}`;
|
||||
}
|
||||
}).join(' AND ');
|
||||
}
|
||||
}
|
||||
import type { QueryResultRow } from 'pg';
|
||||
import type { PostgreSQLClient } from './client';
|
||||
import type { WhereCondition, JoinCondition, OrderByCondition, QueryResult } from './types';
|
||||
|
||||
/**
|
||||
* PostgreSQL Query Builder
|
||||
*
|
||||
* Provides a fluent interface for building SQL queries
|
||||
*/
|
||||
export class PostgreSQLQueryBuilder {
|
||||
private queryType: 'SELECT' | 'INSERT' | 'UPDATE' | 'DELETE' | null = null;
|
||||
private selectColumns: string[] = [];
|
||||
private fromTable: string = '';
|
||||
private joins: JoinCondition[] = [];
|
||||
private whereConditions: WhereCondition[] = [];
|
||||
private groupByColumns: string[] = [];
|
||||
private havingConditions: WhereCondition[] = [];
|
||||
private orderByConditions: OrderByCondition[] = [];
|
||||
private limitCount: number | null = null;
|
||||
private offsetCount: number | null = null;
|
||||
private insertValues: Record<string, any> = {};
|
||||
private updateValues: Record<string, any> = {};
|
||||
|
||||
private readonly client: PostgreSQLClient;
|
||||
|
||||
constructor(client: PostgreSQLClient) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* SELECT statement
|
||||
*/
|
||||
select(columns: string | string[] = '*'): this {
|
||||
this.queryType = 'SELECT';
|
||||
this.selectColumns = Array.isArray(columns) ? columns : [columns];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* FROM clause
|
||||
*/
|
||||
from(table: string): this {
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* JOIN clause
|
||||
*/
|
||||
join(table: string, on: string, type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL' = 'INNER'): this {
|
||||
this.joins.push({ type, table, on });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* WHERE clause
|
||||
*/
|
||||
where(column: string, operator: string, value?: any): this {
|
||||
this.whereConditions.push({ column, operator: operator as any, value });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* GROUP BY clause
|
||||
*/
|
||||
groupBy(columns: string | string[]): this {
|
||||
this.groupByColumns = Array.isArray(columns) ? columns : [columns];
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* ORDER BY clause
|
||||
*/
|
||||
orderBy(column: string, direction: 'ASC' | 'DESC' = 'ASC'): this {
|
||||
this.orderByConditions.push({ column, direction });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* LIMIT clause
|
||||
*/
|
||||
limit(count: number): this {
|
||||
this.limitCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* OFFSET clause
|
||||
*/
|
||||
offset(count: number): this {
|
||||
this.offsetCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* INSERT statement
|
||||
*/
|
||||
insert(table: string): this {
|
||||
this.queryType = 'INSERT';
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* VALUES for INSERT
|
||||
*/
|
||||
values(data: Record<string, any>): this {
|
||||
this.insertValues = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* UPDATE statement
|
||||
*/
|
||||
update(table: string): this {
|
||||
this.queryType = 'UPDATE';
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* SET for UPDATE
|
||||
*/
|
||||
set(data: Record<string, any>): this {
|
||||
this.updateValues = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE statement
|
||||
*/
|
||||
delete(table: string): this {
|
||||
this.queryType = 'DELETE';
|
||||
this.fromTable = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and execute the query
|
||||
*/
|
||||
async execute<T extends QueryResultRow = any>(): Promise<QueryResult<T>> {
|
||||
const { sql, params } = this.build();
|
||||
return await this.client.query<T>(sql, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the SQL query
|
||||
*/
|
||||
build(): { sql: string; params: any[] } {
|
||||
const params: any[] = [];
|
||||
let sql = '';
|
||||
|
||||
switch (this.queryType) {
|
||||
case 'SELECT':
|
||||
sql = this.buildSelectQuery(params);
|
||||
break;
|
||||
case 'INSERT':
|
||||
sql = this.buildInsertQuery(params);
|
||||
break;
|
||||
case 'UPDATE':
|
||||
sql = this.buildUpdateQuery(params);
|
||||
break;
|
||||
case 'DELETE':
|
||||
sql = this.buildDeleteQuery(params);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Query type not specified');
|
||||
}
|
||||
|
||||
return { sql, params };
|
||||
}
|
||||
|
||||
private buildSelectQuery(params: any[]): string {
|
||||
let sql = `SELECT ${this.selectColumns.join(', ')}`;
|
||||
|
||||
if (this.fromTable) {
|
||||
sql += ` FROM ${this.fromTable}`;
|
||||
}
|
||||
|
||||
// Add JOINs
|
||||
for (const join of this.joins) {
|
||||
sql += ` ${join.type} JOIN ${join.table} ON ${join.on}`;
|
||||
}
|
||||
|
||||
// Add WHERE
|
||||
if (this.whereConditions.length > 0) {
|
||||
sql += ' WHERE ' + this.buildWhereClause(this.whereConditions, params);
|
||||
}
|
||||
|
||||
// Add GROUP BY
|
||||
if (this.groupByColumns.length > 0) {
|
||||
sql += ` GROUP BY ${this.groupByColumns.join(', ')}`;
|
||||
}
|
||||
|
||||
// Add HAVING
|
||||
if (this.havingConditions.length > 0) {
|
||||
sql += ' HAVING ' + this.buildWhereClause(this.havingConditions, params);
|
||||
}
|
||||
|
||||
// Add ORDER BY
|
||||
if (this.orderByConditions.length > 0) {
|
||||
const orderBy = this.orderByConditions
|
||||
.map(order => `${order.column} ${order.direction}`)
|
||||
.join(', ');
|
||||
sql += ` ORDER BY ${orderBy}`;
|
||||
}
|
||||
|
||||
// Add LIMIT
|
||||
if (this.limitCount !== null) {
|
||||
sql += ` LIMIT $${params.length + 1}`;
|
||||
params.push(this.limitCount);
|
||||
}
|
||||
|
||||
// Add OFFSET
|
||||
if (this.offsetCount !== null) {
|
||||
sql += ` OFFSET $${params.length + 1}`;
|
||||
params.push(this.offsetCount);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private buildInsertQuery(params: any[]): string {
|
||||
const columns = Object.keys(this.insertValues);
|
||||
const placeholders = columns.map((_, i) => `$${params.length + i + 1}`);
|
||||
|
||||
params.push(...Object.values(this.insertValues));
|
||||
|
||||
return `INSERT INTO ${this.fromTable} (${columns.join(', ')}) VALUES (${placeholders.join(', ')})`;
|
||||
}
|
||||
|
||||
private buildUpdateQuery(params: any[]): string {
|
||||
const sets = Object.keys(this.updateValues).map((key, i) => {
|
||||
return `${key} = $${params.length + i + 1}`;
|
||||
});
|
||||
|
||||
params.push(...Object.values(this.updateValues));
|
||||
|
||||
let sql = `UPDATE ${this.fromTable} SET ${sets.join(', ')}`;
|
||||
|
||||
if (this.whereConditions.length > 0) {
|
||||
sql += ' WHERE ' + this.buildWhereClause(this.whereConditions, params);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private buildDeleteQuery(params: any[]): string {
|
||||
let sql = `DELETE FROM ${this.fromTable}`;
|
||||
|
||||
if (this.whereConditions.length > 0) {
|
||||
sql += ' WHERE ' + this.buildWhereClause(this.whereConditions, params);
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
private buildWhereClause(conditions: WhereCondition[], params: any[]): string {
|
||||
return conditions.map(condition => {
|
||||
if (condition.operator === 'IS NULL' || condition.operator === 'IS NOT NULL') {
|
||||
return `${condition.column} ${condition.operator}`;
|
||||
} else {
|
||||
params.push(condition.value);
|
||||
return `${condition.column} ${condition.operator} $${params.length}`;
|
||||
}
|
||||
}).join(' AND ');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue