diff --git a/src/queryKinds/ddl/table/Alter.test.ts b/src/queryKinds/ddl/table/Alter.test.ts new file mode 100644 index 0000000..07e5284 --- /dev/null +++ b/src/queryKinds/ddl/table/Alter.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, it } from "vitest"; +import AlterTableQuery from "./Alter.js"; +import Column from "../../../queryUtils/Column.js"; + + +describe('Alter Table Query', () => { + it('should create a basic ALTER TABLE query to add a column', () => { + const query = new AlterTableQuery('users') + .addColumnsToAdd(Column('id', 'INT').primaryKey().notNull()) + .build(); + + expect(query).toEqual([ + 'ALTER TABLE "users" ADD COLUMN id INT;', + 'ALTER TABLE "users" ALTER COLUMN id SET NOT NULL;', + 'ALTER TABLE "users" ADD CONSTRAINT id_pkey PRIMARY KEY (id);', + ]); + }); + + it('should allow to set table name later', () => { + const query = new AlterTableQuery() + .table('products') + .addColumnsToAdd([ + Column('product_id', 'INT').primaryKey().notNull(), + ]) + .build(); + + expect(query).toEqual([ + 'ALTER TABLE "products" ADD COLUMN product_id INT;', + 'ALTER TABLE "products" ALTER COLUMN product_id SET NOT NULL;', + 'ALTER TABLE "products" ADD CONSTRAINT product_id_pkey PRIMARY KEY (product_id);', + ]); + }); + + it('should allow to set columns to add', () => { + const query = new AlterTableQuery('orders') + .setColumnsToAdd([ + Column('order_id', 'INT').primaryKey().notNull(), + Column('order_date', 'DATE').notNull(), + ]) + .build(); + + expect(query).toEqual([ + 'ALTER TABLE "orders" ADD COLUMN order_id INT;', + 'ALTER TABLE "orders" ALTER COLUMN order_id SET NOT NULL;', + 'ALTER TABLE "orders" ADD CONSTRAINT order_id_pkey PRIMARY KEY (order_id);', + 'ALTER TABLE "orders" ADD COLUMN order_date DATE;', + 'ALTER TABLE "orders" ALTER COLUMN order_date SET NOT NULL;', + ]); + }); +}); diff --git a/src/queryKinds/ddl/table/Alter.ts b/src/queryKinds/ddl/table/Alter.ts index 0574657..442cc3f 100644 --- a/src/queryKinds/ddl/table/Alter.ts +++ b/src/queryKinds/ddl/table/Alter.ts @@ -199,13 +199,9 @@ export default class AlterTableQuery extends TableQueryDefinition { * @returns The SQL string representation of the ALTER TABLE query. * @throws Error if the query has not been built yet. */ - public toSQL(): string | string[] { + public toSQL(): string[] { if (this.builtQuery) this.build(); - if (!this.builtQuery) - throw new Error( - "No built query available. Please build the query first.", - ); - return this.builtQuery; + return this.builtQuery as string[]; } /** diff --git a/src/queryKinds/ddl/table/Create.test.ts b/src/queryKinds/ddl/table/Create.test.ts index a385c69..743db36 100644 --- a/src/queryKinds/ddl/table/Create.test.ts +++ b/src/queryKinds/ddl/table/Create.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest"; import CreateTableQuery from "./Create.js"; import Column from "../../../queryUtils/Column.js"; import { Decimal, Varchar } from "../../../types/ColumnTypes.js"; +import QueryKind from "../../../types/QueryKind.js"; describe('Create Table Query', () => { @@ -101,4 +102,68 @@ describe('Create Table Query', () => { const query = new CreateTableQuery('empty_table'); expect(() => query.build()).toThrow('No columns defined for the table.'); }); + + it('should reset the query state', () => { + const query = new CreateTableQuery('temp_table') + .ifNotExists() + .addColumns([ + Column('id', 'INT').primaryKey().notNull() + ]); + + query.reset(); + + expect(() => query.build()).toThrow('Table name is not set.'); + }); + + it('should return toSQL correctly', () => { + const query = new CreateTableQuery('logs') + .addColumns(Column('id', 'INT').primaryKey().notNull()) + .addColumns(Column('message', Varchar(255)).notNull()); + + expect(query.toSQL()).toBe( + 'CREATE TABLE "logs" (\n id INT PRIMARY KEY,\n message VARCHAR(255) NOT NULL\n);' + ); + }); + + it('should be able to handle setting columns', () => { + const query = new CreateTableQuery('employees') + .setColumns([ + Column('id', 'INT').primaryKey().notNull(), + Column('first_name', Varchar(50)).notNull(), + Column('last_name', Varchar(50)).notNull() + ]); + + expect(query.build()).toBe( + 'CREATE TABLE "employees" (\n id INT PRIMARY KEY,\n first_name VARCHAR(50) NOT NULL,\n last_name VARCHAR(50) NOT NULL\n);' + ); + }); + + it('should be able to return its columns array', () => { + const columns = [ + Column('id', 'INT').primaryKey().notNull(), + Column('username', Varchar(50)).notNull() + ]; + const query = new CreateTableQuery('accounts') + .setColumns(columns); + + expect(query.columns).toEqual(columns); + }); + + it('should be able to set the table name later', () => { + const query = new CreateTableQuery() + .table('departments') + .addColumns([ + Column('id', 'INT').primaryKey().notNull(), + Column('dept_name', Varchar(100)).notNull() + ]); + + expect(query.build()).toBe( + 'CREATE TABLE "departments" (\n id INT PRIMARY KEY,\n dept_name VARCHAR(100) NOT NULL\n);' + ); + }); + + it('should return its kind', () => { + const query = new CreateTableQuery('audit'); + expect(query.kind).toBe(QueryKind.CREATE_TABLE); + }); }); diff --git a/src/queryKinds/ddl/table/Create.ts b/src/queryKinds/ddl/table/Create.ts index dea910e..9f712f2 100644 --- a/src/queryKinds/ddl/table/Create.ts +++ b/src/queryKinds/ddl/table/Create.ts @@ -17,7 +17,7 @@ export default class CreateTableQuery extends TableQueryDefinition { this.tableName = tableName ? SqlEscaper.escapeTableName(tableName, this.flavor) : ""; - this.tableColumns = columns ?? []; + this.tableColumns = columns; } /** @@ -98,7 +98,7 @@ export default class CreateTableQuery extends TableQueryDefinition { this.tableName = ""; this.tableColumns = []; this.builtQuery = null; - this.ifNotExistsFlag = false; + this.resetIfNotExists(); return this; } @@ -107,7 +107,8 @@ export default class CreateTableQuery extends TableQueryDefinition { * @returns The SQL string representation of the CREATE TABLE query. */ public toSQL(): string { - return this.build(); + if(!this.builtQuery) this.build(); + return this.builtQuery as string; } /** diff --git a/src/queryKinds/ddl/table/Drop.test.ts b/src/queryKinds/ddl/table/Drop.test.ts new file mode 100644 index 0000000..79875cb --- /dev/null +++ b/src/queryKinds/ddl/table/Drop.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from "vitest"; +import DropTableQuery from "./Drop.js"; +import QueryKind from "../../../types/QueryKind.js"; + +describe('Drop Table Query', () => { + it('should create a basic DROP TABLE query', () => { + const query = new DropTableQuery('users').build(); + expect(query).toBe('DROP TABLE "users";'); + }); + + it('should be able to set table name later', () => { + const query = new DropTableQuery().table('products').build(); + expect(query).toBe('DROP TABLE "products";'); + }); + + it('should throw if table name is not provided', () => { + const query = new DropTableQuery(); + expect(() => query.build()).toThrow('Table name is required to build DROP TABLE query.'); + }); + + it('should create a DROP TABLE query with IF EXISTS', () => { + const query = new DropTableQuery('users').ifExists().build(); + expect(query).toBe('DROP TABLE IF EXISTS "users";'); + }); + + it('should clone the DropTableQuery instance', () => { + const original = new DropTableQuery('orders').ifExists(); + const cloned = original.clone(); + expect(cloned).not.toBe(original); + expect(cloned.build()).toBe(original.build()); + }); + + it('should reset the DropTableQuery instance', () => { + const query = new DropTableQuery('customers').ifExists(); + query.reset(); + expect(() => query.build()).toThrow('Table name is required to build DROP TABLE query.'); + }); + + it('should return the correct SQL string representation', () => { + const query = new DropTableQuery('employees').ifExists(); + expect(query.toSQL()).toBe('DROP TABLE IF EXISTS "employees";'); + }); + + it('should return kind as DROP_TABLE', () => { + const query = new DropTableQuery('departments'); + expect(query.kind).toBe(QueryKind.DROP_TABLE); + }); +}); diff --git a/src/queryKinds/ddl/table/Drop.ts b/src/queryKinds/ddl/table/Drop.ts index fe29cbd..f1a13ff 100644 --- a/src/queryKinds/ddl/table/Drop.ts +++ b/src/queryKinds/ddl/table/Drop.ts @@ -15,6 +15,11 @@ export default class DropTableQuery extends TableQueryDefinition { : ""; } + public ifExists(): this { + this.ifNotExistsFlag = true; + return this; + } + /** * Builds the DROP TABLE SQL query string. * @param _deepAnalysis - Optional boolean to indicate if deep analysis is required (default is false). @@ -39,7 +44,8 @@ export default class DropTableQuery extends TableQueryDefinition { * @returns A new DropTableQuery instance with the same properties as the current instance. */ public clone(): DropTableQuery { - const cloned = new DropTableQuery(this.tableName); + const cloned = new DropTableQuery(); + cloned.tableName = this.tableName; cloned.flavor = this.flavor; cloned.ifNotExistsFlag = this.ifNotExistsFlag; return cloned; @@ -53,7 +59,7 @@ export default class DropTableQuery extends TableQueryDefinition { public reset(): this { this.tableName = ""; this.builtQuery = null; - this.ifNotExistsFlag = false; + this.resetIfNotExists(); return this; } @@ -62,7 +68,8 @@ export default class DropTableQuery extends TableQueryDefinition { * @returns The SQL string representation of the DROP TABLE query. */ public toSQL(): string { - return this.build(); + if(!this.builtQuery) this.build(); + return this.builtQuery as string; } /** Getter for the kind of query. */