Skip to content

Commit acbe58e

Browse files
authored
Merge pull request #34 from synatic/develop
fixed match position in join
2 parents 51ddd33 + 8638b0b commit acbe58e

25 files changed

+173937
-1060
lines changed

README.md

+199-195
Large diffs are not rendered by default.

lib/MongoFunctions.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class AllowableFunctions {
4949
name: 'field_exists',
5050
allowQuery: true,
5151
parse: (parameters) => {
52-
return {[parameters[0]]:{$exists:parameters[1]}};
52+
return {[parameters[0]]: {$exists: parameters[1]}};
5353
},
5454
},
5555
// endregion

lib/SQLParser.js

+94-74
Large diffs are not rendered by default.

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@synatic/sql-to-mongo",
3-
"version": "0.0.2",
3+
"version": "0.0.3",
44
"description": "Convert SQL to mongo queries or aggregates",
55
"main": "index.js",
66
"files": [
@@ -44,10 +44,10 @@
4444
"node": ">=12"
4545
},
4646
"dependencies": {
47-
"@synatic/json-magic": "0.1.1",
47+
"@synatic/json-magic": "^1.0.0",
4848
"check-types": "11.1.2",
4949
"deepmerge": "4.2.2",
50-
"node-sql-parser": "3.6.0"
50+
"node-sql-parser": "4.0.2"
5151
},
5252
"devDependencies": {
5353
"deep-equal": "^2.0.5",

scratchpad.js

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
2-
const SQLParser=require('./lib/SQLParser');
3-
1+
const SQLParser = require('./lib/SQLParser');
42

53
// 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)" )
64
// 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)" )
@@ -14,20 +12,22 @@ const SQLParser=require('./lib/SQLParser');
1412
// const parsedVal=SQLParser.makeMongoAggregate("select *,FIRST_IN_ARRAY(inventory) as inventory_docs from orders inner join `inventory` on orders.item=inventory.sku")
1513

1614
// 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)")
17-
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")
15+
// 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")
16+
const parsedVal = SQLParser.makeMongoAggregate(
17+
'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'
18+
);
19+
1820
// 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")
1921
// 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")
2022
// 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")
2123

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

25-
26-
return console.log(JSON.stringify(parsedVal.pipeline?parsedVal.pipeline:parsedVal.query))
27+
return console.log(JSON.stringify(parsedVal.pipeline ? parsedVal.pipeline : parsedVal.query));
2728

2829
// 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
2930

30-
3131
// const _arithmetic=require('./test/expressionOperators/ArithmeticExpressionOperators.json')
3232
//
3333
// const newTests=[];
@@ -51,4 +51,3 @@ return console.log(JSON.stringify(parsedVal.pipeline?parsedVal.pipeline:parsedVa
5151
//
5252
//
5353
// let x;
54-

test/Client.js

+73-64
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { MongoClient } = require('mongodb');
1+
const {MongoClient} = require('mongodb');
22
// eslint-disable-next-line no-unused-vars
33
const assert = require('assert');
44
const SQLParser = require('../lib/SQLParser.js');
@@ -10,8 +10,8 @@ const _customerNotes = require('./exampleData/customer-notes.json');
1010
const _customerNotes2 = require('./exampleData/customer-notes2.json');
1111
const _orders = require('./exampleData/orders.json');
1212
const _inventory = require('./exampleData/inventory.json');
13-
const _connectionString = "mongodb://127.0.0.1:27017";
14-
const _dbName = "sql-to-mongo-test";
13+
const _connectionString = 'mongodb://127.0.0.1:27017';
14+
const _dbName = 'sql-to-mongo-test';
1515

1616
const _queryTests = [].concat(
1717
require('./queryTests/queryTests.json'),
@@ -25,55 +25,68 @@ const _queryTests = [].concat(
2525
require('./queryTests/columnOperators.json')
2626
);
2727

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

3030
describe('Client Queries', function () {
31-
this.timeout(90000)
31+
this.timeout(90000);
3232
let client;
3333
before(function (done) {
3434
const run = async () => {
3535
try {
3636
client = new MongoClient(_connectionString);
3737
await client.connect();
38-
const { databases } = await client.db().admin().listDatabases();
39-
if (databases.findIndex(d => d.name === _dbName) > -1) {
38+
const {databases} = await client.db().admin().listDatabases();
39+
if (databases.findIndex((d) => d.name === _dbName) > -1) {
4040
await client.db(_dbName).dropDatabase();
4141
}
4242
const db = client.db(_dbName);
4343

44-
await db.collection('customers').bulkWrite(_customers.map(d => {
45-
return { insertOne: { document: d } };
46-
}));
47-
48-
await db.collection('stores').bulkWrite(_stores.map(d => {
49-
return { insertOne: { document: d } };
50-
}));
51-
52-
await db.collection('films').bulkWrite(_films.map(d => {
53-
return { insertOne: { document: d } };
54-
}));
55-
await db.collection('customer-notes').bulkWrite(_customerNotes.map(d => {
56-
return { insertOne: { document: d } };
57-
}));
58-
59-
await db.collection('customer-notes2').bulkWrite(_customerNotes2.map(d => {
60-
return { insertOne: { document: d } };
61-
}));
62-
63-
await db.collection('orders').bulkWrite(_orders.map(d => {
64-
return { insertOne: { document: d } };
65-
}));
66-
67-
await db.collection('inventory').bulkWrite(_inventory.map(d => {
68-
return { insertOne: { document: d } };
69-
}));
44+
await db.collection('customers').bulkWrite(
45+
_customers.map((d) => {
46+
return {insertOne: {document: d}};
47+
})
48+
);
49+
50+
await db.collection('stores').bulkWrite(
51+
_stores.map((d) => {
52+
return {insertOne: {document: d}};
53+
})
54+
);
55+
56+
await db.collection('films').bulkWrite(
57+
_films.map((d) => {
58+
return {insertOne: {document: d}};
59+
})
60+
);
61+
await db.collection('customer-notes').bulkWrite(
62+
_customerNotes.map((d) => {
63+
return {insertOne: {document: d}};
64+
})
65+
);
66+
67+
await db.collection('customer-notes2').bulkWrite(
68+
_customerNotes2.map((d) => {
69+
return {insertOne: {document: d}};
70+
})
71+
);
72+
73+
await db.collection('orders').bulkWrite(
74+
_orders.map((d) => {
75+
return {insertOne: {document: d}};
76+
})
77+
);
78+
79+
await db.collection('inventory').bulkWrite(
80+
_inventory.map((d) => {
81+
return {insertOne: {document: d}};
82+
})
83+
);
7084

7185
done();
7286
} catch (exp) {
7387
done(exp);
7488
}
75-
76-
}
89+
};
7790
run();
7891
});
7992

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

8699
describe('run query tests', function (done) {
87100
(async () => {
88-
const tests = _queryTests.filter(q => !!q.query && !q.error);
101+
const tests = _queryTests.filter((q) => !!q.query && !q.error);
89102
for (const test of tests) {
90-
it(`${test.name?test.name + ':':''}${test.query}`,function(done){
103+
it(`${test.name ? test.name + ':' : ''}${test.query}`, function (done) {
91104
(async () => {
92105
try {
93106
const parsedQuery = SQLParser.parseSQL(test.query);
94107
if (parsedQuery.count) {
95-
const count = await client.db(_dbName).collection(parsedQuery.collection).countDocuments(parsedQuery.query || null);
108+
const count = await client
109+
.db(_dbName)
110+
.collection(parsedQuery.collection)
111+
.countDocuments(parsedQuery.query || null);
96112
console.log(`${count}`);
97113
} else {
98-
const find = client.db(_dbName).collection(parsedQuery.collection).find(parsedQuery.query || null, {projection: parsedQuery.projection});
114+
const find = client
115+
.db(_dbName)
116+
.collection(parsedQuery.collection)
117+
.find(parsedQuery.query || null, {projection: parsedQuery.projection});
99118
if (parsedQuery.sort) {
100-
find.sort(parsedQuery.sort)
119+
find.sort(parsedQuery.sort);
101120
}
102121
if (parsedQuery.limit) {
103-
find.limit(parsedQuery.limit)
122+
find.limit(parsedQuery.limit);
104123
}
105124
const results = await find.toArray();
106-
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ""}`);
125+
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ''}`);
107126
}
108127
done();
109128
} catch (exp) {
110129
done(exp ? exp.message : null);
111130
}
112-
})()
131+
})();
113132
});
114133
}
115134
done();
116135
})();
117-
118-
119136
});
120137

121-
describe('run query tests as aggregates' , function (done) {
138+
describe('run query tests as aggregates', function (done) {
122139
(async () => {
123-
const tests = _queryTests.filter(q => !!q.query && !q.error);
140+
const tests = _queryTests.filter((q) => !!q.query && !q.error);
124141
for (const test of tests) {
125-
it(`${test.name?test.name + ':':''}${test.query}`,function(done){
142+
it(`${test.name ? test.name + ':' : ''}${test.query}`, function (done) {
126143
(async () => {
127144
try {
128145
const parsedQuery = SQLParser.makeMongoAggregate(test.query);
129146

130147
let results = await client.db(_dbName).collection(parsedQuery.collections[0]).aggregate(parsedQuery.pipeline);
131-
results = await results.toArray()
148+
results = await results.toArray();
132149

133-
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ""}`);
150+
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ''}`);
134151
done();
135152
} catch (exp) {
136153
done(exp ? exp.message : null);
@@ -139,23 +156,21 @@ describe('Client Queries', function () {
139156
});
140157
}
141158
done();
142-
})()
143-
144-
159+
})();
145160
});
146161

147162
describe('run aggregate tests', function (done) {
148163
(async () => {
149-
const tests = _aggregateTests.filter(q => !!q.query && !q.error);
164+
const tests = _aggregateTests.filter((q) => !!q.query && !q.error);
150165
for (const test of tests) {
151-
it(`${test.name?test.name + ':':''}${test.query}`,function(done){
166+
it(`${test.name ? test.name + ':' : ''}${test.query}`, function (done) {
152167
(async () => {
153168
try {
154169
const parsedQuery = SQLParser.makeMongoAggregate(test.query);
155170
let results = await client.db(_dbName).collection(parsedQuery.collections[0]).aggregate(parsedQuery.pipeline);
156-
results = await results.toArray()
171+
results = await results.toArray();
157172

158-
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ""}`);
173+
console.log(`count:${results.length} | ${results[0] ? JSON.stringify(results[0]) : ''}`);
159174
done();
160175
} catch (exp) {
161176
done(exp ? exp.message : null);
@@ -164,12 +179,6 @@ describe('Client Queries', function () {
164179
});
165180
}
166181
done();
167-
})()
168-
169-
182+
})();
170183
});
171-
172-
173-
174-
175184
});

test/SQL Parser.js

+12-15
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ const _queryTests = [].concat(
1212
require('./queryTests/comparisonOperators.json'),
1313
require('./queryTests/columnOperators.json')
1414
);
15-
const _aggregateTests = [].concat(require('./aggregateTests/aggregateTests.json'),require('./aggregateTests/joins.json'));
16-
15+
const _aggregateTests = [].concat(require('./aggregateTests/aggregateTests.json'), require('./aggregateTests/joins.json'));
1716

1817
describe('SQL Parser', function () {
1918
describe('should parse from sql ast: SQLParser.parseSQLtoAST', function () {
@@ -45,7 +44,7 @@ describe('SQL Parser', function () {
4544
} catch (exp) {
4645
return assert.equal(
4746
exp.message,
48-
'1:11 - Expected "#", ",", "--", "/*", ";", "FOR", "FROM", "GROUP", "HAVING", "LIMIT", "ORDER", "UNION", "WHERE", [ \\t\\n\\r], or end of input but "`" found.'
47+
'1:11 - Expected "#", ",", "--", "/*", ";", "FOR", "FROM", "GO", "GROUP", "HAVING", "LIMIT", "ORDER", "UNION", "WHERE", "WINDOW", [ \\t\\n\\r], or end of input but "`" found.'
4948
);
5049
}
5150
assert(false, 'No error');
@@ -80,8 +79,6 @@ describe('SQL Parser', function () {
8079
}
8180
assert(false, 'No error');
8281
});
83-
84-
8582
});
8683

8784
describe('should test can query: SQLParser.canQuery', function () {
@@ -374,7 +371,7 @@ describe('SQL Parser', function () {
374371
{
375372
limit: 100,
376373
collection: 'people',
377-
query: {$and:[{status: {$eq: 'A'}}, {age: {$eq: 50}}]},
374+
query: {$and: [{status: {$eq: 'A'}}, {age: {$eq: 50}}]},
378375
type: 'query',
379376
},
380377
'Invalid parse'
@@ -421,18 +418,18 @@ describe('SQL Parser', function () {
421418
limit: 100,
422419
collection: 'people',
423420
query: {
424-
"$and": [
421+
$and: [
425422
{
426-
"age": {
427-
"$gt": 25
428-
}
423+
age: {
424+
$gt: 25,
425+
},
429426
},
430427
{
431-
"age": {
432-
"$lt": 30
433-
}
434-
}
435-
]
428+
age: {
429+
$lt: 30,
430+
},
431+
},
432+
],
436433
},
437434
type: 'query',
438435
},

0 commit comments

Comments
 (0)