747 lines
31 KiB
JavaScript
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 } |