Skip to content

Commit 7223b71

Browse files
committed
Large refactoring in data provider
1 parent 89e46c9 commit 7223b71

25 files changed

+1272
-146
lines changed

src/DataProvider.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
'use strict';
2+
3+
const DataSource = require('./DataSource');
4+
const DataSourceRead = require('./dataSource/DataSourceRead');
5+
const ProgramError = require('./error/ProgramError');
6+
7+
class DataProvider
8+
{
9+
/**
10+
*
11+
* @param {DataSourceAnalyzer} dataSourceAnalyzer
12+
*/
13+
constructor(dataSourceAnalyzer)
14+
{
15+
this.dataSourceAnalyzer = dataSourceAnalyzer;
16+
}
17+
18+
/**
19+
* @public
20+
* @param {SqlNodes.Table} tableNode
21+
* @returns {DataSource}
22+
*/
23+
getDataSource(tableNode)
24+
{
25+
const chain = this.dataSourceAnalyzer.createCallChain(tableNode.source);
26+
const streamsChain = this.createStreamsChain(chain);
27+
const stream = this.createResultStream(streamsChain);
28+
29+
const resolvedAlias = streamsChain[streamsChain.length - 1].alias;
30+
const alias = (tableNode.alias && tableNode.alias.name) || resolvedAlias;
31+
32+
return new DataSource(stream, alias);
33+
}
34+
35+
/**
36+
* @private
37+
* @param {DataSourceRead|DataSourceTransform} start
38+
* @returns {stream.Readable[]}
39+
*/
40+
createStreamsChain(start)
41+
{
42+
if (start instanceof DataSourceRead) {
43+
return [this.createStream(start.desc, start.location, start.options)];
44+
}
45+
46+
const source = this.createStreamsChain(start.input);
47+
48+
const transform = this.createStream(start.desc, source[source.length - 1], start.options);
49+
50+
return source.concat([transform]);
51+
}
52+
53+
/**
54+
* @private
55+
* @param {stream.Readable[]} streamsChain
56+
* @returns {stream.Readable}
57+
*/
58+
createResultStream(streamsChain)
59+
{
60+
if (!streamsChain.length) {
61+
throw new ProgramError('Empty streams chain');
62+
}
63+
64+
var end = streamsChain[0].stream;
65+
66+
for (let i = 1; i < streamsChain.length; i++) {
67+
end = end.pipe(streamsChain[i].stream);
68+
}
69+
70+
return end;
71+
}
72+
73+
/**
74+
* @private
75+
* @param {DataFunctionDescription} desc
76+
* @param {mixed} source
77+
* @param {Object} options
78+
* @returns {DataSource}
79+
*/
80+
createStream(desc, source, options)
81+
{
82+
const s = desc.createStream(source, options);
83+
var dataSource;
84+
85+
if (s instanceof DataSource) {
86+
dataSource = s;
87+
} else {
88+
dataSource = new DataSource(s);
89+
}
90+
91+
if (source instanceof DataSource) {
92+
dataSource.alias = source.alias;
93+
}
94+
95+
return dataSource;
96+
}
97+
}
98+
99+
module.exports = DataProvider;

src/DataSource.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,7 @@ class DataSource
1919
}
2020

2121
DataSource.DEFAULT_NAME = '@';
22+
DataSource.TYPE_OBJECTS = 'objects';
23+
DataSource.TYPE_BINARY = 'binary';
2224

2325
module.exports = DataSource;

src/DataSourceResolversPool.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
const SqlNodes = require('./sql/Nodes');
3+
const DataSource = require('./DataSource');
44

55
class DataSourceResolversPool
66
{
@@ -30,29 +30,17 @@ class DataSourceResolversPool
3030
const source = resolver._resolve(pathFragments);
3131

3232
if (source) {
33-
return source;
33+
if (source instanceof DataSource) {
34+
return source;
35+
} else {
36+
return new DataSource(source, resolver.extractAlias(pathFragments));
37+
}
3438
}
3539
}
3640

3741
return null;
3842
}
3943

40-
/**
41-
*
42-
* @param {ComplexIdent} complexIdent
43-
* @returns {string}
44-
*/
45-
extractBindingAlias(complexIdent)
46-
{
47-
const lastFragment = complexIdent.fragments[complexIdent.fragments.length - 1];
48-
49-
if (lastFragment instanceof SqlNodes.BindingIdent || lastFragment instanceof SqlNodes.BindingIdentList) {
50-
return lastFragment.basename();
51-
}
52-
53-
return null;
54-
}
55-
5644
/**
5745
*
5846
* @param {string[]} pathFragments

src/Engine.js

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,68 @@
33
const SqlParser = require('./sql/Parser');
44
const SqlNodes = require('./sql/Nodes');
55
const SqlToJs = require('./SqlToJs');
6+
67
const PreparingContext = require('./PreparingContext');
78
const RuntimeContext = require('./RuntimeContext');
89
const FunctionsMap = require('./FunctionsMap');
10+
11+
const DataSourceNotFound = require('./error/DataSourceNotFound');
12+
13+
const DataSource = require('./DataSource');
14+
const DataSourceApiResolver = require('./DataSourceApiResolver');
15+
const DataSourceResolversPool = require('./DataSourceResolversPool');
16+
const DataProvider = require('./DataProvider');
17+
const DataSourceAnalyzer = require('./dataSource/DataSourceAnalyzer');
18+
const DataFunctionsRegistry = require('./dataSource/DataFunctionsRegistry');
19+
const DataFunctionDescription = require('./dataSource/DataFunctionDescription');
20+
921
const Select = require('./Select');
1022
const Insert = require('./Insert');
1123
const Update = require('./Update');
24+
1225
const path = require('path');
1326

1427
class Engine
1528
{
1629
/**
1730
*
18-
* @param {string} sql
1931
* @param {PublicApiOptions} options
32+
*/
33+
constructor(options = {})
34+
{
35+
this.options = options;
36+
this.functionsMap = this.createFunctionsMap();
37+
}
38+
39+
/**
40+
*
41+
* @param {string} sql
42+
* @param {DataSourceApiResolver} dataSourceInternalResolver
2043
* @returns {Select|Insert}
2144
*/
22-
createQuery(sql, options = {})
45+
createQuery(sql, dataSourceInternalResolver = new DataSourceApiResolver())
2346
{
24-
const functionsMap = this.createFunctionsMap();
25-
const runtimeContext = new RuntimeContext(functionsMap);
47+
const runtimeContext = new RuntimeContext(this.functionsMap);
2648

2749
const sqlToJs = new SqlToJs(
28-
functionsMap,
50+
this.functionsMap,
2951
runtimeContext
3052
);
3153

3254
const preparingContext = new PreparingContext(
3355
sqlToJs,
34-
functionsMap
56+
this.functionsMap
3557
);
3658

37-
preparingContext.options = options;
59+
const dataProvider = this.createDataProvider(sqlToJs, dataSourceInternalResolver);
60+
61+
preparingContext.options = this.options;
3862

3963
const ast = SqlParser.parse(sql);
4064

4165
if (ast instanceof SqlNodes.Select) {
4266

43-
return new Select(preparingContext, runtimeContext, ast);
67+
return new Select(dataProvider, preparingContext, runtimeContext, ast);
4468
} else if (ast instanceof SqlNodes.Delete) {
4569
const selectAst = new SqlNodes.Select;
4670

@@ -50,18 +74,53 @@ class Engine
5074
selectAst.where = new SqlNodes.Boolean(false);
5175
}
5276

53-
return new Select(preparingContext, runtimeContext, selectAst);
77+
return new Select(dataProvider, preparingContext, runtimeContext, selectAst);
5478
} else if (ast instanceof SqlNodes.Insert) {
5579

56-
return new Insert(preparingContext, runtimeContext, ast);
80+
return new Insert(dataProvider, preparingContext, runtimeContext, ast);
5781
} else if (ast instanceof SqlNodes.Update) {
5882

59-
return new Update(preparingContext, runtimeContext, ast);
83+
return new Update(dataProvider, preparingContext, runtimeContext, ast);
6084
} else {
6185
throw new Error('Unknown query: ' + ast.constructor.name);
6286
}
6387
}
6488

89+
createDataProvider(sqlToJs, dataSourceInternalResolver)
90+
{
91+
const pool = new DataSourceResolversPool;
92+
93+
if (this.options.dataSourceResolvers) {
94+
for (const resolver of this.options.dataSourceResolvers) {
95+
pool.add(resolver);
96+
}
97+
}
98+
99+
pool.add(dataSourceInternalResolver);
100+
101+
const dataFunctionsRegistry = new DataFunctionsRegistry();
102+
103+
dataFunctionsRegistry.add(new DataFunctionDescription(
104+
DataFunctionDescription.TYPE_READ,
105+
'INTERNAL',
106+
(location, options) => {
107+
const dataSource = pool.resolve(location);
108+
109+
if (!dataSource) {
110+
throw new DataSourceNotFound(location);
111+
}
112+
113+
return dataSource;
114+
},
115+
null,
116+
DataSource.TYPE_OBJECTS
117+
));
118+
119+
const dataSourceAnalyzer = new DataSourceAnalyzer(sqlToJs, dataFunctionsRegistry, 'INTERNAL', null);
120+
121+
return new DataProvider(dataSourceAnalyzer);
122+
}
123+
65124
/**
66125
* @@returns {FunctionsMap}
67126
*/

src/Insert.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,23 @@ const DataRow = require('./DataRow');
66
class Insert
77
{
88
/**
9-
*
9+
* @param {DataProvider} dataProvider
1010
* @param {PreparingContext} preparingContext
1111
* @param {RuntimeContext} runtimeContext
1212
* @param {Node} ast
1313
*/
14-
constructor(preparingContext, runtimeContext, ast)
14+
constructor(dataProvider, preparingContext, runtimeContext, ast)
1515
{
16+
this.dataProvider = dataProvider;
1617
this.preparingContext = preparingContext;
1718
this.runtimeContext = runtimeContext;
1819
this.ast = ast;
1920
}
2021

2122
/**
22-
*
23-
* @param {DataSourceResolversPool} dataSourceResolversPool
2423
* @returns {Append}
2524
*/
26-
stream(dataSourceResolversPool)
25+
stream()
2726
{
2827
const dummyRow = new DataRow({});
2928
const rows = [];

src/PublicApi.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const Engine = require('./Engine');
44
const PublicSelect = require('./public/PublicSelect');
55
const PublicApiOptions = require('./PublicApiOptions');
6+
const DataSourceApiResolver = require('./DataSourceApiResolver');
67
const Explainer = require('./Explainer');
78

89
class PublicApi
@@ -19,7 +20,7 @@ class PublicApi
1920
this.options = new PublicApiOptions(options);
2021
}
2122

22-
this.engine = new Engine();
23+
this.engine = new Engine(this.options);
2324
}
2425

2526
/**
@@ -29,7 +30,9 @@ class PublicApi
2930
*/
3031
query(sql)
3132
{
32-
return new PublicSelect(this.engine.createQuery(sql, this.options), this.options.dataSourceResolvers);
33+
const dataSourceInternalResolver = new DataSourceApiResolver();
34+
35+
return new PublicSelect(this.engine.createQuery(sql, dataSourceInternalResolver), dataSourceInternalResolver);
3336
}
3437

3538
explain(select)

0 commit comments

Comments
 (0)