mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-18 05:36:00 +00:00
Connection to MognoDB legacy
This commit is contained in:
@@ -42,6 +42,7 @@
|
||||
"is-promise": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mongodb": "^6.3.0",
|
||||
"mongodb-old": "npm:mongodb@^6.16.0",
|
||||
"@mongosh/browser-runtime-electron": "^3.16.4",
|
||||
"@mongosh/service-provider-node-driver": "^3.10.2"
|
||||
},
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
const _ = require('lodash');
|
||||
const { EventEmitter } = require('events');
|
||||
const stream = require('stream');
|
||||
const driverBase = require('../frontend/driver');
|
||||
const driverBases = require('../frontend/drivers');
|
||||
const Analyser = require('./Analyser');
|
||||
const isPromise = require('is-promise');
|
||||
const { MongoClient, ObjectId, AbstractCursor, Long } = require('mongodb');
|
||||
const mongodb = require('mongodb');
|
||||
const oldmongodb = require('mongodb-old');
|
||||
const { ObjectId } = require('mongodb');
|
||||
// { MongoClient, ObjectId, AbstractCursor, Long }
|
||||
const { EJSON } = require('bson');
|
||||
const { serializeJsTypesForJsonStringify, deserializeJsTypesFromJsonParse, getLogger } = require('dbgate-tools');
|
||||
const createBulkInsertStream = require('./createBulkInsertStream');
|
||||
@@ -18,7 +21,8 @@ let isProApp;
|
||||
|
||||
const logger = getLogger('mongoDriver');
|
||||
|
||||
function serializeMongoData(row) {
|
||||
function serializeMongoData(row, driverBase) {
|
||||
const { Long } = driverBase.useLegacyDriver ? oldmongodb : mongodb;
|
||||
return EJSON.serialize(
|
||||
serializeJsTypesForJsonStringify(row, (value) => {
|
||||
if (value instanceof Long) {
|
||||
@@ -33,10 +37,10 @@ function serializeMongoData(row) {
|
||||
);
|
||||
}
|
||||
|
||||
async function readCursor(cursor, options) {
|
||||
async function readCursor(cursor, options, driverBase) {
|
||||
options.recordset({ __isDynamicStructure: true });
|
||||
await cursor.forEach((row) => {
|
||||
options.row(serializeMongoData(row));
|
||||
options.row(serializeMongoData(row, driverBase));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -86,8 +90,8 @@ async function getScriptableDb(dbhan) {
|
||||
// }
|
||||
// }
|
||||
|
||||
/** @type {import('dbgate-types').EngineDriver<MongoClient, import('mongodb').Db>} */
|
||||
const driver = {
|
||||
/** @type {import('dbgate-types').EngineDriver<import('mongodb').MongoClient, import('mongodb').Db>} */
|
||||
const drivers = driverBases.map((driverBase) => ({
|
||||
...driverBase,
|
||||
analyserClass: Analyser,
|
||||
async connect({ server, port, user, password, database, useDatabaseUrl, databaseUrl, ssl, useSshTunnel }) {
|
||||
@@ -120,6 +124,8 @@ const driver = {
|
||||
options.tlsInsecure = !ssl.rejectUnauthorized;
|
||||
}
|
||||
|
||||
const { MongoClient } = driverBase.useLegacyDriver ? oldmongodb : mongodb;
|
||||
|
||||
const client = new MongoClient(mongoUrl, options);
|
||||
await client.connect();
|
||||
return {
|
||||
@@ -314,8 +320,10 @@ const driver = {
|
||||
return;
|
||||
}
|
||||
|
||||
const { AbstractCursor } = driverBase.useLegacyDriver ? oldmongodb : mongodb;
|
||||
|
||||
if (exprValue instanceof AbstractCursor) {
|
||||
await readCursor(exprValue, options);
|
||||
await readCursor(exprValue, options, driverBase);
|
||||
} else if (isPromise(exprValue)) {
|
||||
try {
|
||||
const resValue = await exprValue;
|
||||
@@ -427,7 +435,7 @@ const driver = {
|
||||
const cursorStream = exprValue.stream();
|
||||
|
||||
cursorStream.on('data', (row) => {
|
||||
pass.write(serializeMongoData(row));
|
||||
pass.write(serializeMongoData(row, driverBase));
|
||||
});
|
||||
|
||||
// propagate error
|
||||
@@ -487,10 +495,12 @@ const driver = {
|
||||
let cursor = await collection.aggregate(deserializeMongoData(convertToMongoAggregate(options.aggregate)));
|
||||
const rows = await cursor.toArray();
|
||||
return {
|
||||
rows: rows.map(serializeMongoData).map((x) => ({
|
||||
...x._id,
|
||||
..._.omit(x, ['_id']),
|
||||
})),
|
||||
rows: rows
|
||||
.map((row) => serializeMongoData(row, driverBase))
|
||||
.map((x) => ({
|
||||
...x._id,
|
||||
..._.omit(x, ['_id']),
|
||||
})),
|
||||
};
|
||||
} else {
|
||||
// console.log('options.condition', JSON.stringify(options.condition, undefined, 2));
|
||||
@@ -500,7 +510,7 @@ const driver = {
|
||||
if (options.limit) cursor = cursor.limit(options.limit);
|
||||
const rows = await cursor.toArray();
|
||||
return {
|
||||
rows: rows.map(serializeMongoData),
|
||||
rows: rows.map((row) => serializeMongoData(row, driverBase)),
|
||||
};
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -613,10 +623,12 @@ const driver = {
|
||||
]);
|
||||
const rows = await cursor.toArray();
|
||||
return _.uniqBy(
|
||||
rows.map(serializeMongoData).map(({ _id }) => {
|
||||
if (_.isArray(_id) || _.isPlainObject(_id)) return { value: null };
|
||||
return { value: _id };
|
||||
}),
|
||||
rows
|
||||
.map((row) => serializeMongoData(row, driverBase))
|
||||
.map(({ _id }) => {
|
||||
if (_.isArray(_id) || _.isPlainObject(_id)) return { value: null };
|
||||
return { value: _id };
|
||||
}),
|
||||
(x) => x.value
|
||||
);
|
||||
} catch (err) {
|
||||
@@ -753,10 +765,10 @@ const driver = {
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
}));
|
||||
|
||||
driver.initialize = (dbgateEnv) => {
|
||||
drivers.initialize = (dbgateEnv) => {
|
||||
isProApp = dbgateEnv.isProApp;
|
||||
};
|
||||
|
||||
module.exports = driver;
|
||||
module.exports = drivers;
|
||||
@@ -1,4 +1,4 @@
|
||||
const driver = require('./driver');
|
||||
const drivers = require('./drivers');
|
||||
const {
|
||||
formatProfilerEntry,
|
||||
extractProfileTimestamp,
|
||||
@@ -7,13 +7,13 @@ const {
|
||||
|
||||
module.exports = {
|
||||
packageName: 'dbgate-plugin-mongo',
|
||||
drivers: [driver],
|
||||
drivers,
|
||||
functions: {
|
||||
formatProfilerEntry,
|
||||
extractProfileTimestamp,
|
||||
aggregateProfileChartEntry,
|
||||
},
|
||||
initialize(dbgateEnv) {
|
||||
driver.initialize(dbgateEnv);
|
||||
drivers.initialize(dbgateEnv);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -16,9 +16,12 @@ function jsonStringifyWithObjectId(obj) {
|
||||
return JSON.stringify(obj, mongoReplacer, 2)
|
||||
.replace(/\{\s*\"\$oid\"\s*\:\s*\"([0-9a-f]+)\"\s*\}/g, (m, id) => `ObjectId("${id}")`)
|
||||
.replace(/\{\s*\"\$bigint\"\s*\:\s*\"([0-9]+)\"\s*\}/g, (m, num) => `${num}n`)
|
||||
.replace(/\{\s*"\$binary"\s*:\s*\{\s*"base64"\s*:\s*"([^"]+)"(?:\s*,\s*"subType"\s*:\s*"([0-9a-fA-F]{2})")?\s*\}\s*\}/g, (m, base64, subType) => {
|
||||
return `BinData(${parseInt(subType || "00", 16)}, "${base64}")`;
|
||||
});
|
||||
.replace(
|
||||
/\{\s*"\$binary"\s*:\s*\{\s*"base64"\s*:\s*"([^"]+)"(?:\s*,\s*"subType"\s*:\s*"([0-9a-fA-F]{2})")?\s*\}\s*\}/g,
|
||||
(m, base64, subType) => {
|
||||
return `BinData(${parseInt(subType || '00', 16)}, "${base64}")`;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/** @type {import('dbgate-types').SqlDialect} */
|
||||
@@ -34,7 +37,7 @@ const dialect = {
|
||||
};
|
||||
|
||||
/** @type {import('dbgate-types').EngineDriver} */
|
||||
const driver = {
|
||||
const mongoDriverBase = {
|
||||
...driverBase,
|
||||
dumperClass: Dumper,
|
||||
databaseEngineTypes: ['document'],
|
||||
@@ -193,4 +196,16 @@ const driver = {
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = driver;
|
||||
const mongoDriver = {
|
||||
...mongoDriverBase,
|
||||
};
|
||||
|
||||
const legacyMongoDriver = {
|
||||
...mongoDriverBase,
|
||||
engine: 'mongo-legacy@dbgate-plugin-mongo',
|
||||
title: 'MongoDB 4 - Legacy',
|
||||
premiumOnly: true,
|
||||
useLegacyDriver: true,
|
||||
};
|
||||
|
||||
module.exports = [mongoDriver, legacyMongoDriver];
|
||||
@@ -1,9 +1,9 @@
|
||||
import driver from './driver';
|
||||
import drivers from './drivers';
|
||||
import { formatProfilerEntry, extractProfileTimestamp, aggregateProfileChartEntry } from './profilerFunctions';
|
||||
|
||||
export default {
|
||||
packageName: 'dbgate-plugin-mongo',
|
||||
drivers: [driver],
|
||||
drivers,
|
||||
functions: {
|
||||
formatProfilerEntry,
|
||||
extractProfileTimestamp,
|
||||
|
||||
Reference in New Issue
Block a user