1
1
mirror of https://github.com/Fabio286/antares.git synced 2025-02-21 06:00:38 +01:00

feat(Firebird SQL): manual commit mode

This commit is contained in:
Fabio Di Stasio 2022-11-10 15:52:31 +01:00
parent 03777a2ea3
commit 27566c1dfa
9 changed files with 97 additions and 75 deletions

View File

@ -90,6 +90,5 @@ export const defaults: Customizations = {
triggerFunctionlanguages: null, triggerFunctionlanguages: null,
parametersLength: false, parametersLength: false,
languages: null, languages: null,
readOnlyMode: false, readOnlyMode: false
blobAsText: false
}; };

View File

@ -90,6 +90,5 @@ export const customizations: Customizations = {
triggerFunctionlanguages: null, triggerFunctionlanguages: null,
parametersLength: false, parametersLength: false,
languages: null, languages: null,
readOnlyMode: false, readOnlyMode: false
blobAsText: true
}; };

View File

@ -78,6 +78,13 @@ export default [
collation: true, collation: true,
unsigned: false, unsigned: false,
zerofill: false zerofill: false
},
{
name: 'BLOB-TEXT',
length: false,
collation: true,
unsigned: false,
zerofill: false
} }
] ]
}, },
@ -86,7 +93,14 @@ export default [
types: [ types: [
{ {
name: 'BLOB', name: 'BLOB',
length: true, length: false,
collation: false,
unsigned: false,
zerofill: false
},
{
name: 'CHAR-BINARY',
length: false,
collation: false, collation: false,
unsigned: false, unsigned: false,
zerofill: false zerofill: false

View File

@ -10,7 +10,8 @@ export const LONG_TEXT = [
'MEDIUMTEXT', 'MEDIUMTEXT',
'LONGTEXT', 'LONGTEXT',
'JSON', 'JSON',
'VARBINARY' 'VARBINARY',
'BLOB-TEXT'
]; ];
export const ARRAY = [ export const ARRAY = [
@ -85,7 +86,8 @@ export const BLOB = [
'MEDIUMBLOB', 'MEDIUMBLOB',
'LONGBLOB', 'LONGBLOB',
'LONG_BLOB', 'LONG_BLOB',
'BYTEA' 'BYTEA',
'CHAR-BINARY'
]; ];
export const BIT = [ export const BIT = [

View File

@ -89,5 +89,4 @@ export interface Customizations {
parametersLength?: boolean; parametersLength?: boolean;
languages?: string[]; languages?: string[];
readOnlyMode?: boolean; readOnlyMode?: boolean;
blobAsText: boolean;
} }

View File

@ -8,11 +8,11 @@ import { FLOAT, NUMBER } from 'common/fieldTypes';
export class FirebirdSQLClient extends AntaresCore { export class FirebirdSQLClient extends AntaresCore {
private _schema?: string; private _schema?: string;
private _runningConnections: Map<string, number>; private _runningConnections: Map<string, number>;
private _connectionsToCommit: Map<string, firebird.Database>; private _connectionsToCommit: Map<string, firebird.Transaction>;
protected _connection?: firebird.Database; protected _connection?: firebird.Database;
_params: firebird.Options; _params: firebird.Options;
private types: {[key: number]: string} ={ private _types: {[key: number]: string} ={
452: 'CHAR', // Array of char 452: 'CHAR', // Array of char
448: 'VARCHAR', 448: 'VARCHAR',
500: 'SMALLINT', 500: 'SMALLINT',
@ -22,7 +22,7 @@ export class FirebirdSQLClient extends AntaresCore {
530: 'DOUBLE PRECISION', 530: 'DOUBLE PRECISION',
510: 'TIMESTAMP', 510: 'TIMESTAMP',
520: 'BLOB', 520: 'BLOB',
540: 'ARRAY', 540: 'VARCHAR', // ARRAY ???
550: 'QUAD', 550: 'QUAD',
560: 'TIME', 560: 'TIME',
570: 'DATE', 570: 'DATE',
@ -38,6 +38,29 @@ export class FirebirdSQLClient extends AntaresCore {
this._connectionsToCommit = new Map(); this._connectionsToCommit = new Map();
} }
private _getType (type: string, subType?: number) {
let fieldType = type.trim();
if ([...NUMBER, ...FLOAT].includes(fieldType)) {
if (subType === 1)
fieldType = 'NUMERIC';
else if (subType === 2)
fieldType = 'DECIMAL';
}
if (fieldType === 'BLOB') {
if (subType === 1)
fieldType = 'BLOB-TEXT';
}
if (fieldType === 'CHAR') {
if (subType === 1)
fieldType = 'CHAR-BINARY';
}
return fieldType;
}
getTypeInfo (type: string): antares.TypeInformations { getTypeInfo (type: string): antares.TypeInformations {
return dataTypes return dataTypes
.reduce((acc, group) => [...acc, ...group.types], []) .reduce((acc, group) => [...acc, ...group.types], [])
@ -170,7 +193,6 @@ export class FirebirdSQLClient extends AntaresCore {
async getTableColumns ({ schema, table }: { schema: string; table: string }) { async getTableColumns ({ schema, table }: { schema: string; table: string }) {
interface TableColumnsResult { interface TableColumnsResult {
DESCRIPTION?: string; DESCRIPTION?: string;
/* eslint-disable camelcase */
FIELD_NAME: string; FIELD_NAME: string;
FIELD_TYPE: string; FIELD_TYPE: string;
FIELD_POSITION: number; FIELD_POSITION: number;
@ -180,10 +202,9 @@ export class FirebirdSQLClient extends AntaresCore {
FIELD_LENGTH: number; FIELD_LENGTH: number;
FIELD_PRECISION: number; FIELD_PRECISION: number;
FIELD_SCALE: number; FIELD_SCALE: number;
/* eslint-enable camelcase */
SUBTYPE: number;
EXTERNAL_TYPE: number; EXTERNAL_TYPE: number;
COLLATION: string; SUBTYPE: number;
COLLATION?: string;
CHARSET: string; CHARSET: string;
} }
@ -209,16 +230,16 @@ export class FirebirdSQLClient extends AntaresCore {
const { rows: fields } = await this.raw<antares.QueryResult<TableColumnsResult>>(` const { rows: fields } = await this.raw<antares.QueryResult<TableColumnsResult>>(`
SELECT SELECT
r.RDB$FIELD_NAME AS field_name, r.RDB$FIELD_NAME AS FIELD_NAME,
r.RDB$DESCRIPTION AS description, r.RDB$DESCRIPTION AS DESCRIPTION,
r.RDB$DEFAULT_VALUE AS default_value, r.RDB$DEFAULT_VALUE AS DEFAULT_VALUE,
r.RDB$NULL_FLAG AS not_null, r.RDB$NULL_FLAG AS NOT_NULL,
r.RDB$FIELD_POSITION AS field_position, r.RDB$FIELD_POSITION AS FIELD_POSITION,
f.RDB$FIELD_LENGTH AS field_length, f.RDB$FIELD_LENGTH AS FIELD_LENGTH,
f.RDB$FIELD_PRECISION AS field_precision, f.RDB$FIELD_PRECISION AS FIELD_PRECISION,
f.RDB$FIELD_SCALE AS field_scale, f.RDB$FIELD_SCALE AS FIELD_SCALE,
f.RDB$EXTERNAL_TYPE AS external_type, f.RDB$EXTERNAL_TYPE AS EXTERNAL_TYPE,
r.RDB$DEFAULT_SOURCE AS default_source, r.RDB$DEFAULT_SOURCE AS DEFAULT_SOURCE,
CASE f.RDB$FIELD_TYPE CASE f.RDB$FIELD_TYPE
WHEN 261 THEN 'BLOB' WHEN 261 THEN 'BLOB'
WHEN 14 THEN 'CHAR' WHEN 14 THEN 'CHAR'
@ -235,10 +256,10 @@ export class FirebirdSQLClient extends AntaresCore {
WHEN 35 THEN 'TIMESTAMP' WHEN 35 THEN 'TIMESTAMP'
WHEN 37 THEN 'VARCHAR' WHEN 37 THEN 'VARCHAR'
ELSE 'UNKNOWN' ELSE 'UNKNOWN'
END AS field_type, END AS FIELD_TYPE,
f.RDB$FIELD_SUB_TYPE AS subtype, f.RDB$FIELD_SUB_TYPE AS SUBTYPE,
-- coll.RDB$COLLATION_NAME AS collation, -- coll.RDB$COLLATION_NAME AS COLLATION,
cset.RDB$CHARACTER_SET_NAME AS charset cset.RDB$CHARACTER_SET_NAME AS CHARSET
FROM RDB$RELATION_FIELDS r FROM RDB$RELATION_FIELDS r
LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME LEFT JOIN RDB$FIELDS f ON r.RDB$FIELD_SOURCE = f.RDB$FIELD_NAME
-- LEFT JOIN RDB$COLLATIONS coll ON f.RDB$COLLATION_ID = coll.RDB$COLLATION_ID -- LEFT JOIN RDB$COLLATIONS coll ON f.RDB$COLLATION_ID = coll.RDB$COLLATION_ID
@ -249,14 +270,7 @@ export class FirebirdSQLClient extends AntaresCore {
return fields.map(field => { return fields.map(field => {
const defaultValue = field.DEFAULT_SOURCE ? field.DEFAULT_SOURCE.replace('DEFAULT ', '') : null; const defaultValue = field.DEFAULT_SOURCE ? field.DEFAULT_SOURCE.replace('DEFAULT ', '') : null;
let fieldType = field.FIELD_TYPE.trim(); const fieldType = this._getType(field.FIELD_TYPE, field.SUBTYPE);
if ([...NUMBER, ...FLOAT].includes(fieldType)) {
if (field.SUBTYPE === 1)
fieldType = 'NUMERIC';
else if (field.SUBTYPE === 2)
fieldType = 'DECIMAL';
}
return { return {
name: field.FIELD_NAME.trim(), name: field.FIELD_NAME.trim(),
@ -625,27 +639,23 @@ export class FirebirdSQLClient extends AntaresCore {
} }
async commitTab (tabUid: string) { async commitTab (tabUid: string) {
// const connection = this._connectionsToCommit.get(tabUid); const connection = this._connectionsToCommit.get(tabUid);
// if (connection) { if (connection) {
// connection.prepare('COMMIT').run(); connection.commit();
// return this.destroyConnectionToCommit(tabUid); return this.destroyConnectionToCommit(tabUid);
// } }
} }
async rollbackTab (tabUid: string) { async rollbackTab (tabUid: string) {
// const connection = this._connectionsToCommit.get(tabUid); const connection = this._connectionsToCommit.get(tabUid);
// if (connection) { if (connection) {
// connection.prepare('ROLLBACK').run(); connection.rollback();
// return this.destroyConnectionToCommit(tabUid); return this.destroyConnectionToCommit(tabUid);
// } }
} }
destroyConnectionToCommit (tabUid: string) { destroyConnectionToCommit (tabUid: string) {
// const connection = this._connectionsToCommit.get(tabUid); this._connectionsToCommit.delete(tabUid);
// if (connection) {
// connection.close();
// this._connectionsToCommit.delete(tabUid);
// }
} }
getSQL () { getSQL () {
@ -737,21 +747,21 @@ export class FirebirdSQLClient extends AntaresCore {
.map(q => q.trim()) .map(q => q.trim())
: [sql]; : [sql];
let connection: firebird.Database; let connection: firebird.Database | firebird.Transaction;
if (!args.autocommit && args.tabUid) { // autocommit OFF if (!args.autocommit && args.tabUid) { // autocommit OFF
if (this._connectionsToCommit.has(args.tabUid)) if (this._connectionsToCommit.has(args.tabUid))
connection = this._connectionsToCommit.get(args.tabUid); connection = this._connectionsToCommit.get(args.tabUid);
else { else {
connection = await this.getConnection(); connection = await this.getConnection();
await new Promise((resolve, reject) => { const transaction = await new Promise<firebird.Transaction>((resolve, reject) => {
connection.query('BEGIN TRANSACTION', [], (err, res) => { (connection as firebird.Database).transaction(firebird.ISOLATION_READ_COMMITED, (err, transaction) => {
if (err) reject(err); if (err) reject(err);
else resolve(res); else resolve(transaction);
}); });
}); });
this._connectionsToCommit.set(args.tabUid, connection); connection = transaction;
this._connectionsToCommit.set(args.tabUid, transaction);
} }
} }
else// autocommit ON else// autocommit ON
@ -821,14 +831,7 @@ export class FirebirdSQLClient extends AntaresCore {
if (fields) { if (fields) {
remappedFields = fields.map(field => { remappedFields = fields.map(field => {
let fieldType = this.types[field.type]; const fieldType = this._getType(this._types[field.type], field.subType);
if ([...NUMBER, ...FLOAT].includes(fieldType)) {
if (field.subType === 1)
fieldType = 'NUMERIC';
else if (field.subType === 2)
fieldType = 'DECIMAL';
}
return { return {
name: field.alias, name: field.alias,

View File

@ -81,7 +81,6 @@
:fields="fieldsObj" :fields="fieldsObj"
:key-usage="keyUsage" :key-usage="keyUsage"
:element-type="elementType" :element-type="elementType"
:blob-as-text="blobAsText"
:class="{'selected': selectedRows.includes(row._antares_id)}" :class="{'selected': selectedRows.includes(row._antares_id)}"
:selected="selectedRows.includes(row._antares_id)" :selected="selectedRows.includes(row._antares_id)"
:selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null" :selected-cell="selectedRows.length === 1 && selectedRows.includes(row._antares_id) ? selectedField : null"
@ -183,7 +182,6 @@ const isEditingRow = ref(false);
const workspaceSchema = computed(() => getWorkspace(props.connUid).breadcrumbs.schema); const workspaceSchema = computed(() => getWorkspace(props.connUid).breadcrumbs.schema);
const workspaceClient = computed(() => getWorkspace(props.connUid).client); const workspaceClient = computed(() => getWorkspace(props.connUid).client);
const blobAsText = computed(() => getWorkspace(props.connUid).customizations.blobAsText);
const primaryField = computed(() => { const primaryField = computed(() => {
const primaryFields = fields.value.filter(field => field.key === 'pri'); const primaryFields = fields.value.filter(field => field.key === 'pri');

View File

@ -243,8 +243,7 @@ const props = defineProps({
itemHeight: Number, itemHeight: Number,
elementType: { type: String, default: 'table' }, elementType: { type: String, default: 'table' },
selected: { type: Boolean, default: false }, selected: { type: Boolean, default: false },
selectedCell: { type: String, default: null }, selectedCell: { type: String, default: null }
blobAsText: { type: Boolean, default: false }
}); });
const emit = defineEmits(['update-field', 'select-row', 'contextmenu', 'start-editing', 'stop-editing']); const emit = defineEmits(['update-field', 'select-row', 'contextmenu', 'start-editing', 'stop-editing']);
@ -319,7 +318,7 @@ const inputProps = computed(() => {
return { type: 'text', mask: datetimeMask }; return { type: 'text', mask: datetimeMask };
} }
if (BLOB.includes(editingType.value) && !props.blobAsText) if (BLOB.includes(editingType.value))
return { type: 'file', mask: false }; return { type: 'file', mask: false };
if (BOOLEAN.includes(editingType.value)) if (BOOLEAN.includes(editingType.value))
@ -399,7 +398,7 @@ const editON = async (field: string) => {
editingField.value = field; editingField.value = field;
editingLength.value = props.fields[field].length; editingLength.value = props.fields[field].length;
if ([...LONG_TEXT, ...ARRAY, ...TEXT_SEARCH].includes(type) || (BLOB.includes(type) && props.blobAsText)) { if ([...LONG_TEXT, ...ARRAY, ...TEXT_SEARCH].includes(type)) {
isTextareaEditor.value = true; isTextareaEditor.value = true;
editingContent.value = typeFormat(content, type); editingContent.value = typeFormat(content, type);
emit('start-editing', field); emit('start-editing', field);
@ -416,7 +415,7 @@ const editON = async (field: string) => {
return; return;
} }
if (BLOB.includes(type) && !props.blobAsText) { if (BLOB.includes(type)) {
isBlobEditor.value = true; isBlobEditor.value = true;
editingContent.value = content || ''; editingContent.value = content || '';
fileToUpload.value = null; fileToUpload.value = null;
@ -455,7 +454,7 @@ const editOFF = () => {
isInlineEditor.value[editingField.value] = false; isInlineEditor.value[editingField.value] = false;
let content; let content;
if (!BLOB.includes(editingType.value) || (BLOB.includes(editingType.value) && props.blobAsText)) { if (!BLOB.includes(editingType.value)) {
if ([...DATETIME, ...TIME].includes(editingType.value)) { if ([...DATETIME, ...TIME].includes(editingType.value)) {
if (editingContent.value !== null && editingContent.value.substring(editingContent.value.length - 1) === '.') if (editingContent.value !== null && editingContent.value.substring(editingContent.value.length - 1) === '.')
editingContent.value = editingContent.value.slice(0, -1); editingContent.value = editingContent.value.slice(0, -1);
@ -589,7 +588,7 @@ const typeFormat = (val: string | number | Date | number[], type: string, precis
return moment(val).isValid() ? moment(val).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`) : val; return moment(val).isValid() ? moment(val).format(`YYYY-MM-DD HH:mm:ss${datePrecision}`) : val;
} }
if (BLOB.includes(type) && !props.blobAsText) { if (BLOB.includes(type)) {
const buff = Buffer.from(val as string); const buff = Buffer.from(val as string);
if (!buff.length) return ''; if (!buff.length) return '';

View File

@ -26,6 +26,8 @@
"macaddr8": $string-color, "macaddr8": $string-color,
"uuid": $string-color, "uuid": $string-color,
"regproc": $string-color, "regproc": $string-color,
"blob-text": $string-color,
"int": $number-color, "int": $number-color,
"tinyint": $number-color, "tinyint": $number-color,
"smallint": $number-color, "smallint": $number-color,
@ -44,6 +46,7 @@
"double_precision": $number-color, "double_precision": $number-color,
"oid": $number-color, "oid": $number-color,
"xid": $number-color, "xid": $number-color,
"money": $number-color, "money": $number-color,
"number": $number-color, "number": $number-color,
"datetime": $date-color, "datetime": $date-color,
@ -54,9 +57,12 @@
"timestamp": $date-color, "timestamp": $date-color,
"timestamp_without_time_zone": $date-color, "timestamp_without_time_zone": $date-color,
"timestamp_with_time_zone": $date-color, "timestamp_with_time_zone": $date-color,
"bit": $bit-color, "bit": $bit-color,
"bit_varying": $bit-color, "bit_varying": $bit-color,
"binary": $blob-color, "binary": $blob-color,
"char-binary": $blob-color,
"varbinary": $blob-color, "varbinary": $blob-color,
"blob": $blob-color, "blob": $blob-color,
"tinyblob": $blob-color, "tinyblob": $blob-color,
@ -65,10 +71,12 @@
"longblob": $blob-color, "longblob": $blob-color,
"long_blob": $blob-color, "long_blob": $blob-color,
"bytea": $blob-color, "bytea": $blob-color,
"enum": $enum-color, "enum": $enum-color,
"set": $enum-color, "set": $enum-color,
"bool": $enum-color, "bool": $enum-color,
"boolean": $enum-color, "boolean": $enum-color,
"interval": $array-color, "interval": $array-color,
"array": $array-color, "array": $array-color,
"anyarray": $array-color, "anyarray": $array-color,
@ -85,6 +93,7 @@
"geomcollection": $array-color, "geomcollection": $array-color,
"geometrycollection": $array-color, "geometrycollection": $array-color,
"aclitem": $array-color, "aclitem": $array-color,
"unknown": $unknown-color, "unknown": $unknown-color,
) )
); );