parent
c1e7f750fc
commit
b131cb589e
@ -0,0 +1,30 @@
|
||||
import {Directive} from './Directive.ts'
|
||||
import {Injectable} from '../../../di/src/decorator/Injection.ts'
|
||||
import {CLIService} from '../service/CLI.service.ts'
|
||||
|
||||
@Injectable()
|
||||
export class AboutDirective extends Directive {
|
||||
public readonly keyword = 'about'
|
||||
public readonly help = 'Display information about Daton'
|
||||
|
||||
constructor(
|
||||
protected readonly cli: CLIService,
|
||||
) { super() }
|
||||
|
||||
public async invoke() {
|
||||
if ( this.cli.show_logo() ) {
|
||||
console.log('')
|
||||
console.log(this.cli.get_logo())
|
||||
}
|
||||
|
||||
[
|
||||
'',
|
||||
'Daton is an opinionated application framework written for Deno. It provides a rich library of utilities, an ORM, dependency injector, routing stack, and logic for controllers, models, middleware, and configuration.',
|
||||
'',
|
||||
`Daton was created by and is © ${(new Date).getFullYear()} Garrett Mills. It is licensed for use by the terms of the MIT license.`,
|
||||
'',
|
||||
'Source code: https://code.garrettmills.dev/garrettmills/daton',
|
||||
'',
|
||||
].map(x => console.log(x))
|
||||
}
|
||||
}
|
@ -1,10 +1,47 @@
|
||||
import {Directive} from './Directive.ts'
|
||||
import {CLIService} from "../service/CLI.service.ts";
|
||||
import {Injectable} from "../../../di/src/decorator/Injection.ts";
|
||||
|
||||
@Injectable()
|
||||
export class UsageDirective extends Directive {
|
||||
public readonly keyword = 'help'
|
||||
public readonly help = 'Display usage information'
|
||||
|
||||
constructor(
|
||||
protected readonly cli: CLIService,
|
||||
) { super() }
|
||||
|
||||
public async invoke() {
|
||||
console.log('Hello, from Daton CLI.')
|
||||
console.log('')
|
||||
if ( this.cli.show_logo() ) {
|
||||
console.log(this.cli.get_logo())
|
||||
console.log('')
|
||||
}
|
||||
|
||||
console.log('Welcome to the Daton CLI. This tool can help you interact with your Daton application.\n')
|
||||
console.log('To get started, specify one of the directives below. You can always specify the --help option to get more information about a directive.')
|
||||
console.log('')
|
||||
|
||||
const usages = this.cli.get_directives().map((directive: Directive): string[] => {
|
||||
return [directive.keyword, directive.help]
|
||||
})
|
||||
|
||||
const pad_length = usages.max(grp => grp[0].length) + 2
|
||||
|
||||
const padded_usages = usages.map(grp => {
|
||||
const keyword = grp[0]
|
||||
if ( keyword.length < pad_length ) {
|
||||
const pad = Array(pad_length - keyword.length).fill(' ').join('')
|
||||
return [`${pad}${keyword}`, grp[1]]
|
||||
}
|
||||
|
||||
return grp
|
||||
})
|
||||
|
||||
padded_usages.each(grp => {
|
||||
console.log(`${grp[0]} : ${grp[1]}`)
|
||||
})
|
||||
|
||||
console.log('')
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,156 @@
|
||||
import ConnectionMutable from './ConnectionMutable.ts'
|
||||
import {MalformedSQLGrammarError} from './Select.ts'
|
||||
import {escape, EscapedValue} from "../types.ts";
|
||||
|
||||
/**
|
||||
* Base query builder class for ALTER DATABASE queries.
|
||||
* @extends ConnectionMutable
|
||||
*/
|
||||
export class AlterDatabase<T> extends ConnectionMutable<T> {
|
||||
protected _name?: string
|
||||
protected _rename?: string
|
||||
protected _owner?: string
|
||||
protected _tablespace?: string
|
||||
protected _conn_limit?: number
|
||||
protected _is_template?: boolean
|
||||
protected _allow_connections?: boolean
|
||||
|
||||
protected _reset_all: boolean = false
|
||||
protected _config_resets: string[] = []
|
||||
protected _config_from_current: string[] = []
|
||||
protected _config_sets: (string|EscapedValue)[][] = []
|
||||
|
||||
constructor(name?: string) {
|
||||
super()
|
||||
if ( name ) this._name = name
|
||||
}
|
||||
|
||||
sql(level: number = 0): string {
|
||||
if ( !this._name ) {
|
||||
throw new MalformedSQLGrammarError(`Database name to alter is undefined.`)
|
||||
}
|
||||
|
||||
const queries = []
|
||||
|
||||
const option_pairs: (string|boolean|number)[][] = []
|
||||
if ( typeof this._allow_connections !== 'undefined' ) {
|
||||
option_pairs.push(['ALLOW_CONNECTIONS', this._allow_connections])
|
||||
}
|
||||
|
||||
if ( typeof this._conn_limit !== 'undefined' ) {
|
||||
option_pairs.push(['CONNECTION LIMIT', this._conn_limit])
|
||||
}
|
||||
|
||||
if ( typeof this._is_template !== 'undefined' ) {
|
||||
option_pairs.push(['IS_TEMPLATE', this._is_template])
|
||||
}
|
||||
|
||||
if ( option_pairs.length > 0 ) {
|
||||
option_pairs.some(pair => {
|
||||
queries.push(`ALTER DATABASE ${this._name} WITH ${pair[0]} ${pair[1]}`)
|
||||
})
|
||||
}
|
||||
|
||||
if ( this._owner ) {
|
||||
queries.push(`ALTER DATABASE ${this._name} OWNER TO ${this._owner}`)
|
||||
}
|
||||
|
||||
if ( this._tablespace ) {
|
||||
queries.push(`ALTER DATABASE ${this._name} SET TABLESPACE ${this._tablespace}`)
|
||||
}
|
||||
|
||||
if ( this._reset_all ) {
|
||||
queries.push(`ALTER DATABASE ${this._name} RESET ALL`)
|
||||
}
|
||||
|
||||
if ( this._config_resets.length > 0 ) {
|
||||
this._config_resets.some(param => {
|
||||
queries.push(`ALTER DATABASE ${this._name} RESET ${param}`)
|
||||
})
|
||||
}
|
||||
|
||||
if ( this._config_from_current.length > 0 ) {
|
||||
this._config_from_current.some(param => {
|
||||
queries.push(`ALTER DATABASE ${this._name} SET ${param} FROM CURRENT`)
|
||||
})
|
||||
}
|
||||
|
||||
if ( this._config_sets.length > 0 ) {
|
||||
this._config_sets.some(set => {
|
||||
queries.push(`ALTER DATABASE ${this._name} SET ${set[0]} TO ${escape(set[1])}`)
|
||||
})
|
||||
}
|
||||
|
||||
// This needs to happen last
|
||||
if ( this._rename ) {
|
||||
queries.push(`ALTER DATABASE ${this._name} RENAME TO ${this._rename}`)
|
||||
}
|
||||
|
||||
return queries.join(';\n')
|
||||
}
|
||||
|
||||
name(name: string): this {
|
||||
this._name = name
|
||||
return this
|
||||
}
|
||||
|
||||
rename_to(name: string): this {
|
||||
this._rename = name
|
||||
return this
|
||||
}
|
||||
|
||||
owner(user: string): this {
|
||||
this._owner = user
|
||||
return this
|
||||
}
|
||||
|
||||
tablespace(name: string): this {
|
||||
this._tablespace = name
|
||||
return this
|
||||
}
|
||||
|
||||
connection_limit(max: number): this {
|
||||
this._conn_limit = max
|
||||
return this
|
||||
}
|
||||
|
||||
as_template(): this {
|
||||
this._is_template = true
|
||||
return this
|
||||
}
|
||||
|
||||
not_as_template(): this {
|
||||
this._is_template = false
|
||||
return this
|
||||
}
|
||||
|
||||
disallow_connections(): this {
|
||||
this._allow_connections = false
|
||||
return this
|
||||
}
|
||||
|
||||
allow_connections(): this {
|
||||
this._allow_connections = true
|
||||
return this
|
||||
}
|
||||
|
||||
reset_all(): this {
|
||||
this._reset_all = true
|
||||
return this
|
||||
}
|
||||
|
||||
reset(parameter: string): this {
|
||||
this._config_resets.push(parameter)
|
||||
return this
|
||||
}
|
||||
|
||||
set_from_current(parameter: string): this {
|
||||
this._config_from_current.push(parameter)
|
||||
return this
|
||||
}
|
||||
|
||||
set(parameter: string, value: EscapedValue): this {
|
||||
this._config_sets.push([parameter, value])
|
||||
return this
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
import ConnectionMutable from './ConnectionMutable.ts'
|
||||
import {MalformedSQLGrammarError} from './Select.ts'
|
||||
|
||||
/**
|
||||
* Base query builder class for CREATE DATABASE queries.
|
||||
* @extends ConnectionMutable
|
||||
*/
|
||||
export class CreateDatabase<T> extends ConnectionMutable<T> {
|
||||
protected _name?: string
|
||||
protected _owner?: string
|
||||
protected _template?: string
|
||||
protected _encoding?: string
|
||||
protected _lc_collate?: string
|
||||
protected _lc_ctype?: string
|
||||
protected _tablespace?: string
|
||||
protected _conn_limit?: number
|
||||
protected _is_template?: boolean
|
||||
protected _allow_connections?: boolean
|
||||
|
||||
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(`Database name to create is undefined.`)
|
||||
}
|
||||
|
||||
const key_pairs: (string|number)[][] = []
|
||||
if ( this._owner ) {
|
||||
key_pairs.push(['OWNER', this._owner])
|
||||
}
|
||||
|
||||
if ( this._template ) {
|
||||
key_pairs.push(['TEMPLATE', this._template])
|
||||
}
|
||||
|
||||
if ( this._encoding ) {
|
||||
key_pairs.push(['ENCODING', this._encoding])
|
||||
}
|
||||
|
||||
if ( this._lc_collate ) {
|
||||
key_pairs.push(['LC_COLLATE', this._lc_collate])
|
||||
}
|
||||
|
||||
if ( this._lc_ctype ) {
|
||||
key_pairs.push(['LC_CTYPE', this._lc_ctype])
|
||||
}
|
||||
|
||||
if ( this._tablespace ) {
|
||||
key_pairs.push(['TABLESPACE', this._tablespace])
|
||||
}
|
||||
|
||||
if ( this._conn_limit ) {
|
||||
key_pairs.push(['CONNECTION LIMIT', this._conn_limit])
|
||||
}
|
||||
|
||||
if ( typeof this._allow_connections !== 'undefined' ) {
|
||||
key_pairs.push(['ALLOW_CONNECTIONS', this._allow_connections ? 'TRUE' : 'FALSE'])
|
||||
}
|
||||
|
||||
if ( typeof this._is_template !== 'undefined' ) {
|
||||
key_pairs.push(['IS_TEMPLATE', this._is_template ? 'TRUE' : 'FALSE'])
|
||||
}
|
||||
|
||||
return [
|
||||
`CREATE DATABASE ${this._name}`,
|
||||
...(key_pairs.length < 1 ? [] : [`${indent}WITH`, ...key_pairs.map(x => `${indent}${indent}${x[0]} ${x[1]}`)]),
|
||||
].filter(x => String(x).trim()).join(`\n${indent}`)
|
||||
}
|
||||
|
||||
name(name: string): this {
|
||||
this._name = name
|
||||
return this
|
||||
}
|
||||
|
||||
owner(user: string): this {
|
||||
this._owner = user
|
||||
return this
|
||||
}
|
||||
|
||||
template(name: string): this {
|
||||
this._template = name
|
||||
return this
|
||||
}
|
||||
|
||||
encoding(name: string): this {
|
||||
this._encoding = name
|
||||
return this
|
||||
}
|
||||
|
||||
lc_collate(type: string): this {
|
||||
this._lc_collate = type
|
||||
return this
|
||||
}
|
||||
|
||||
lc_ctype(type: string): this {
|
||||
this._lc_ctype = type
|
||||
return this
|
||||
}
|
||||
|
||||
tablespace(name: string): this {
|
||||
this._tablespace = name
|
||||
return this
|
||||
}
|
||||
|
||||
connection_limit(max: number): this {
|
||||
this._conn_limit = max
|
||||
return this
|
||||
}
|
||||
|
||||
as_template(): this {
|
||||
this._is_template = true
|
||||
return this
|
||||
}
|
||||
|
||||
disallow_connections(): this {
|
||||
this._allow_connections = false
|
||||
return this
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import AppClass from '../../../../lib/src/lifecycle/AppClass.ts'
|
||||
|
||||
export default abstract class Migration extends AppClass {
|
||||
public static get_current_epoch(): number {
|
||||
return (new Date).getTime()
|
||||
}
|
||||
|
||||
public abstract readonly ordering_epoch: number
|
||||
|
||||
public abstract up(): any
|
||||
|
||||
public abstract down(): any
|
||||
|
||||
public should_apply(): any {
|
||||
return true
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import {Model} from '../../model/Model.ts'
|
||||
import {Field} from '../../model/Field.ts'
|
||||
import {Type} from '../../db/types.ts'
|
||||
|
||||
export default class MigrationApply extends Model<MigrationApply> {
|
||||
protected static table = 'daton_migration_applies'
|
||||
protected static key = 'daton_migration_apply_id'
|
||||
|
||||
@Field(Type.serial)
|
||||
public daton_migration_apply_id!: number
|
||||
|
||||
@Field(Type.bigint)
|
||||
public ordering_epoch!: number
|
||||
|
||||
@Field(Type.varchar)
|
||||
public migration_file_name!: string
|
||||
|
||||
@Field(Type.timestamp)
|
||||
public applied_date!: Date
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
import AppClass from '../../../../lib/src/lifecycle/AppClass.ts'
|
||||
import {Connection} from '../../db/Connection.ts'
|
||||
import {Collection} from '../../../../lib/src/collection/Collection.ts'
|
||||
import {Table} from './Table.ts'
|
||||
import {Builder} from '../../builder/Builder.ts'
|
||||
import {Join} from '../../builder/type/join/Join.ts'
|
||||
|
||||
export class Database extends AppClass {
|
||||
private _table_cache?: Collection<Table>
|
||||
protected _rename?: string
|
||||
|
||||
protected _owner?: string
|
||||
protected _owner_override?: string
|
||||
public owner(set?: string) {
|
||||
if ( set ) {
|
||||
this._owner_override = set
|
||||
return this
|
||||
} else {
|
||||
return this._owner_override || this._owner
|
||||
}
|
||||
}
|
||||
|
||||
protected _encoding?: string
|
||||
protected _encoding_override?: string
|
||||
public encoding(set?: string) {
|
||||
if ( set ) {
|
||||
this._encoding_override = set
|
||||
return this
|
||||
} else {
|
||||
return this._encoding_override || this._encoding
|
||||
}
|
||||
}
|
||||
|
||||
protected _lc_collate?: string
|
||||
protected _lc_collate_override?: string
|
||||
public lc_collate(set?: string) {
|
||||
if ( set ) {
|
||||
this._lc_collate_override = set
|
||||
return this
|
||||
} else {
|
||||
return this._lc_collate_override || this._lc_collate
|
||||
}
|
||||
}
|
||||
|
||||
protected _lc_ctype?: string
|
||||
protected _lc_ctype_override?: string
|
||||
public lc_ctype(set?: string) {
|
||||
if ( set ) {
|
||||
this._lc_ctype_override = set
|
||||
return this
|
||||
} else {
|
||||
return this._lc_ctype_override || this._lc_ctype
|
||||
}
|
||||
}
|
||||
|
||||
protected _tablespace?: string
|
||||
protected _tablespace_override?: string
|
||||
public tablespace(set?: string) {
|
||||
if ( set ) {
|
||||
this._tablespace_override = set
|
||||
return this
|
||||
} else {
|
||||
return this._tablespace_override || this._tablespace
|
||||
}
|
||||
}
|
||||
|
||||
protected _is_template?: boolean
|
||||
protected _is_template_override?: boolean
|
||||
public is_template(set?: boolean) {
|
||||
if ( typeof set !== 'undefined' ) {
|
||||
this._is_template_override = set
|
||||
return this
|
||||
} else {
|
||||
return (typeof this._is_template_override !== 'undefined' ? this._is_template_override : this._is_template)
|
||||
}
|
||||
}
|
||||
|
||||
protected _allow_conn?: boolean
|
||||
protected _allow_conn_override?: boolean
|
||||
public allow_conn(set?: boolean) {
|
||||
if ( typeof set !== 'undefined' ) {
|
||||
this._allow_conn_override = set
|
||||
return this
|
||||
} else {
|
||||
return (typeof this._allow_conn_override !== 'undefined' ? this._allow_conn_override : this._allow_conn)
|
||||
}
|
||||
}
|
||||
|
||||
protected _conn_limit?: number
|
||||
protected _conn_limit_override?: number
|
||||
public connection_limit(set?: number) {
|
||||
if ( typeof set !== 'undefined' ) {
|
||||
this._conn_limit_override = set
|
||||
} else {
|
||||
return (typeof this._conn_limit_override !== 'undefined' ? this._conn_limit_override : this._conn_limit)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
public readonly connection: Connection,
|
||||
public readonly name: string,
|
||||
) { super() }
|
||||
|
||||
rename(name: string): this {
|
||||
this._rename = name
|
||||
return this
|
||||
}
|
||||
|
||||
async introspect() {
|
||||
this._table_cache = await this.connection.tables(this.name)
|
||||
this._table_cache.each((table: Table) => table.set_database(this))
|
||||
|
||||
const query = (new Builder).select(
|
||||
'pg_catalog.pg_get_userbyid(db.datdba) AS owner',
|
||||
'pg_encoding_to_char(db.encoding) AS encoding_char',
|
||||
'datcollate',
|
||||
'datctype',
|
||||
'tablespace.spcname AS tablespace',
|
||||
'datistemplate',
|
||||
'datallowconn',
|
||||
'datconnlimit'
|
||||
)
|
||||
.from('pg_catalog.pg_database', 'db')
|
||||
.join('pg_catalog.pg_tablespace', 'tablespace', (join: Join) => {
|
||||
join.whereRaw('db.dattablespace', '=', 'tablespace.oid')
|
||||
})
|
||||
.where('db.datname', '=', this.name)
|
||||
.target_connection(this.connection)
|
||||
|
||||
const info: any = (await query.execute()).rows.first()
|
||||
if ( info ) {
|
||||
this._owner = info.owner
|
||||
this._encoding = info.encoding_char
|
||||
this._lc_collate = info.datcollate
|
||||
this._lc_ctype = info.datctype
|
||||
this._tablespace = info.tablespace
|
||||
this._is_template = info.datistemplate
|
||||
this._allow_conn = info.datallowconn
|
||||
this._conn_limit = info.datconnlimit
|
||||
}
|
||||
}
|
||||
|
||||
async tables(invalidate_cache: boolean = false) {
|
||||
if ( !this._table_cache || invalidate_cache ) {
|
||||
this._table_cache = await this.connection.tables(this.name)
|
||||
this._table_cache.each((table: Table) => table.set_database(this))
|
||||
}
|
||||
|
||||
return this._table_cache
|
||||
}
|
||||
|
||||
async table(name: string, invalidate_cache: boolean = false) {
|
||||
if ( !this._table_cache || invalidate_cache ) {
|
||||
this._table_cache = await this.connection.tables(this.name)
|
||||
this._table_cache.each((table: Table) => table.set_database(this))
|
||||
}
|
||||
|
||||
return this._table_cache.firstWhere('name', '=', name)
|
||||
}
|
||||
|
||||
public is_dirty() {
|
||||
return (
|
||||
(this._owner_override && this._owner_override !== this._owner)
|
||||
|| (this._encoding_override && this._encoding_override !== this._encoding)
|
||||
|| (this._lc_collate_override && this._lc_collate_override !== this._lc_collate)
|
||||
|| (this._lc_ctype_override && this._lc_ctype_override !== this._lc_ctype)
|
||||
|| (this._tablespace_override && this._tablespace_override !== this._tablespace)
|
||||
|| (typeof this._is_template_override !== 'undefined' && this._is_template_override !== this._is_template)
|
||||
|| (typeof this._allow_conn_override !== 'undefined' && this._allow_conn_override !== this._allow_conn)
|
||||
|| (typeof this._conn_limit_override !== 'undefined' && this._conn_limit_override !== this._conn_limit)
|
||||
|| this._rename
|
||||
)
|
||||
}
|
||||
|
||||
public async exists() {
|
||||
return !!(await this.connection.database(this.name))
|
||||
}
|
||||
|
||||
public async save() {
|
||||
if ( await this.exists() ) {
|
||||
const query = (new Builder).alter_database().name(this.name)
|
||||
|
||||
if ( this._owner_override && this._owner_override !== this._owner ) {
|
||||
query.owner(this._owner_override)
|
||||
}
|
||||
|
||||
if ( typeof this._allow_conn_override !== 'undefined' && this._allow_conn_override !== this._allow_conn ) {
|
||||
if ( this._allow_conn_override ) query.allow_connections()
|
||||
else query.disallow_connections()
|
||||
}
|
||||
|
||||
if ( typeof this._conn_limit_override !== 'undefined' && this._conn_limit_override !== this._conn_limit ) {
|
||||
query.connection_limit(this._conn_limit_override)
|
||||
}
|
||||
|
||||
if ( typeof this._is_template_override !== 'undefined' && this._is_template_override !== this._is_template ) {
|
||||
if ( this._is_template_override ) query.as_template()
|
||||
else query.not_as_template()
|
||||
}
|
||||
|
||||
if ( this._rename ) {
|
||||
query.rename_to(this._rename)
|
||||
}
|
||||
|
||||
if ( this._owner_override && this._owner_override !== this._owner ) {
|
||||
query.owner(this._owner_override)
|
||||
}
|
||||
|
||||
if ( this._tablespace_override && this._tablespace_override !== this._tablespace ) {
|
||||
query.tablespace(this._tablespace_override)
|
||||
}
|
||||
|
||||
if ( query.sql().trim().length < 1 ) return
|
||||
|
||||
await query.execute_in_connection(this.connection)
|
||||
} else {
|
||||
const query = (new Builder).create_database()
|
||||
.name(this.name)
|
||||
|
||||
if ( this._owner_override ) query.owner(this._owner_override)
|
||||
if ( this._is_template_override ) query.as_template()
|
||||
if ( this._encoding_override ) query.encoding(this._encoding_override)
|
||||
if ( this._lc_ctype_override ) query.lc_collate(this._lc_ctype_override)
|
||||
if ( this._lc_ctype ) query.lc_ctype(this._lc_ctype)
|
||||
if ( this._tablespace ) query.tablespace(this._tablespace)
|
||||
if ( !this._allow_conn_override && typeof this._allow_conn_override !== 'undefined' ) query.disallow_connections()
|
||||
if ( this._conn_limit_override && typeof this._conn_limit_override !== 'undefined' ) query.connection_limit(this._conn_limit_override)
|
||||
|
||||
await query.execute_in_connection(this.connection)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import AppClass from '../../../../lib/src/lifecycle/AppClass.ts'
|
||||
import {Connection} from "../../db/Connection.ts";
|
||||
import {Database} from "./Database.ts";
|
||||
|
||||
export class Table extends AppClass {
|
||||
protected parent_database?: Database
|
||||
|
||||
constructor(
|
||||
public readonly connection: Connection,
|
||||
public readonly database_name: string,
|
||||
public readonly name: string,
|
||||
) { super() }
|
||||
|
||||
public set_database(db: Database) {
|
||||
this.parent_database = db
|
||||
}
|
||||
}
|
Loading…
Reference in new issue