Skip to content

Commit

Permalink
Merge pull request #34 from synatic/develop
Browse files Browse the repository at this point in the history
fixed match position in join
  • Loading branch information
filepounder authored Dec 9, 2021
2 parents 51ddd33 + 8638b0b commit acbe58e
Show file tree
Hide file tree
Showing 25 changed files with 173,937 additions and 1,060 deletions.
394 changes: 199 additions & 195 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/MongoFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class AllowableFunctions {
name: 'field_exists',
allowQuery: true,
parse: (parameters) => {
return {[parameters[0]]:{$exists:parameters[1]}};
return {[parameters[0]]: {$exists: parameters[1]}};
},
},
// endregion
Expand Down
168 changes: 94 additions & 74 deletions lib/SQLParser.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@synatic/sql-to-mongo",
"version": "0.0.2",
"version": "0.0.3",
"description": "Convert SQL to mongo queries or aggregates",
"main": "index.js",
"files": [
Expand Down Expand Up @@ -44,10 +44,10 @@
"node": ">=12"
},
"dependencies": {
"@synatic/json-magic": "0.1.1",
"@synatic/json-magic": "^1.0.0",
"check-types": "11.1.2",
"deepmerge": "4.2.2",
"node-sql-parser": "3.6.0"
"node-sql-parser": "4.0.2"
},
"devDependencies": {
"deep-equal": "^2.0.5",
Expand Down
15 changes: 7 additions & 8 deletions scratchpad.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

const SQLParser=require('./lib/SQLParser');

const SQLParser = require('./lib/SQLParser');

// let parsedVal=SQLParser.makeMongoAggregate("select c.*,`customer-notes`.*,cn2.* from customers c inner join `customer-notes` on `customer-notes`.id=c.id left outer join (select * from `customer-notes2` where id <3) cn2 on cn2.id=firstInArray(`customer-notes`.id)" )
// let parsedVal=SQLParser.makeMongoAggregate("select c.*,cn.* from customers c inner join `customer-notes` cn on cn.id=c.id and (cn.id>2 or cn.id<5)" )
Expand All @@ -14,20 +12,22 @@ const SQLParser=require('./lib/SQLParser');
// const parsedVal=SQLParser.makeMongoAggregate("select *,FIRST_IN_ARRAY(inventory) as inventory_docs from orders inner join `inventory` on orders.item=inventory.sku")

// let parsedVal=SQLParser.makeMongoAggregate("select * from `customers` where id in (select id from `customer notes` where abs(id) <10) and id in (select id from `customer notes` where abs(id) <10)")
const parsedVal=SQLParser.makeMongoAggregate("select c.*,cn.*,cn2.* from customers c inner join `customer-notes` cn on c.id=cn.id inner join `customer-notes2` cn2 on cn2.id=c.id")
// const parsedVal=SQLParser.makeMongoAggregate("select c.*,c2.test from customers c inner join `customer-notes` cn on c.id=cn.id inner join `customer-notes2` cn2 on cn2.id=c.id")
const parsedVal = SQLParser.makeMongoAggregate(
'select c.*,c2.test from customers c inner join `customer-notes` cn on c.id=cn.id where cn.id>1 and c.id>2'
);

// const parsedVal=SQLParser.makeMongoAggregate("Select VoucherName,Status,Sum(1) as Count,case when Status='Created' then 1 else 0 end as SortOrder from test group by VoucherName,Status order by VoucherName,Status")
// let parsedVal=SQLParser.makeMongoAggregate("select `Address.City` as City,abs(-1) as absId,avg(lengthOfArray(`Rentals`)) as AvgRentals from `customers` where `First Name` like 'm%' and absId >1 group by `Address.City`,absId")
// const parsedVal=SQLParser.makeMongoAggregate("select `First Name`,`Address.City` as City,abs(-1) as absId from `customers` where `First Name` like 'm%' and abs(-1) >=1")

// let parsedVal=SQLParser.makeMongoAggregate("select * from (select id,`First Name`,`Last Name`,lengthOfArray(Rentals,'id') from customers )")
// const parsedVal=SQLParser.makeMongoAggregate("select `Address.Country` as Country,sum(id) as totalId from customers group by `Address.Country`")


return console.log(JSON.stringify(parsedVal.pipeline?parsedVal.pipeline:parsedVal.query))
return console.log(JSON.stringify(parsedVal.pipeline ? parsedVal.pipeline : parsedVal.query));

// select * from (select id,`First Name`,`Last Name`,lengthOfArray(Rentals,'id') from customers ) as t inner join (select id,`First Name`,`Last Name`,lengthOfArray(Rentals,'id') from customers ) as t2 on t2.id=t1.id


// const _arithmetic=require('./test/expressionOperators/ArithmeticExpressionOperators.json')
//
// const newTests=[];
Expand All @@ -51,4 +51,3 @@ return console.log(JSON.stringify(parsedVal.pipeline?parsedVal.pipeline:parsedVa
//
//
// let x;

137 changes: 73 additions & 64 deletions test/Client.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { MongoClient } = require('mongodb');
const {MongoClient} = require('mongodb');
// eslint-disable-next-line no-unused-vars
const assert = require('assert');
const SQLParser = require('../lib/SQLParser.js');
Expand All @@ -10,8 +10,8 @@ const _customerNotes = require('./exampleData/customer-notes.json');
const _customerNotes2 = require('./exampleData/customer-notes2.json');
const _orders = require('./exampleData/orders.json');
const _inventory = require('./exampleData/inventory.json');
const _connectionString = "mongodb://127.0.0.1:27017";
const _dbName = "sql-to-mongo-test";
const _connectionString = 'mongodb://127.0.0.1:27017';
const _dbName = 'sql-to-mongo-test';

const _queryTests = [].concat(
require('./queryTests/queryTests.json'),
Expand All @@ -25,55 +25,68 @@ const _queryTests = [].concat(
require('./queryTests/columnOperators.json')
);

const _aggregateTests = [].concat(require('./aggregateTests/aggregateTests.json'),require('./aggregateTests/joins.json'));
const _aggregateTests = [].concat(require('./aggregateTests/aggregateTests.json'), require('./aggregateTests/joins.json'));

describe('Client Queries', function () {
this.timeout(90000)
this.timeout(90000);
let client;
before(function (done) {
const run = async () => {
try {
client = new MongoClient(_connectionString);
await client.connect();
const { databases } = await client.db().admin().listDatabases();
if (databases.findIndex(d => d.name === _dbName) > -1) {
const {databases} = await client.db().admin().listDatabases();
if (databases.findIndex((d) => d.name === _dbName) > -1) {
await client.db(_dbName).dropDatabase();
}
const db = client.db(_dbName);

await db.collection('customers').bulkWrite(_customers.map(d => {
return { insertOne: { document: d } };
}));

await db.collection('stores').bulkWrite(_stores.map(d => {
return { insertOne: { document: d } };
}));

await db.collection('films').bulkWrite(_films.map(d => {
return { insertOne: { document: d } };
}));
await db.collection('customer-notes').bulkWrite(_customerNotes.map(d => {
return { insertOne: { document: d } };
}));

await db.collection('customer-notes2').bulkWrite(_customerNotes2.map(d => {
return { insertOne: { document: d } };
}));

await db.collection('orders').bulkWrite(_orders.map(d => {
return { insertOne: { document: d } };
}));

await db.collection('inventory').bulkWrite(_inventory.map(d => {
return { insertOne: { document: d } };
}));
await db.collection('customers').bulkWrite(
_customers.map((d) => {
return {insertOne: {document: d}};
})
);

await db.collection('stores').bulkWrite(
_stores.map((d) => {
return {insertOne: {document: d}};
})
);

await db.collection('films').bulkWrite(
_films.map((d) => {
return {insertOne: {document: d}};
})
);
await db.collection('customer-notes').bulkWrite(
_customerNotes.map((d) => {
return {insertOne: {document: d}};
})
);

await db.collection('customer-notes2').bulkWrite(
_customerNotes2.map((d) => {
return {insertOne: {document: d}};
})
);

await db.collection('orders').bulkWrite(
_orders.map((d) => {
return {insertOne: {document: d}};
})
);

await db.collection('inventory').bulkWrite(
_inventory.map((d) => {
return {insertOne: {document: d}};
})
);

done();
} catch (exp) {
done(exp);
}

}
};
run();
});

Expand All @@ -85,52 +98,56 @@ describe('Client Queries', function () {

describe('run query tests', function (done) {
(async () => {
const tests = _queryTests.filter(q => !!q.query && !q.error);
const tests = _queryTests.filter((q) => !!q.query && !q.error);
for (const test of tests) {
it(`${test.name?test.name + ':':''}${test.query}`,function(done){
it(`${test.name ? test.name + ':' : ''}${test.query}`, function (done) {
(async () => {
try {
const parsedQuery = SQLParser.parseSQL(test.query);
if (parsedQuery.count) {
const count = await client.db(_dbName).collection(parsedQuery.collection).countDocuments(parsedQuery.query || null);
const count = await client
.db(_dbName)
.collection(parsedQuery.collection)
.countDocuments(parsedQuery.query || null);
console.log(`${count}`);
} else {
const find = client.db(_dbName).collection(parsedQuery.collection).find(parsedQuery.query || null, {projection: parsedQuery.projection});
const find = client
.db(_dbName)
.collection(parsedQuery.collection)
.find(parsedQuery.query || null, {projection: parsedQuery.projection});
if (parsedQuery.sort) {
find.sort(parsedQuery.sort)
find.sort(parsedQuery.sort);
}
if (parsedQuery.limit) {
find.limit(parsedQuery.limit)
find.limit(parsedQuery.limit);
}
const results = await find.toArray();
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ""}`);
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ''}`);
}
done();
} catch (exp) {
done(exp ? exp.message : null);
}
})()
})();
});
}
done();
})();


});

describe('run query tests as aggregates' , function (done) {
describe('run query tests as aggregates', function (done) {
(async () => {
const tests = _queryTests.filter(q => !!q.query && !q.error);
const tests = _queryTests.filter((q) => !!q.query && !q.error);
for (const test of tests) {
it(`${test.name?test.name + ':':''}${test.query}`,function(done){
it(`${test.name ? test.name + ':' : ''}${test.query}`, function (done) {
(async () => {
try {
const parsedQuery = SQLParser.makeMongoAggregate(test.query);

let results = await client.db(_dbName).collection(parsedQuery.collections[0]).aggregate(parsedQuery.pipeline);
results = await results.toArray()
results = await results.toArray();

console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ""}`);
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ''}`);
done();
} catch (exp) {
done(exp ? exp.message : null);
Expand All @@ -139,23 +156,21 @@ describe('Client Queries', function () {
});
}
done();
})()


})();
});

describe('run aggregate tests', function (done) {
(async () => {
const tests = _aggregateTests.filter(q => !!q.query && !q.error);
const tests = _aggregateTests.filter((q) => !!q.query && !q.error);
for (const test of tests) {
it(`${test.name?test.name + ':':''}${test.query}`,function(done){
it(`${test.name ? test.name + ':' : ''}${test.query}`, function (done) {
(async () => {
try {
const parsedQuery = SQLParser.makeMongoAggregate(test.query);
let results = await client.db(_dbName).collection(parsedQuery.collections[0]).aggregate(parsedQuery.pipeline);
results = await results.toArray()
results = await results.toArray();

console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ""}`);
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ''}`);
done();
} catch (exp) {
done(exp ? exp.message : null);
Expand All @@ -164,12 +179,6 @@ describe('Client Queries', function () {
});
}
done();
})()


})();
});




});
27 changes: 12 additions & 15 deletions test/SQL Parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ const _queryTests = [].concat(
require('./queryTests/comparisonOperators.json'),
require('./queryTests/columnOperators.json')
);
const _aggregateTests = [].concat(require('./aggregateTests/aggregateTests.json'),require('./aggregateTests/joins.json'));

const _aggregateTests = [].concat(require('./aggregateTests/aggregateTests.json'), require('./aggregateTests/joins.json'));

describe('SQL Parser', function () {
describe('should parse from sql ast: SQLParser.parseSQLtoAST', function () {
Expand Down Expand Up @@ -45,7 +44,7 @@ describe('SQL Parser', function () {
} catch (exp) {
return assert.equal(
exp.message,
'1:11 - Expected "#", ",", "--", "/*", ";", "FOR", "FROM", "GROUP", "HAVING", "LIMIT", "ORDER", "UNION", "WHERE", [ \\t\\n\\r], or end of input but "`" found.'
'1:11 - Expected "#", ",", "--", "/*", ";", "FOR", "FROM", "GO", "GROUP", "HAVING", "LIMIT", "ORDER", "UNION", "WHERE", "WINDOW", [ \\t\\n\\r], or end of input but "`" found.'
);
}
assert(false, 'No error');
Expand Down Expand Up @@ -80,8 +79,6 @@ describe('SQL Parser', function () {
}
assert(false, 'No error');
});


});

describe('should test can query: SQLParser.canQuery', function () {
Expand Down Expand Up @@ -374,7 +371,7 @@ describe('SQL Parser', function () {
{
limit: 100,
collection: 'people',
query: {$and:[{status: {$eq: 'A'}}, {age: {$eq: 50}}]},
query: {$and: [{status: {$eq: 'A'}}, {age: {$eq: 50}}]},
type: 'query',
},
'Invalid parse'
Expand Down Expand Up @@ -421,18 +418,18 @@ describe('SQL Parser', function () {
limit: 100,
collection: 'people',
query: {
"$and": [
$and: [
{
"age": {
"$gt": 25
}
age: {
$gt: 25,
},
},
{
"age": {
"$lt": 30
}
}
]
age: {
$lt: 30,
},
},
],
},
type: 'query',
},
Expand Down
Loading

0 comments on commit acbe58e

Please sign in to comment.