awSQL/lib/Tables.js
2024-12-07 02:42:25 +01:00

747 lines
31 KiB
JavaScript

const { throwTypeError, throwRangeError } = require("./Errors");
/**
* Prepares a new alteration of a table
*/
class AlterTable {
#instance;
#database;
#name;
#structure;
constructor(instance, defaultDatabase, name){
this.#instance = instance;
this.#database = defaultDatabase;
this.#name = name;
}
/**
* Selects a database for this query
* @param {String} database - Name of the database
* @returns {this}
*/
selectDatabase(database){
if (!database) throw new Error("database must not be empty");
if (typeof database !== "string") throwTypeError("string", database);
this.#database = database;
return this;
}
/**
* The new desired structure.
* - Drops columns that are existing in the current table but not in this structure
* - Adds columns that are missing in the current table
* - Modifies all other columns where at least one datatype is not matching
* @param {Structure} struc - New structure for the table
* @returns {this}
*/
structure(struc){
if (!struc) throw new Error("struc must not be empty");
if (typeof struc !== "function") throwTypeError("function", struc);
this.#structure = struc;
return this;
}
/**
* Executes the prepared querry
* @returns {Any}
*/
async execute(){
if (!this.#database) throw new Error(`Can't alter table ${this.#name}: Database not selected`);
if (!this.#name) throw new Error(`Can't alter table on ${this.#database}: No name given`);
if (!this.#instance.isConnected()) throw new Error(`Can't execute query: Instance has no connection`);
if (!this.#structure) throw new Error(`Can't alter table ${this.#database}.${this.#name}: No new structure given`);
const currentStruc = (await this.#instance.getStructure(this.#name, this.#database)).get();
const newStruc = this.#structure.get();
if (currentStruc.length===0) throw new Error(`Can't alter table ${this.#name}: Table does not exist`);
for (let col of currentStruc){
if (!newStruc.find(newCol => newCol.Field === col.Field)){
// DELETE COLUMN
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} DROP COLUMN \`${col.Field}\``);
}
}
for (let col of newStruc){
const oldStrucCol = currentStruc.find((oldCol) => oldCol.Field === col.Field);
if (!oldStrucCol){
// ADD COLUMN
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} ADD COLUMN \`${col.Field}\` ${col.Type}${col.Extra?` ${col.Extra}`:""}${col.Null==="YES"?" NULL":" NOT NULL"}${col.Default?` DEFAULT '${col.Default}'`:""}`);
if (col.Key){
switch(col.Key){
case "PRI":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} ADD PRIMARY KEY (${col.Field});`);
break;
case "MUL":
console.log("HEY");
await this.#instance.queryRaw(`CREATE INDEX ${col.Field} ON ${this.#database}.${this.#name} (${col.Field})`);
break;
case "UNI":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} ADD UNIQUE (${col.Field});`);
break;
}
}
continue;
}
for (let key in col){
if (oldStrucCol[key] !== col[key]){
console.log(oldStrucCol[key], col[key]);
// UPDATE COLUMN
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} MODIFY COLUMN \`${col.Field}\` ${col.Type}${col.Extra?` ${col.Extra}`:""}${col.Null==="YES"?" NULL":" NOT NULL"}${col.Default?` DEFAULT '${col.Default}'`:""}`);
if (oldStrucCol.Key){
switch(oldStrucCol.Key){
case "PRI":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} DROP PRIMARY KEY;`);
break;
case "MUL":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} DROP INDEX ${col.Field};`);
break;
case "UNI":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} DROP UNIQUE (${col.Field});`);
break;
}
}
if (col.Key){
switch(col.Key){
case "PRI":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} ADD PRIMARY KEY (${col.Field});`);
break;
case "MUL":
await this.#instance.queryRaw(`CREATE INDEX ${col.Field} ON ${this.#database}.${this.#name} (${col.Field})`);
break;
case "UNI":
await this.#instance.queryRaw(`ALTER TABLE ${this.#database}.${this.#name} ADD UNIQUE (${col.Field});`);
break;
}
}
break;
}
}
}
return await this.#instance.checkStructure(this.#name, newStruc, this.#database);
}
}
/**
* Prepares creation of a new table
*/
class CreateTable {
#instance;
#database;
#name;
#structure;
constructor(instance, defaultDatabase, name) {
this.#instance = instance;
this.#database = defaultDatabase;
this.#name = name;
}
/**
* Selects a database for this query
* @param {String} database - Name of the database
* @returns {this}
*/
selectDatabase(database){
if (!database) throw new Error("database must not be empty");
if (typeof database !== "string") throwTypeError("string", database);
this.#database = database;
return this;
}
/**
* Sets a new name
* @param {String} name
* @returns {this}
*/
name(name){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
this.#name = name;
return this;
}
/**
* Defines the structure for the table
* @param {Structure} struc - Instance of Structure
* @returns {this}
*/
structure(struc){
if (!struc) throw new Error("struc must not be empty");
if (typeof struc !== "function") throwTypeError("function", struc);
this.#structure = struc;
return this;
}
/**
* Executes the prepared querry
* @returns {Any}
*/
async execute(){
if (!this.#database) throw new Error(`Can't create table ${this.#name}: Database not selected`);
if (!this.#name) throw new Error(`Can't create table on ${this.#database}: No name given`);
if (!this.#instance.isConnected()) throw new Error(`Can't execute query: Instance has no connection`);
if (!this.#structure) throw new Error(`Can't create table ${this.#database}.${this.#name}: No structure given`);
const colObjs = this.#structure.get();
const coltypes = colObjs.map(obj => `\`${obj.Field}\` ${obj.Type}${obj.Null==="YES"?" NULL":" NOT NULL"}${obj.Default?` DEFAULT '${obj.Default}'`:""}${obj.Extra?` ${obj.Extra}`:""}`);
const constraints = colObjs.map(obj => `${obj.Key?obj.Key==="PRI"?` PRIMARY KEY (${obj.Field})`:obj.Key==="MUL"?` INDEX (${obj.Field})`:obj.Key==="UNI"?` UNIQUE (${obj.Key})`:"":""}`)
.filter(str => str !== ""); // Filter out empty
const queryString = `CREATE TABLE ${this.#database}.${this.#name} (${coltypes}${constraints.length>0?",":""}${constraints})`;
return await this.#instance.queryRaw(queryString);
}
}
/**
* @typedef {Object} ConstraintOptions
* @property {Boolean} [primary] - Whether this column should be primary
* @property {Boolean} [index] - Whether this column should be indexable (Faster query, slower insertion)
* @property {Boolean} [null] - Whether this column is null per default
* @property {Boolean} [unique] - Whether this column data should be unique
* @property {String} [default] - Set's the default data for this column
* @property {Boolean} [auto_increment] - Whether this column should be numerical auto_increment
* @property {Boolean} [unsigned] - Only on numerical: Whether this numerical field should be unsigned
*/
/**
* Creates a new table-structure
*/
class Structure {
#columns = [];
constructor(tableDescription) {
if (!tableDescription) return;
this.#columns = tableDescription;
}
/**
* Drops (Removes) a column name
* @param {String} name - The name of the column
* @returns {this}
*/
drop(name){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
let index;
for (let i = 0; i < this.#columns.length; i++){
if (this.#columns[i].Field === name) {
index=i;
break;
}
}
this.#columns.splice(index, 1);
return this;
}
/**
* Returns the columns
* @returns {Array<ColumnStructure>}
*/
get(){
return this.#columns;
}
/**
* Adds a new column of data type 'char' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Length of characters. Min 0, Max 255. Default 1
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
char(name, size=1, options={}){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 0 || size > 255){
throwRangeError(0, 255, size);
}
this.#columns.push(parseColumnData(name, `char(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'varchar' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Length of characters. Min 0, Max 255. Default 1
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
varchar(name, size=8, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 0 || size > 255){
throwRangeError(0, 255, size);
}
this.#columns.push(parseColumnData(name, `varchar(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'binary' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Length of data. Min 1
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
binary(name, size=1, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1){
throwRangeError(1, "*", size);
}
this.#columns.push(parseColumnData(name, `binary(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'varbinary' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Length of data. Min 1
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
varbinary(name, size=1, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1){
throwRangeError(1, "*", size);
}
this.#columns.push(parseColumnData(name, `varbinary(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'tinyblob' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
tinyblob(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `tinyblob`, options));
return this;
}
/**
* Adds a new column of data type 'tinytext' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
tinytext(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `tinytext`, options));
return this;
}
/**
* Adds a new column of data type 'text' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
text(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `text`, options));
return this;
}
/**
* Adds a new column of data type 'blob' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Size in bytes. Min 1, Max 65535. Defaults to 65535
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
blob(name, size=65535, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 65535) throwRangeError(1, 65535, size);
this.#columns.push(parseColumnData(name, `blob(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'mediumtext' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
mediumtext(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `mediumtext`, options));
return this;
}
/**
* Adds a new column of data type 'longtext' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
longtext(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `longtext`, options));
return this;
}
/**
* Adds a new column of data type 'longblob' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
longblob(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `longblob`, options));
return this;
}
/**
* Adds a new column of data type 'enum' to this structure
* @param {String} name - Name of the column
* @param {Array<String>} vals - Array of possible values
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
enum(name, vals=[], options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (!Array.isArray(vals)) throwTypeError("array", vals);
if (vals.length===0) throw new Error("vals must not be empty");
if (typeof options !== "object") throwTypeError("object", options);
if (!Array.isArray(vals)) throw new Error(`Column datatype 'enum': 'vals' must be of type Array`);
if (vals.length<=0) throw new Error(`Column datatype 'enum' must contain a list of possible values. Received undefined`);
this.#columns.push(parseColumnData(name, `enum(${vals.map(val=>`'${val}'`)})`, options));
return this;
}
/**
* Adds a new column of data type 'enum' to this structure
* @param {String} name - Name of the column
* @param {Array<String>} vals - Array of possible values
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
set(name, vals=[], options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (!Array.isArray(vals)) throwTypeError("array", vals);
if (vals.length===0) throw new Error("vals must not be empty");
if (typeof options !== "object") throwTypeError("object", options);
if (!Array.isArray(vals)) throw new Error(`Column datatype 'set': 'vals' must be of type Array`);
if (vals.length<=0) throw new Error(`Column datatype 'set' must contain a list of possible values. Received undefined`);
this.#columns.push(parseColumnData(name, `set(${vals.map(val=>`'${val}'`)})`, options));
return this;
}
/**
* Adds a new column of data type 'bit' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Min 1, Max 64. Default to 1
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
bit(name, size=1, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 64) throwRangeError(1, 64, size);
this.#columns.push(parseColumnData(name, `bit(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'tinyint' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Min 1, Max 255. Defaults to 255
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
tinyint(name, size=255, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 255) throwRangeError(1, 255, size);
this.#columns.push(parseColumnData(name, `tinyint(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'bool' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
bool(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `bool`, options));
return this;
}
/**
* Adds a new column of data type 'smallint' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] Min 1, Max 255. Defaults to 255
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
smallint(name, size=255, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 255) throwRangeError(1, 255, size);
this.#columns.push(parseColumnData(name, `smallint(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'mediumint' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] Min 1, Max 255. Defaults to 255
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
mediumint(name, size=255, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 255) throwRangeError(1, 255, size);
this.#columns.push(parseColumnData(name, `mediumint(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'int' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] Min 1, Max 255. Defaults to 255
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
int(name, size=255, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 255) throwRangeError(1, 255, size);
this.#columns.push(parseColumnData(name, `int(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'bigint' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] Min 1, Max 255. Defaults to 255
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
bigint(name, size=255, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 255) throwRangeError(1, 255, size);
this.#columns.push(parseColumnData(name, `bigint(${size})`, options));
return this;
}
/**
* Adds a new column of data type 'float' to this structure
* @param {String} name - Name of the column
* @param {Number} [p] - Precision. Min 1, Max 53. Defaults to 25
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
float(name, p=25, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof p !== "number") throwTypeError("number", p);
if (typeof options !== "object") throwTypeError("object", options);
if (p < 1 || p > 53) throwRangeError(1, 53, p);
this.#columns.push(parseColumnData(name, `float(${p})`, options));
return this;
}
/**
* Adds a new column of data type 'double' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Min 1. Defaults to 16
* @param {Number} [d] - Double precision. Min 1. Defaults to 8
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
double(name, size=16, d=8, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof d !== "number") throwTypeError("number", d);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1) throwRangeError(1, "*", size);
if (d < 1) throwRangeError(1, "*", d);
this.#columns.push(parseColumnData(name, `double(${size},${d})`, options));
return this;
}
/**
* Adds a new column of data type 'decimal' to this structure
* @param {String} name - Name of the column
* @param {Number} [size] - Min 1, Max 65. Defaults to 10
* @param {Number} [d] - Double precision. Min 0. Defaults to 0.
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
decimal(name, size=10, d=0, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof size !== "number") throwTypeError("number", size);
if (typeof d !== "number") throwTypeError("number", d);
if (typeof options !== "object") throwTypeError("object", options);
if (size < 1 || size > 65) throwRangeError(1, 65, size);
if (d < 0) throwRangeError(0, "*", d);
this.#columns.push(parseColumnData(name, `decimal(${size},${d})`, options));
return this;
}
/**
* Adds a new column of data type 'date' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
date(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `date`, options));
return this;
}
/**
* Adds a new column of data type 'datetime' to this structure
* @param {String} name - Name of the column
* @param {Number} [fsp] - Fractional second precision. Min 0, Max 6. Defaults to 0
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
datetime(name, fsp=0, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof fsp !== "number") throwTypeError("number", fsp);
if (typeof options !== "object") throwTypeError("object", options);
if (fsp < 0 || fsp > 6) throwRangeError(0, 6, fsp);
this.#columns.push(parseColumnData(name, `datetime(${fsp})`, options));
return this;
}
/**
* Adds a new column of data type 'timestamp' to this structure
* @param {String} name - Name of the column
* @param {Number} [fsp] - Fractional second precision. Min 0, Max 6. Defaults to 0
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
timestamp(name, fsp=0, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof fsp !== "number") throwTypeError("number", fsp);
if (typeof options !== "object") throwTypeError("object", options);
if (fsp < 0 || fsp > 6) throwRangeError(0, 6, fsp);
this.#columns.push(parseColumnData(name, `timestamp(${fsp})`, options));
return this;
}
/**
* Adds a new column of data type 'time' to this structure
* @param {String} name - Name of the column
* @param {Number} [fsp] - Fractional second precision. Min 0, Max 6. Defaults to 0
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
time(name, fsp=0, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof fsp !== "number") throwTypeError("number", fsp);
if (typeof options !== "object") throwTypeError("object", options);
if (fsp < 0 || fsp > 6) throwRangeError(0, 6, fsp);
this.#columns.push(parseColumnData(name, `time(${fsp})`, options));
return this;
}
/**
* Adds a new column of data type 'year' to this structure
* @param {String} name - Name of the column
* @param {ConstraintOptions} [options] - Extra constraint options
* @returns {this}
*/
year(name, options){
if (!name) throw new Error("name must not be empty");
if (typeof name !== "string") throwTypeError("string", name);
if (typeof options !== "object") throwTypeError("object", options);
this.#columns.push(parseColumnData(name, `time`, options));
return this;
}
}
/**
* Parses the given column data
* @private
* @param {String} name - Column name
* @param {String} type - Column type
* @param {ConstraintOptions} options
* @returns {ColumnStructure}
*/
function parseColumnData(name, type, options={}){
if (options.primary + options.unique + options.index > 1) throw new Error(`ConstrainError: Only one of 'primary', 'unique' or 'index' allowed`);
return {
Field: name,
Type: `${type}${options.unsigned?" unsigned":""}`,
Null: options.null?"YES":"NO",
Key: options.primary?"PRI":options.index?"MUL":options.unique?"UNI":"",
Default: options.default?options.default:null,
Extra: options.auto_increment?"auto_increment":""
}
}
/**
* @typedef {Object} ColumnStructure
* @property {String} Field - Column name
* @property {String} Type - Column type
* @property {"YES"|"NO"} Null - Whether the column allows null-values
* @property {""|"PRI"|"MUL"|"UNI"} Key - PRI = Primary, MUL = Indexed, UNI = Unique
* @property {String|null} Default - Default values for this row
* @property {""|"auto_increment"} Extra - Any extra
*/
module.exports = { CreateTable, Structure, AlterTable }