diff --git a/README.md b/README.md index e04b6f1f..e48fc711 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/common/customizations/defaults.js b/src/common/customizations/defaults.js index b2e6d2e3..89fdd829 100644 --- a/src/common/customizations/defaults.js +++ b/src/common/customizations/defaults.js @@ -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 }; diff --git a/src/common/customizations/mysql.js b/src/common/customizations/mysql.js index 254c4634..049706ab 100644 --- a/src/common/customizations/mysql.js +++ b/src/common/customizations/mysql.js @@ -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 }; diff --git a/src/common/customizations/postgresql.js b/src/common/customizations/postgresql.js index 3b8aefc5..d5d8b7bf 100644 --- a/src/common/customizations/postgresql.js +++ b/src/common/customizations/postgresql.js @@ -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 }; diff --git a/src/common/data-types/mysql.js b/src/common/data-types/mysql.js index 9e62a49c..3e0315ea 100644 --- a/src/common/data-types/mysql.js +++ b/src/common/data-types/mysql.js @@ -4,7 +4,7 @@ module.exports = [ types: [ { name: 'TINYINT', - length: true, + length: 4, collation: false, unsigned: true, zerofill: true diff --git a/src/common/data-types/postgresql.js b/src/common/data-types/postgresql.js index 47a16c00..bfe9e50d 100644 --- a/src/common/data-types/postgresql.js +++ b/src/common/data-types/postgresql.js @@ -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 } ] diff --git a/src/main/libs/clients/PostgreSQLClient.js b/src/main/libs/clients/PostgreSQLClient.js index 0161426b..d2612dff 100644 --- a/src/main/libs/clients/PostgreSQLClient.js +++ b/src/main/libs/clients/PostgreSQLClient.js @@ -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); } diff --git a/src/renderer/components/WorkspacePropsOptionsModal.vue b/src/renderer/components/WorkspacePropsOptionsModal.vue index 79e68ff5..27d7ccf0 100644 --- a/src/renderer/components/WorkspacePropsOptionsModal.vue +++ b/src/renderer/components/WorkspacePropsOptionsModal.vue @@ -26,7 +26,7 @@ > -
+
@@ -38,7 +38,7 @@ >
-
+
@@ -50,7 +50,7 @@ >
-
+
@@ -66,7 +66,7 @@
-
+
diff --git a/src/renderer/components/WorkspacePropsTab.vue b/src/renderer/components/WorkspacePropsTab.vue index 397a15a7..c510cb18 100644 --- a/src/renderer/components/WorkspacePropsTab.vue +++ b/src/renderer/components/WorkspacePropsTab.vue @@ -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, diff --git a/src/renderer/components/WorkspacePropsTable.vue b/src/renderer/components/WorkspacePropsTable.vue index 8709a10a..aff1af7f 100644 --- a/src/renderer/components/WorkspacePropsTable.vue +++ b/src/renderer/components/WorkspacePropsTable.vue @@ -49,21 +49,21 @@
-
+
{{ $t('word.unsigned') }}
-
+
{{ $t('message.allowNull') }}
-
+
{{ $t('message.zeroFill') }} @@ -77,14 +77,14 @@
-
+
{{ $t('word.comment') }}
-
+
{{ $t('word.collation') }} @@ -106,6 +106,7 @@ :indexes="getIndexes(row.name)" :foreigns="getForeigns(row.name)" :data-types="dataTypes" + :customizations="customizations" @contextmenu="contextMenu" /> @@ -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; }, diff --git a/src/renderer/components/WorkspacePropsTableRow.vue b/src/renderer/components/WorkspacePropsTableRow.vue index 80a945a8..60dfe613 100644 --- a/src/renderer/components/WorkspacePropsTableRow.vue +++ b/src/renderer/components/WorkspacePropsTableRow.vue @@ -1,8 +1,8 @@
-
+
-
+
-
+
-
+
-
+