mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-17 22:36:01 +00:00
Implement base64 encoding for binary data in SQL dumper and modify row handling in MySQL and MSSQL drivers
This commit is contained in:
@@ -79,7 +79,12 @@ export class SqlDumper implements AlterProcessor {
|
|||||||
else if (_isDate(value)) this.putStringValue(new Date(value).toISOString());
|
else if (_isDate(value)) this.putStringValue(new Date(value).toISOString());
|
||||||
else if (value?.type == 'Buffer' && _isArray(value?.data)) this.putByteArrayValue(value?.data);
|
else if (value?.type == 'Buffer' && _isArray(value?.data)) this.putByteArrayValue(value?.data);
|
||||||
else if (value?.$binary?.base64) {
|
else if (value?.$binary?.base64) {
|
||||||
this.putByteArrayValue(Array.from(Buffer.from(value.$binary.base64, 'base64')));
|
const binary = atob(value.$binary.base64);
|
||||||
|
const bytes = new Array(binary.length);
|
||||||
|
for (let i = 0; i < binary.length; i++) {
|
||||||
|
bytes[i] = binary.charCodeAt(i);
|
||||||
|
}
|
||||||
|
this.putByteArrayValue(bytes);
|
||||||
}
|
}
|
||||||
else if (value?.$bigint) this.putRaw(value?.$bigint);
|
else if (value?.$bigint) this.putRaw(value?.$bigint);
|
||||||
else if (_isPlainObject(value) || _isArray(value)) this.putStringValue(JSON.stringify(value));
|
else if (_isPlainObject(value) || _isArray(value)) this.putStringValue(JSON.stringify(value));
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ export function base64ToHex(base64String) {
|
|||||||
return '0x' + hexString.toUpperCase();
|
return '0x' + hexString.toUpperCase();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function hexToBase64(hexString) {
|
||||||
|
const binaryString = hexString.match(/.{1,2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join('');
|
||||||
|
return btoa(binaryString);
|
||||||
|
}
|
||||||
|
|
||||||
export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) {
|
export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) {
|
||||||
if (!_isString(value)) return value;
|
if (!_isString(value)) return value;
|
||||||
|
|
||||||
@@ -62,9 +67,10 @@ export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) {
|
|||||||
const mHex = value.match(/^0x([0-9a-fA-F][0-9a-fA-F])+$/);
|
const mHex = value.match(/^0x([0-9a-fA-F][0-9a-fA-F])+$/);
|
||||||
if (mHex) {
|
if (mHex) {
|
||||||
return {
|
return {
|
||||||
type: 'Buffer',
|
$binary: {
|
||||||
data: hexStringToArray(value.substring(2)),
|
base64: hexToBase64(value.substring(2))
|
||||||
};
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,10 +252,11 @@ export function stringifyCellValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (editorTypes?.parseHexAsBuffer) {
|
if (editorTypes?.parseHexAsBuffer) {
|
||||||
if (value?.type == 'Buffer' && _isArray(value.data)) {
|
// if (value?.type == 'Buffer' && _isArray(value.data)) {
|
||||||
return { value: '0x' + arrayToHexString(value.data), gridStyle: 'valueCellStyle' };
|
// return { value: '0x' + arrayToHexString(value.data), gridStyle: 'valueCellStyle' };
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editorTypes?.parseObjectIdAsDollar) {
|
if (editorTypes?.parseObjectIdAsDollar) {
|
||||||
if (value?.$oid) {
|
if (value?.$oid) {
|
||||||
switch (intent) {
|
switch (intent) {
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ function extractTediousColumns(columns, addDriverNativeColumn = false) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function modifyRow(row, columns) {
|
||||||
|
columns.forEach((col) => {
|
||||||
|
if (Buffer.isBuffer(row[col.columnName])) {
|
||||||
|
row[col.columnName] = { $binary: { base64: Buffer.from(row[col.columnName]).toString('base64') } };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
async function getDefaultAzureSqlToken() {
|
async function getDefaultAzureSqlToken() {
|
||||||
const credential = new ManagedIdentityCredential();
|
const credential = new ManagedIdentityCredential();
|
||||||
const tokenResponse = await credential.getToken('https://database.windows.net/.default');
|
const tokenResponse = await credential.getToken('https://database.windows.net/.default');
|
||||||
@@ -121,9 +130,12 @@ async function tediousQueryCore(dbhan, sql, options) {
|
|||||||
});
|
});
|
||||||
request.on('row', function (columns) {
|
request.on('row', function (columns) {
|
||||||
result.rows.push(
|
result.rows.push(
|
||||||
_.zipObject(
|
modifyRow(
|
||||||
result.columns.map(x => x.columnName),
|
_.zipObject(
|
||||||
columns.map(x => x.value)
|
result.columns.map(x => x.columnName),
|
||||||
|
columns.map(x => x.value)
|
||||||
|
),
|
||||||
|
result.columns
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -148,13 +160,17 @@ async function tediousReadQuery(dbhan, sql, structure) {
|
|||||||
currentColumns = extractTediousColumns(columns);
|
currentColumns = extractTediousColumns(columns);
|
||||||
pass.write({
|
pass.write({
|
||||||
__isStreamHeader: true,
|
__isStreamHeader: true,
|
||||||
|
engine: 'mssql@dbgate-plugin-mssql',
|
||||||
...(structure || { columns: currentColumns }),
|
...(structure || { columns: currentColumns }),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
request.on('row', function (columns) {
|
request.on('row', function (columns) {
|
||||||
const row = _.zipObject(
|
const row = modifyRow(
|
||||||
currentColumns.map(x => x.columnName),
|
_.zipObject(
|
||||||
columns.map(x => x.value)
|
currentColumns.map(x => x.columnName),
|
||||||
|
columns.map(x => x.value)
|
||||||
|
),
|
||||||
|
currentColumns
|
||||||
);
|
);
|
||||||
pass.write(row);
|
pass.write(row);
|
||||||
});
|
});
|
||||||
@@ -204,12 +220,15 @@ async function tediousStream(dbhan, sql, options) {
|
|||||||
});
|
});
|
||||||
request.on('columnMetadata', function (columns) {
|
request.on('columnMetadata', function (columns) {
|
||||||
currentColumns = extractTediousColumns(columns);
|
currentColumns = extractTediousColumns(columns);
|
||||||
options.recordset(currentColumns);
|
options.recordset(currentColumns, { engine: 'mssql@dbgate-plugin-mssql' });
|
||||||
});
|
});
|
||||||
request.on('row', function (columns) {
|
request.on('row', function (columns) {
|
||||||
const row = _.zipObject(
|
const row = modifyRow(
|
||||||
currentColumns.map(x => x.columnName),
|
_.zipObject(
|
||||||
columns.map(x => x.value)
|
currentColumns.map(x => x.columnName),
|
||||||
|
columns.map(x => x.value)
|
||||||
|
),
|
||||||
|
currentColumns
|
||||||
);
|
);
|
||||||
options.row(row);
|
options.row(row);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function extractColumns(fields) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function transformRow(row, columns) {
|
function modifyRow(row, columns) {
|
||||||
columns.forEach((col) => {
|
columns.forEach((col) => {
|
||||||
if (Buffer.isBuffer(row[col.columnName])) {
|
if (Buffer.isBuffer(row[col.columnName])) {
|
||||||
row[col.columnName] = { $binary: { base64: Buffer.from(row[col.columnName]).toString('base64') } };
|
row[col.columnName] = { $binary: { base64: Buffer.from(row[col.columnName]).toString('base64') } };
|
||||||
@@ -106,7 +106,7 @@ const drivers = driverBases.map(driverBase => ({
|
|||||||
dbhan.client.query(sql, function (error, results, fields) {
|
dbhan.client.query(sql, function (error, results, fields) {
|
||||||
if (error) reject(error);
|
if (error) reject(error);
|
||||||
const columns = extractColumns(fields);
|
const columns = extractColumns(fields);
|
||||||
resolve({ rows: results && columns && results.map && results.map(row => transformRow(zipDataRow(row, columns), columns)), columns });
|
resolve({ rows: results && columns && results.map && results.map(row => modifyRow(zipDataRow(row, columns), columns)), columns });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -139,7 +139,7 @@ const drivers = driverBases.map(driverBase => ({
|
|||||||
options.recordset(columns, { engine: driverBase.engine });
|
options.recordset(columns, { engine: driverBase.engine });
|
||||||
} else {
|
} else {
|
||||||
if (columns) {
|
if (columns) {
|
||||||
options.row(transformRow(zipDataRow(row, columns), columns));
|
options.row(modifyRow(zipDataRow(row, columns), columns));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -184,7 +184,7 @@ const drivers = driverBases.map(driverBase => ({
|
|||||||
...(structure || { columns }),
|
...(structure || { columns }),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.on('result', row => pass.write(transformRow(zipDataRow(row, columns), columns)))
|
.on('result', row => pass.write(modifyRow(zipDataRow(row, columns), columns)))
|
||||||
.on('end', () => pass.end());
|
.on('end', () => pass.end());
|
||||||
|
|
||||||
return pass;
|
return pass;
|
||||||
|
|||||||
Reference in New Issue
Block a user