mirror of https://github.com/Fabio286/antares.git
feat(PostgreSQL): table fields edit
This commit is contained in:
parent
e7401cc96e
commit
e3f259c6e8
|
@ -21,7 +21,7 @@ I'm actively working on it, hoping to provide cool features and fixes as soon as
|
|||
|
||||
Why am I developing an SQL client when there are a lot of them on the market?
|
||||
The main goal is to develop a totally free, full featured, cross platform and open source alternative, empowered by JavaScript's ecosystem.
|
||||
An application created with minimalism and semplicity in mind, with features in the right places, not hundreds of tiny buttons or submenu.
|
||||
A modern application created with minimalism and semplicity in mind, with features in the right places, not hundreds of tiny buttons, tabs or submenu.
|
||||
|
||||
## How to contribute
|
||||
|
||||
|
|
|
@ -37,5 +37,12 @@ module.exports = {
|
|||
indexes: false,
|
||||
foreigns: false,
|
||||
sortableFields: false,
|
||||
zerofill: false
|
||||
unsigned: false,
|
||||
nullable: false,
|
||||
zerofill: false,
|
||||
autoIncrement: false,
|
||||
comment: false,
|
||||
collation: false,
|
||||
arrays: false,
|
||||
onUpdate: false
|
||||
};
|
||||
|
|
|
@ -36,5 +36,11 @@ module.exports = {
|
|||
indexes: true,
|
||||
foreigns: true,
|
||||
sortableFields: true,
|
||||
zerofill: true
|
||||
unsigned: true,
|
||||
nullable: true,
|
||||
zerofill: true,
|
||||
autoIncrement: true,
|
||||
comment: true,
|
||||
collation: true,
|
||||
onUpdate: true
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ module.exports = {
|
|||
schedulers: false,
|
||||
// Settings
|
||||
databaseEdit: false,
|
||||
tableSettings: false,
|
||||
tableSettings: true,
|
||||
viewSettings: false,
|
||||
triggerSettings: false,
|
||||
routineSettings: false,
|
||||
|
@ -27,5 +27,7 @@ module.exports = {
|
|||
schedulerSettings: false,
|
||||
indexes: true,
|
||||
foreigns: true,
|
||||
sortableFields: false
|
||||
sortableFields: false,
|
||||
nullable: true,
|
||||
arrays: true
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ module.exports = [
|
|||
types: [
|
||||
{
|
||||
name: 'TINYINT',
|
||||
length: true,
|
||||
length: 4,
|
||||
collation: false,
|
||||
unsigned: true,
|
||||
zerofill: true
|
||||
|
|
|
@ -4,22 +4,22 @@ module.exports = [
|
|||
types: [
|
||||
{
|
||||
name: 'SMALLINT',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
name: 'INTEGER',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
name: 'BIGINT',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
name: 'DECIMAL',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
|
@ -29,17 +29,17 @@ module.exports = [
|
|||
},
|
||||
{
|
||||
name: 'SMALLSERIAL',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
name: 'SERIAL',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
name: 'BIGSERIAL',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
}
|
||||
]
|
||||
|
@ -49,12 +49,12 @@ module.exports = [
|
|||
types: [
|
||||
{
|
||||
name: 'REAL',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
},
|
||||
{
|
||||
name: 'DOUBLE PRECISION',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
}
|
||||
]
|
||||
|
@ -64,7 +64,7 @@ module.exports = [
|
|||
types: [
|
||||
{
|
||||
name: 'money',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: true
|
||||
}
|
||||
]
|
||||
|
@ -77,14 +77,9 @@ module.exports = [
|
|||
length: true,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
name: 'CHAR',
|
||||
length: false,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
name: 'CHARACTER',
|
||||
length: false,
|
||||
length: true,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
|
@ -109,7 +104,7 @@ module.exports = [
|
|||
types: [
|
||||
{
|
||||
name: 'BYTEA',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: false
|
||||
}
|
||||
]
|
||||
|
@ -129,17 +124,17 @@ module.exports = [
|
|||
},
|
||||
{
|
||||
name: 'DATE',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
name: 'TIME',
|
||||
length: true,
|
||||
name: 'TIME WITHOUT TIME ZONE',
|
||||
length: false,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
name: 'TIME WITH TIME ZONE',
|
||||
length: true,
|
||||
length: false,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
|
@ -229,12 +224,12 @@ module.exports = [
|
|||
types: [
|
||||
{
|
||||
name: 'BIT',
|
||||
length: false,
|
||||
length: true,
|
||||
unsigned: false
|
||||
},
|
||||
{
|
||||
name: 'BIT VARYING',
|
||||
length: false,
|
||||
length: true,
|
||||
unsigned: false
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
'use strict';
|
||||
import pg, { Pool, Client, types } from 'pg';
|
||||
import { Pool, Client, types } from 'pg';
|
||||
import { parse } from 'pgsql-ast-parser';
|
||||
import { AntaresCore } from '../AntaresCore';
|
||||
import dataTypes from 'common/data-types/postgresql';
|
||||
|
@ -8,11 +8,11 @@ function pgToString (value) {
|
|||
return value.toString();
|
||||
}
|
||||
|
||||
pg.types.setTypeParser(1082, pgToString); // date
|
||||
pg.types.setTypeParser(1083, pgToString); // time
|
||||
pg.types.setTypeParser(1114, pgToString); // timestamp
|
||||
pg.types.setTypeParser(1184, pgToString); // timestamptz
|
||||
pg.types.setTypeParser(1266, pgToString); // timetz
|
||||
types.setTypeParser(1082, pgToString); // date
|
||||
types.setTypeParser(1083, pgToString); // time
|
||||
types.setTypeParser(1114, pgToString); // timestamp
|
||||
types.setTypeParser(1184, pgToString); // timestamptz
|
||||
types.setTypeParser(1266, pgToString); // timetz
|
||||
|
||||
export class PostgreSQLClient extends AntaresCore {
|
||||
constructor (args) {
|
||||
|
@ -282,7 +282,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
default: field.column_default,
|
||||
charset: field.character_set_name,
|
||||
collation: field.collation_name,
|
||||
autoIncrement: null,
|
||||
autoIncrement: false,
|
||||
onUpdate: null,
|
||||
comment: ''
|
||||
};
|
||||
|
@ -317,7 +317,10 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
name: row.constraint_name,
|
||||
column: row.column_name,
|
||||
indexType: null,
|
||||
type: row.constraint_type
|
||||
type: row.constraint_type,
|
||||
cardinality: null,
|
||||
comment: '',
|
||||
indexComment: ''
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -359,6 +362,8 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
tc.constraint_name,
|
||||
tc.table_name,
|
||||
kcu.column_name,
|
||||
kcu.position_in_unique_constraint,
|
||||
kcu.ordinal_position,
|
||||
ccu.table_schema AS foreign_table_schema,
|
||||
ccu.table_name AS foreign_table_name,
|
||||
ccu.column_name AS foreign_column_name,
|
||||
|
@ -1020,8 +1025,10 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
options
|
||||
} = params;
|
||||
|
||||
let sql = `ALTER TABLE \`${table}\` `;
|
||||
let sql = '';
|
||||
const alterColumns = [];
|
||||
const renameColumns = [];
|
||||
const createSequences = [];
|
||||
|
||||
// OPTIONS
|
||||
if ('comment' in options) alterColumns.push(`COMMENT='${options.comment}'`);
|
||||
|
@ -1034,7 +1041,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
const typeInfo = this._getTypeInfo(addition.type);
|
||||
const length = typeInfo.length ? addition.numLength || addition.charLength || addition.datePrecision : false;
|
||||
|
||||
alterColumns.push(`ADD COLUMN \`${addition.name}\`
|
||||
alterColumns.push(`ADD COLUMN ${addition.name}
|
||||
${addition.type.toUpperCase()}${length ? `(${length})` : ''}
|
||||
${addition.unsigned ? 'UNSIGNED' : ''}
|
||||
${addition.zerofill ? 'ZEROFILL' : ''}
|
||||
|
@ -1043,8 +1050,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
${addition.default ? `DEFAULT ${addition.default}` : ''}
|
||||
${addition.comment ? `COMMENT '${addition.comment}'` : ''}
|
||||
${addition.collation ? `COLLATE ${addition.collation}` : ''}
|
||||
${addition.onUpdate ? `ON UPDATE ${addition.onUpdate}` : ''}
|
||||
${addition.after ? `AFTER \`${addition.after}\`` : 'FIRST'}`);
|
||||
${addition.onUpdate ? `ON UPDATE ${addition.onUpdate}` : ''}`);
|
||||
});
|
||||
|
||||
// ADD INDEX
|
||||
|
@ -1071,18 +1077,33 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
changes.forEach(change => {
|
||||
const typeInfo = this._getTypeInfo(change.type);
|
||||
const length = typeInfo.length ? change.numLength || change.charLength || change.datePrecision : false;
|
||||
let localType;
|
||||
|
||||
alterColumns.push(`CHANGE COLUMN \`${change.orgName}\` \`${change.name}\`
|
||||
${change.type.toUpperCase()}${length ? `(${length})` : ''}
|
||||
${change.unsigned ? 'UNSIGNED' : ''}
|
||||
${change.zerofill ? 'ZEROFILL' : ''}
|
||||
${change.nullable ? 'NULL' : 'NOT NULL'}
|
||||
${change.autoIncrement ? 'AUTO_INCREMENT' : ''}
|
||||
${change.default ? `DEFAULT ${change.default}` : ''}
|
||||
${change.comment ? `COMMENT '${change.comment}'` : ''}
|
||||
${change.collation ? `COLLATE ${change.collation}` : ''}
|
||||
${change.onUpdate ? `ON UPDATE ${change.onUpdate}` : ''}
|
||||
${change.after ? `AFTER \`${change.after}\`` : 'FIRST'}`);
|
||||
switch (change.type) {
|
||||
case 'SERIAL':
|
||||
localType = 'integer';
|
||||
break;
|
||||
case 'SMALLSERIAL':
|
||||
localType = 'smallint';
|
||||
break;
|
||||
case 'BIGSERIAL':
|
||||
localType = 'bigint';
|
||||
break;
|
||||
default:
|
||||
localType = change.type.toLowerCase();
|
||||
}
|
||||
|
||||
alterColumns.push(`ALTER COLUMN "${change.orgName}" TYPE ${localType}${length ? `(${length})` : ''} USING "${change.orgName}"::${localType}`);
|
||||
alterColumns.push(`ALTER COLUMN "${change.orgName}" ${change.nullable ? 'DROP NOT NULL' : 'SET NOT NULL'}`);
|
||||
alterColumns.push(`ALTER COLUMN "${change.orgName}" ${change.default ? `SET DEFAULT ${change.default}` : 'DROP DEFAULT'}`);
|
||||
if (['SERIAL', 'SMALLSERIAL', 'BIGSERIAL'].includes(change.type)) {
|
||||
const sequenceName = `${table}_${change.name}_seq`.replace(' ', '_');
|
||||
createSequences.push(`CREATE SEQUENCE IF NOT EXISTS ${sequenceName} OWNED BY "${table}"."${change.orgName}"`);
|
||||
alterColumns.push(`ALTER COLUMN "${change.orgName}" SET DEFAULT nextval('${sequenceName}')`);
|
||||
}
|
||||
|
||||
if (change.orgName !== change.name)
|
||||
renameColumns.push(`ALTER TABLE "${table}" RENAME COLUMN "${change.orgName}" TO "${change.name}"`);
|
||||
});
|
||||
|
||||
// CHANGE INDEX
|
||||
|
@ -1113,7 +1134,7 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
|
||||
// DROP FIELDS
|
||||
deletions.forEach(deletion => {
|
||||
alterColumns.push(`DROP COLUMN \`${deletion.name}\``);
|
||||
alterColumns.push(`DROP COLUMN ${deletion.name}`);
|
||||
});
|
||||
|
||||
// DROP INDEX
|
||||
|
@ -1129,10 +1150,12 @@ export class PostgreSQLClient extends AntaresCore {
|
|||
alterColumns.push(`DROP FOREIGN KEY \`${deletion.constraintName}\``);
|
||||
});
|
||||
|
||||
sql += alterColumns.join(', ');
|
||||
if (alterColumns.length) sql += `ALTER TABLE "${table}" ${alterColumns.join(', ')}; `;
|
||||
|
||||
// RENAME
|
||||
if (options.name) sql += `; RENAME TABLE \`${table}\` TO \`${options.name}\``;
|
||||
if (renameColumns.length) sql += `${renameColumns.join(';')}; `;
|
||||
if (createSequences.length) sql = `${createSequences.join(';')}; ${sql}`;
|
||||
if (options.name) sql += `ALTER TABLE "${table}" RENAME TO "${options.name}"; `;
|
||||
|
||||
return await this.raw(sql);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div v-if="workspace.customizations.comment" class="form-group">
|
||||
<label class="form-label col-4">
|
||||
{{ $t('word.comment') }}
|
||||
</label>
|
||||
|
@ -38,7 +38,7 @@
|
|||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div v-if="workspace.customizations.autoIncrement" class="form-group">
|
||||
<label class="form-label col-4">
|
||||
{{ $t('word.autoIncrement') }}
|
||||
</label>
|
||||
|
@ -50,7 +50,7 @@
|
|||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div v-if="workspace.customizations.collations" class="form-group">
|
||||
<label class="form-label col-4">
|
||||
{{ $t('word.collation') }}
|
||||
</label>
|
||||
|
@ -66,7 +66,7 @@
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div v-if="workspace.customizations.engines" class="form-group">
|
||||
<label class="form-label col-4">
|
||||
{{ $t('word.engine') }}
|
||||
</label>
|
||||
|
|
|
@ -433,11 +433,11 @@ export default {
|
|||
_id: uidGen(),
|
||||
name: `${this.$tc('word.field', 1)}_${++this.newFieldsCounter}`,
|
||||
key: '',
|
||||
type: 'int',
|
||||
type: this.workspace.dataTypes[0].types[0].name,
|
||||
schema: this.schema,
|
||||
table: this.table,
|
||||
numPrecision: null,
|
||||
numLength: 11,
|
||||
numLength: this.workspace.dataTypes[0].types[0].length,
|
||||
datePrecision: null,
|
||||
charLength: null,
|
||||
nullable: false,
|
||||
|
|
|
@ -49,21 +49,21 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="th">
|
||||
<div v-if="customizations.unsigned" class="th">
|
||||
<div class="column-resizable">
|
||||
<div class="table-column-title">
|
||||
{{ $t('word.unsigned') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="th">
|
||||
<div v-if="customizations.nullable" class="th">
|
||||
<div class="column-resizable">
|
||||
<div class="table-column-title">
|
||||
{{ $t('message.allowNull') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="th">
|
||||
<div v-if="customizations.zerofill" class="th">
|
||||
<div class="column-resizable">
|
||||
<div class="table-column-title">
|
||||
{{ $t('message.zeroFill') }}
|
||||
|
@ -77,14 +77,14 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="th">
|
||||
<div v-if="customizations.comment" class="th">
|
||||
<div class="column-resizable">
|
||||
<div class="table-column-title">
|
||||
{{ $t('word.comment') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="th">
|
||||
<div v-if="customizations.collation" class="th">
|
||||
<div class="column-resizable min-100">
|
||||
<div class="table-column-title">
|
||||
{{ $t('word.collation') }}
|
||||
|
@ -106,6 +106,7 @@
|
|||
:indexes="getIndexes(row.name)"
|
||||
:foreigns="getForeigns(row.name)"
|
||||
:data-types="dataTypes"
|
||||
:customizations="customizations"
|
||||
@contextmenu="contextMenu"
|
||||
/>
|
||||
</draggable>
|
||||
|
@ -154,6 +155,9 @@ export default {
|
|||
workspaceSchema () {
|
||||
return this.getWorkspace(this.connUid).breadcrumbs.schema;
|
||||
},
|
||||
customizations () {
|
||||
return this.getWorkspace(this.connUid).customizations;
|
||||
},
|
||||
dataTypes () {
|
||||
return this.getWorkspace(this.connUid).dataTypes;
|
||||
},
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div class="tr" @contextmenu.prevent="$emit('contextmenu', $event, localRow._id)">
|
||||
<div class="td" tabindex="0">
|
||||
<div class="row-draggable">
|
||||
<i class="mdi mdi-drag-horizontal row-draggable-icon" />
|
||||
<div :class="customizations.sortableFields ? 'row-draggable' : 'text-center'">
|
||||
<i v-if="customizations.sortableFields" class="mdi mdi-drag-horizontal row-draggable-icon" />
|
||||
{{ localRow.order }}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -96,7 +96,11 @@
|
|||
>
|
||||
</template>
|
||||
</div>
|
||||
<div class="td" tabindex="0">
|
||||
<div
|
||||
v-if="customizations.unsigned"
|
||||
class="td"
|
||||
tabindex="0"
|
||||
>
|
||||
<label class="form-checkbox">
|
||||
<input
|
||||
v-model="localRow.unsigned"
|
||||
|
@ -106,7 +110,11 @@
|
|||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="td" tabindex="0">
|
||||
<div
|
||||
v-if="customizations.nullable"
|
||||
class="td"
|
||||
tabindex="0"
|
||||
>
|
||||
<label class="form-checkbox">
|
||||
<input
|
||||
v-model="localRow.nullable"
|
||||
|
@ -116,7 +124,11 @@
|
|||
<i class="form-icon" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="td" tabindex="0">
|
||||
<div
|
||||
v-if="customizations.zerofill"
|
||||
class="td"
|
||||
tabindex="0"
|
||||
>
|
||||
<label class="form-checkbox">
|
||||
<input
|
||||
v-model="localRow.zerofill"
|
||||
|
@ -131,7 +143,11 @@
|
|||
{{ fieldDefault }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="td type-varchar" tabindex="0">
|
||||
<div
|
||||
v-if="customizations.comment"
|
||||
class="td type-varchar"
|
||||
tabindex="0"
|
||||
>
|
||||
<span
|
||||
v-if="!isInlineEditor.comment"
|
||||
class="cell-content"
|
||||
|
@ -149,7 +165,11 @@
|
|||
@blur="editOFF"
|
||||
>
|
||||
</div>
|
||||
<div class="td" tabindex="0">
|
||||
<div
|
||||
v-if="customizations.collation"
|
||||
class="td"
|
||||
tabindex="0"
|
||||
>
|
||||
<template v-if="fieldType.collation">
|
||||
<span
|
||||
v-if="!isInlineEditor.collation"
|
||||
|
@ -220,7 +240,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div v-if="customizations.nullable" class="mb-2">
|
||||
<label class="form-radio form-inline">
|
||||
<input
|
||||
v-model="defaultValue.type"
|
||||
|
@ -230,7 +250,7 @@
|
|||
><i class="form-icon" /> NULL
|
||||
</label>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<div v-if="customizations.autoIncrement" class="mb-2">
|
||||
<label class="form-radio form-inline">
|
||||
<input
|
||||
v-model="defaultValue.type"
|
||||
|
@ -261,7 +281,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div v-if="customizations.onUpdate">
|
||||
<div class="form-group">
|
||||
<label class="form-label col-4">
|
||||
{{ $t('message.onUpdate') }}
|
||||
|
@ -294,7 +314,8 @@ export default {
|
|||
row: Object,
|
||||
dataTypes: Array,
|
||||
indexes: Array,
|
||||
foreigns: Array
|
||||
foreigns: Array,
|
||||
customizations: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue