You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
4.0 KiB

import ConnectionMutable from "./ConnectionMutable.ts";
import {Type} from "../../db/types.ts";
import {Collection} from "../../../../lib/src/collection/Collection.ts";
import {MalformedSQLGrammarError} from "./Select.ts";
export interface ColumnDefinition {
with_name: string,
with_type: Type,
type_size?: string | number,
null: boolean,
as_primary_key: boolean,
with_default?: string,
sql: (level: number) => string,
check_expression?: string,
check_no_inherit: boolean,
}
export class ColumnFluency implements ColumnDefinition {
public with_name: string = ''
public with_type: Type = Type.varchar
public null: boolean = false
public as_primary_key: boolean = false
public with_default?: string
public type_size?: string | number
public check_expression?: string
public check_no_inherit: boolean = false
public clone() {
const col = new ColumnFluency()
col.with_name = this.with_name
col.with_type = this.with_type
col.null = this.null
col.as_primary_key = this.as_primary_key
col.with_default = this.with_default
col.type_size = this.type_size
col.check_expression = this.check_expression
col.check_no_inherit = this.check_no_inherit
return col
}
public name(name: string): this {
this.with_name = name
return this
}
public type(type: Type, size?: string | number): this {
this.with_type = type
if ( size ) this.type_size = size
return this
}
public nullable() {
this.null = true
return this
}
public primary_key() {
this.as_primary_key = true
return this
}
public default(val: string) {
this.with_default = val
}
public check(expression: string, inherit: boolean = true): this {
this.check_expression = expression
this.check_no_inherit = !inherit
return this
}
public sql(level: number = 0): string {
const indent = Array(level).fill(' ').join('')
const parts = []
if ( this.null ) parts.push('NULL')
else parts.push('NOT NULL')
if ( this.as_primary_key ) parts.push('PRIMARY KEY')
if ( this.with_default ) parts.push(`DEFAULT ${this.with_default}`)
if ( this.check_expression ) {
parts.push(`CHECK (${this.check_expression})${this.check_no_inherit ? ' NO INHERIT' : ''}`)
}
return `${indent}${this.with_name} ${this.with_type}${this.type_size ? '('+this.type_size+')' : ''}${parts.length > 0 ? ' '+parts.join(' ') : ''}`
}
}
export type FluencyFunction = (col: ColumnFluency) => any
export class CreateTable<T> extends ConnectionMutable<T> {
protected _name?: string
protected _column_defs: Collection<ColumnDefinition> = new Collection<ColumnDefinition>()
constructor(name?: string) {
super()
if ( name ) this._name = name
}
sql(level: number = 0): string {
const indent = Array(level).fill(' ').join('')
if ( !this._name ) {
throw new MalformedSQLGrammarError(`Missing required table name for create statement.`)
}
const column_sql = this._column_defs.map(x => `${indent}${x.sql(level + 1)}`)
return [
`CREATE TABLE ${this._name} (`,
column_sql.join(`,\n${indent}`),
')'
].filter(x => String(x).trim()).join(`\n${indent}`)
}
name(name: string): this {
this._name = name
return this
}
column(name_or_fluency_fn: string | FluencyFunction, type?: Type, type_size?: string | number): this {
const col = new ColumnFluency()
if ( typeof name_or_fluency_fn === 'string' ) {
if ( !type ) throw new MalformedSQLGrammarError(`Missing type for column: ${name_or_fluency_fn}`)
col.name(name_or_fluency_fn)
.type(type, type_size)
} else {
name_or_fluency_fn(col)
}
this._column_defs.push(col)
return this
}
}