Skip to content

Commit

Permalink
fix(sql): move typedef utils inside driver class (#79)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hieuzest authored Apr 9, 2024
1 parent 7f7a000 commit 037cd6a
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 117 deletions.
112 changes: 56 additions & 56 deletions packages/mysql/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,6 @@ declare module 'mysql' {

const timeRegex = /(\d+):(\d+):(\d+)(\.(\d+))?/

function getIntegerType(length = 4) {
if (length <= 1) return 'tinyint'
if (length <= 2) return 'smallint'
if (length <= 3) return 'mediumint'
if (length <= 4) return 'int'
return 'bigint'
}

function getTypeDef({ deftype: type, length, precision, scale }: Field) {
switch (type) {
case 'float':
case 'double':
case 'date': return type
case 'time': return 'time(3)'
case 'timestamp': return 'datetime(3)'
case 'boolean': return 'bit'
case 'integer':
if ((length || 0) > 8) this.logger.warn(`type ${type}(${length}) exceeds the max supported length`)
return getIntegerType(length)
case 'primary':
case 'unsigned':
if ((length || 0) > 8) this.logger.warn(`type ${type}(${length}) exceeds the max supported length`)
return `${getIntegerType(length)} unsigned`
case 'decimal': return `decimal(${precision ?? 10}, ${scale ?? 0}) unsigned`
case 'char': return `char(${length || 255})`
case 'string': return (length || 255) > 65536 ? 'longtext' : `varchar(${length || 255})`
case 'text': return (length || 255) > 65536 ? 'longtext' : `text(${length || 65535})`
case 'binary': return (length || 65537) > 65536 ? 'longblob' : `blob`
case 'list': return `text(${length || 65535})`
case 'json': return `text(${length || 65535})`
default: throw new Error(`unsupported type: ${type}`)
}
}

function isDefUpdated(field: Field, column: ColumnInfo, def: string) {
const typename = def.split(/[ (]/)[0]
if (typename === 'text') return !column.DATA_TYPE.endsWith('text')
if (typename !== column.DATA_TYPE) return true
switch (field.deftype) {
case 'integer':
case 'unsigned':
case 'char':
case 'string':
return !!field.length && !!column.CHARACTER_MAXIMUM_LENGTH && column.CHARACTER_MAXIMUM_LENGTH !== field.length
case 'decimal':
return column.NUMERIC_PRECISION !== field.precision || column.NUMERIC_SCALE !== field.scale
case 'text':
case 'list':
case 'json':
return false
default: return false
}
}

function createIndex(keys: string | string[]) {
return makeArray(keys).map(escapeId).join(', ')
}
Expand Down Expand Up @@ -200,9 +146,9 @@ export class MySQLDriver extends Driver<MySQLDriver.Config> {
if (key === primary && autoInc) {
def += ' int unsigned not null auto_increment'
} else {
const typedef = getTypeDef(fields[key]!)
const typedef = this.getTypeDef(fields[key]!)
if (column && !shouldUpdate) {
shouldUpdate = isDefUpdated(fields[key]!, column, typedef)
shouldUpdate = this.isDefUpdated(fields[key]!, column, typedef)
}
def += ' ' + typedef
if (makeArray(primary).includes(key)) {
Expand Down Expand Up @@ -528,6 +474,60 @@ INSERT INTO mtt VALUES(json_extract(j, concat('$[', i, ']'))); SET i=i+1; END WH
})
})
}

private getTypeDef({ deftype: type, length, precision, scale }: Field) {
const getIntegerType = (length = 4) => {
if (length <= 1) return 'tinyint'
if (length <= 2) return 'smallint'
if (length <= 3) return 'mediumint'
if (length <= 4) return 'int'
return 'bigint'
}

switch (type) {
case 'float':
case 'double':
case 'date': return type
case 'time': return 'time(3)'
case 'timestamp': return 'datetime(3)'
case 'boolean': return 'bit'
case 'integer':
if ((length || 0) > 8) this.logger.warn(`type ${type}(${length}) exceeds the max supported length`)
return getIntegerType(length)
case 'primary':
case 'unsigned':
if ((length || 0) > 8) this.logger.warn(`type ${type}(${length}) exceeds the max supported length`)
return `${getIntegerType(length)} unsigned`
case 'decimal': return `decimal(${precision ?? 10}, ${scale ?? 0}) unsigned`
case 'char': return `char(${length || 255})`
case 'string': return (length || 255) > 65536 ? 'longtext' : `varchar(${length || 255})`
case 'text': return (length || 255) > 65536 ? 'longtext' : `text(${length || 65535})`
case 'binary': return (length || 65537) > 65536 ? 'longblob' : `blob`
case 'list': return `text(${length || 65535})`
case 'json': return `text(${length || 65535})`
default: throw new Error(`unsupported type: ${type}`)
}
}

private isDefUpdated(field: Field, column: ColumnInfo, def: string) {
const typename = def.split(/[ (]/)[0]
if (typename === 'text') return !column.DATA_TYPE.endsWith('text')
if (typename !== column.DATA_TYPE) return true
switch (field.deftype) {
case 'integer':
case 'unsigned':
case 'char':
case 'string':
return !!field.length && !!column.CHARACTER_MAXIMUM_LENGTH && column.CHARACTER_MAXIMUM_LENGTH !== field.length
case 'decimal':
return column.NUMERIC_PRECISION !== field.precision || column.NUMERIC_SCALE !== field.scale
case 'text':
case 'list':
case 'json':
return false
default: return false
}
}
}

export namespace MySQLDriver {
Expand Down
122 changes: 61 additions & 61 deletions packages/postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,65 +57,6 @@ interface QueryTask {

const timeRegex = /(\d+):(\d+):(\d+)(\.(\d+))?/

function getTypeDef(field: Field & { autoInc?: boolean }) {
let { deftype: type, length, precision, scale, autoInc } = field
switch (type) {
case 'primary':
case 'unsigned':
case 'integer':
length ||= 4
if (precision) return `numeric(${precision}, ${scale ?? 0})`
else if (length <= 2) return autoInc ? 'smallserial' : 'smallint'
else if (length <= 4) return autoInc ? 'serial' : 'integer'
else {
if (length > 8) this.logger.warn(`type ${type}(${length}) exceeds the max supported length`)
return autoInc ? 'bigserial' : 'bigint'
}
case 'decimal': return `numeric(${precision ?? 10}, ${scale ?? 0})`
case 'float': return 'real'
case 'double': return 'double precision'
case 'char': return `varchar(${length || 64}) `
case 'string': return `varchar(${length || 255})`
case 'text': return `text`
case 'boolean': return 'boolean'
case 'list': return 'text[]'
case 'json': return 'jsonb'
case 'date': return 'timestamp with time zone'
case 'time': return 'time with time zone'
case 'timestamp': return 'timestamp with time zone'
case 'binary': return 'bytea'
default: throw new Error(`unsupported type: ${type}`)
}
}

function isDefUpdated(field: Field & { autoInc?: boolean }, column: ColumnInfo, def: string) {
const typename = def.split(/[ (]/)[0]
if (field.autoInc) return false
if (['unsigned', 'integer'].includes(field.deftype!)) {
if (column.data_type !== typename) return true
} else if (typename === 'text[]') {
if (column.data_type !== 'ARRAY') return true
} else if (Field.date.includes(field.deftype!)) {
if (column.data_type !== def) return true
} else if (typename === 'varchar') {
if (column.data_type !== 'character varying') return true
} else if (typename !== column.data_type) return true
switch (field.deftype) {
case 'integer':
case 'unsigned':
case 'char':
case 'string':
return !!field.length && !!column.character_maximum_length && column.character_maximum_length !== field.length
case 'decimal':
return column.numeric_precision !== field.precision || column.numeric_scale !== field.scale
case 'text':
case 'list':
case 'json':
return false
default: return false
}
}

function createIndex(keys: string | string[]) {
return makeArray(keys).map(escapeId).join(', ')
}
Expand Down Expand Up @@ -235,9 +176,9 @@ export class PostgresDriver extends Driver<PostgresDriver.Config> {
const column = columns.find(info => legacy.includes(info.column_name))
let shouldUpdate = column?.column_name !== key
const field = Object.assign({ autoInc: primary.includes(key) && table.autoInc }, fields[key]!)
const typedef = getTypeDef(field)
const typedef = this.getTypeDef(field)
if (column && !shouldUpdate) {
shouldUpdate = isDefUpdated(field, column, typedef)
shouldUpdate = this.isDefUpdated(field, column, typedef)
}

if (!column) {
Expand Down Expand Up @@ -479,6 +420,65 @@ export class PostgresDriver extends Driver<PostgresDriver.Config> {
await conn.unsafe(`COMMIT`)
})
}

private getTypeDef(field: Field & { autoInc?: boolean }) {
let { deftype: type, length, precision, scale, autoInc } = field
switch (type) {
case 'primary':
case 'unsigned':
case 'integer':
length ||= 4
if (precision) return `numeric(${precision}, ${scale ?? 0})`
else if (length <= 2) return autoInc ? 'smallserial' : 'smallint'
else if (length <= 4) return autoInc ? 'serial' : 'integer'
else {
if (length > 8) this.logger.warn(`type ${type}(${length}) exceeds the max supported length`)
return autoInc ? 'bigserial' : 'bigint'
}
case 'decimal': return `numeric(${precision ?? 10}, ${scale ?? 0})`
case 'float': return 'real'
case 'double': return 'double precision'
case 'char': return `varchar(${length || 64}) `
case 'string': return `varchar(${length || 255})`
case 'text': return `text`
case 'boolean': return 'boolean'
case 'list': return 'text[]'
case 'json': return 'jsonb'
case 'date': return 'timestamp with time zone'
case 'time': return 'time with time zone'
case 'timestamp': return 'timestamp with time zone'
case 'binary': return 'bytea'
default: throw new Error(`unsupported type: ${type}`)
}
}

private isDefUpdated(field: Field & { autoInc?: boolean }, column: ColumnInfo, def: string) {
const typename = def.split(/[ (]/)[0]
if (field.autoInc) return false
if (['unsigned', 'integer'].includes(field.deftype!)) {
if (column.data_type !== typename) return true
} else if (typename === 'text[]') {
if (column.data_type !== 'ARRAY') return true
} else if (Field.date.includes(field.deftype!)) {
if (column.data_type !== def) return true
} else if (typename === 'varchar') {
if (column.data_type !== 'character varying') return true
} else if (typename !== column.data_type) return true
switch (field.deftype) {
case 'integer':
case 'unsigned':
case 'char':
case 'string':
return !!field.length && !!column.character_maximum_length && column.character_maximum_length !== field.length
case 'decimal':
return column.numeric_precision !== field.precision || column.numeric_scale !== field.scale
case 'text':
case 'list':
case 'json':
return false
default: return false
}
}
}

export namespace PostgresDriver {
Expand Down

0 comments on commit 037cd6a

Please sign in to comment.