Files
dbgate/plugins/dbgate-plugin-firebird/src/backend/helpers.js

170 lines
4.8 KiB
JavaScript

const { createBulkInsertStreamBase } = require('dbgate-tools');
function getDataTypeString({ dataTypeCode, scale, length, precision }) {
switch (dataTypeCode) {
case 7:
return 'smallint';
case 8:
return 'integer';
case 9:
return 'bigint';
case 10:
return 'float';
case 11:
return 'DOUBLE precision';
case 12:
return 'date';
case 13:
return 'time';
case 14:
return `char(${length})`;
case 16:
return `decimal(${precision}, ${scale})`;
case 27:
return 'double precision';
case 35:
return 'blob';
case 37:
return `varchar(${length})`;
case 261:
return 'cstring';
default:
if (dataTypeCode === null || dataTypeCode === undefined) return 'UNKNOWN';
return `unknown (${dataTypeCode})`;
}
}
const eventMap = {
1: { triggerTiming: 'BEFORE', eventType: 'INSERT' },
2: { triggerTiming: 'AFTER', eventType: 'INSERT' },
3: { triggerTiming: 'BEFORE', eventType: 'UPDATE' },
4: { triggerTiming: 'AFTER', eventType: 'UPDATE' },
5: { triggerTiming: 'BEFORE', eventType: 'DELETE' },
6: { triggerTiming: 'AFTER', eventType: 'DELETE' },
17: { triggerTiming: 'BEFORE', eventType: 'INSERT' }, // OR UPDATE
18: { triggerTiming: 'AFTER', eventType: 'INSERT' }, // OR UPDATE
25: { triggerTiming: 'BEFORE', eventType: 'INSERT' }, // OR DELETE
26: { triggerTiming: 'AFTER', eventType: 'INSERT' }, // OR DELETE
27: { triggerTiming: 'BEFORE', eventType: 'UPDATE' }, // OR DELETE
28: { triggerTiming: 'AFTER', eventType: 'UPDATE' }, // OR DELETE
113: { triggerTiming: 'BEFORE', eventType: 'INSERT' }, // OR UPDATE OR DELETE
114: { triggerTiming: 'AFTER', eventType: 'INSERT' }, // OR UPDATE OR DELETE
8192: { triggerTiming: 'BEFORE EVENT', eventType: null }, // ON CONNECT
8193: { triggerTiming: 'AFTER EVENT', eventType: null }, // ON DISCONNECT
8194: { triggerTiming: 'BEFORE STATEMENT', eventType: null }, // ON TRANSACTION START
8195: { triggerTiming: 'AFTER STATEMENT', eventType: null }, // ON TRANSACTION COMMIT
8196: { triggerTiming: 'AFTER STATEMENT', eventType: null }, // ON TRANSACTION ROLLBACK
};
function getTriggerEventType(triggerType) {
return eventMap[triggerType]?.eventType || null;
}
function getTriggerCreateSql(triggerResult) {
const eventType = getTriggerEventType(triggerResult.TRIGGERTYPE);
const triggerTiming = getTriggerTiming(triggerResult.TRIGGERTYPE);
const body = triggerResult.TRIGGER_BODY_SQL;
const createSql = `CREATE OR ALTER TRIGGER "${triggerResult.pureName}" ${triggerTiming} ${eventType} ON "${triggerResult.tableName}" ${body};`;
return createSql;
}
function getTriggerTiming(triggerType) {
return eventMap[triggerType]?.triggerTiming || null;
}
function getFormattedDefaultValue(defaultValue) {
if (defaultValue === null) return null;
return defaultValue.replace(/^default\s*/i, '');
}
function blobStreamToString(stream, encoding = 'utf8') {
return new Promise((resolve, reject) => {
const chunks = [];
stream.on('data', chunk => {
chunks.push(chunk);
});
stream.on('end', () => {
resolve(Buffer.concat(chunks).toString(encoding));
});
stream.on('error', err => {
reject(err);
});
});
}
async function normalizeRow(row) {
const entries = await Promise.all(
Object.entries(row).map(async ([key, value]) => {
if (value === null || value === undefined) return [key, null];
if (typeof value === 'function') {
const result = await new Promise((resolve, reject) => {
value(async (_err, _name, eventEmitter) => {
try {
const stringValue = await blobStreamToString(eventEmitter, 'utf8');
resolve(stringValue);
} catch (error) {
reject(error);
}
});
});
return [key, result];
}
return [key, value];
})
);
return Object.fromEntries(entries);
}
function transformRow(row) {
return Object.fromEntries(
Object.entries(row).map(([key, value]) => {
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/.test(value)) {
return [key, value.replace('T', ' ')];
}
return [key, value];
})
);
}
function createFirebirdInsertStream(driver, stream, dbhan, name, options) {
const writable = createBulkInsertStreamBase(driver, stream, dbhan, name, options);
writable.addRow = async row => {
const transformedRow = transformRow(row);
if (writable.structure) {
writable.buffer.push(transformedRow);
} else {
writable.structure = transformedRow;
await writable.checkStructure();
}
};
return writable;
}
module.exports = {
getDataTypeString,
getTriggerEventType,
getTriggerTiming,
getFormattedDefaultValue,
getTriggerCreateSql,
blobStreamToString,
normalizeRow,
createFirebirdInsertStream,
};