Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
blendb
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
C3SL
blendb
Commits
2b5d97fa
There was a problem fetching the pipeline summary.
Commit
2b5d97fa
authored
8 years ago
by
Lucas Fernandes de Oliveira
Browse files
Options
Downloads
Plain Diff
Merge branch 'issue/29' into 'master'
Issue
#29
: Refactor postgres adapter See merge request
!20
parents
d61f49d6
1635e14e
No related branches found
No related tags found
1 merge request
!20
Issue #29: Refactor postgres adapter
Pipeline
#
Changes
2
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/adapter/postgres.ts
+131
-139
131 additions, 139 deletions
src/adapter/postgres.ts
test/scenario.ts
+5
-0
5 additions, 0 deletions
test/scenario.ts
with
136 additions
and
139 deletions
src/adapter/postgres.ts
+
131
−
139
View file @
2b5d97fa
...
@@ -22,16 +22,13 @@ import { Adapter } from "../core/adapter";
...
@@ -22,16 +22,13 @@ import { Adapter } from "../core/adapter";
import
{
Metric
}
from
"
../core/metric
"
;
import
{
Metric
}
from
"
../core/metric
"
;
import
{
Dimension
}
from
"
../core/dimension
"
;
import
{
Dimension
}
from
"
../core/dimension
"
;
import
{
AggregationType
,
RelationType
}
from
"
../common/types
"
;
import
{
AggregationType
,
RelationType
}
from
"
../common/types
"
;
import
{
View
,
ChildView
}
from
"
../core/view
"
;
import
{
View
}
from
"
../core/view
"
;
import
{
Pool
,
PoolConfig
}
from
"
pg
"
;
import
{
Pool
,
PoolConfig
}
from
"
pg
"
;
interface
ParsedChild
{
interface
DimInfo
{
query
:
string
;
dim
:
Dimension
;
view
:
View
;
views
:
View
[];
dimensions
:
Dimension
[];
}
metrics
:
Metric
[];
alias
:
string
;
};
export
class
PostgresAdapter
extends
Adapter
{
export
class
PostgresAdapter
extends
Adapter
{
private
pool
:
Pool
;
private
pool
:
Pool
;
...
@@ -42,7 +39,20 @@ export class PostgresAdapter extends Adapter {
...
@@ -42,7 +39,20 @@ export class PostgresAdapter extends Adapter {
}
}
public
getDataFromView
(
view
:
View
,
cb
:
(
error
:
Error
,
result
?:
any
[])
=>
void
):
void
{
public
getDataFromView
(
view
:
View
,
cb
:
(
error
:
Error
,
result
?:
any
[])
=>
void
):
void
{
// buildQueryFromView does not put the final ;, it need to be put apart
// buildQueryFromView does not put the final ;, it need to be put apart
let
query
=
this
.
buildQueryFromView
(
view
,
view
.
metrics
,
view
.
dimensions
)
+
"
;
\n
"
;
// let query = this.buildQueryFromView(view, view.metrics, view.dimensions) + ";\n";
const
materialized
=
this
.
searchMaterializedViews
(
view
).
sort
((
a
,
b
)
=>
{
return
(
a
.
id
<
b
.
id
)
?
-
1
:
1
;
});
const
unique
=
[
materialized
[
0
]];
for
(
let
i
=
1
;
i
<
materialized
.
length
;
++
i
)
{
if
(
materialized
[
i
-
1
].
id
!==
materialized
[
i
].
id
)
{
unique
.
push
(
materialized
[
i
]);
}
}
const
query
=
this
.
buildQuery
(
view
,
unique
);
this
.
pool
.
connect
((
err
,
client
,
done
)
=>
{
this
.
pool
.
connect
((
err
,
client
,
done
)
=>
{
if
(
err
)
{
if
(
err
)
{
cb
(
err
);
cb
(
err
);
...
@@ -60,136 +70,6 @@ export class PostgresAdapter extends Adapter {
...
@@ -60,136 +70,6 @@ export class PostgresAdapter extends Adapter {
return
false
;
return
false
;
}
}
private
buildQueryFromView
(
view
:
View
,
metrics
:
Metric
[],
dimensions
:
Dimension
[]):
string
{
/*
Reduce metrics and dimensions array to the intersection with the
view. So is possible only get useful data in the sub-querys.
*/
let
strMetrics
=
metrics
.
map
((
metric
)
=>
{
let
func
=
this
.
getAggregateFunction
(
metric
.
aggregation
,
view
.
origin
);
let
quotedName
=
"
\"
"
+
metric
.
name
+
"
\"
"
;
let
extMetric
=
func
+
"
(
"
+
quotedName
+
"
) AS
"
+
quotedName
;
return
extMetric
;
});
if
(
view
.
materialized
)
{
let
strDimensions
=
dimensions
.
map
((
dimension
)
=>
"
\"
"
+
dimension
.
name
+
"
\"
"
);
let
sql
=
"
(SELECT
"
+
strMetrics
.
concat
(
strDimensions
).
join
(
"
,
"
);
sql
+=
"
FROM
"
+
"
view_
"
+
view
.
id
;
if
(
strDimensions
.
length
>
0
&&
strMetrics
.
length
>
0
)
{
sql
+=
"
GROUP BY
"
+
strDimensions
.
join
(
"
,
"
);
}
sql
+=
"
)
"
;
return
sql
;
}
else
{
let
covered
=
new
Map
();
let
matchable
:
any
[]
=
[]
;
dimensions
.
forEach
((
item
)
=>
{
covered
.
set
(
item
.
name
,
""
);
/*
For each dimension that must be covered
create a match in the array.
If a more than onde view match to the same
dimension, cretes a WHERE clause
*/
matchable
.
push
({
match
:
item
.
name
,
sub
:
item
});
let
dim
=
item
;
/*
Sub dimensions also have parents that can match
with then too.
*/
while
(
dim
.
relation
!==
RelationType
.
NONE
)
{
dim
=
dim
.
parent
;
matchable
.
push
({
match
:
dim
.
name
,
sub
:
item
,
});
}
});
metrics
.
forEach
((
item
)
=>
covered
.
set
(
item
.
name
,
""
));
let
elements
:
string
[]
=
[];
let
group
:
string
[]
=
[];
let
viewsQuery
:
string
[]
=
[];
let
selected
:
string
[]
=
[];
let
children
:
ParsedChild
[]
=
view
.
childViews
.
map
((
item
:
ChildView
)
=>
{
let
dims
=
item
.
view
.
dimensions
.
filter
((
dim
)
=>
{
return
matchable
.
some
((
match
)
=>
match
.
match
===
dim
.
name
);
});
let
mets
=
item
.
metrics
.
filter
((
met
)
=>
{
return
metrics
.
some
((
elem
)
=>
elem
.
name
===
met
.
name
);
});
let
query
=
""
;
if
(
dims
.
length
!==
0
||
mets
.
length
!==
0
)
{
query
=
this
.
buildQueryFromView
(
item
.
view
,
mets
,
dims
);
}
return
{
query
:
query
,
view
:
item
.
view
,
dimensions
:
dims
,
metrics
:
mets
,
alias
:
"
alias_
"
+
item
.
view
.
id
};
}).
filter
((
item
)
=>
item
.
query
!==
""
);
children
.
forEach
((
child
:
ParsedChild
)
=>
{
child
.
view
.
dimensions
.
forEach
((
dimension
:
Dimension
)
=>
{
/*
Make selection. Search for dimensions, that are in
matchable array.
*/
matchable
.
filter
((
item
)
=>
{
return
item
.
match
===
dimension
.
name
;
})
.
forEach
((
item
)
=>
{
// Expand the sub-dimension until match with a parent
let
dim
=
item
.
sub
;
let
extDimension
=
child
.
alias
+
"
.
\"
"
+
dimension
.
name
+
"
\"
"
;
while
(
dim
.
name
!==
item
.
match
)
{
extDimension
=
this
.
translateRelation
(
dim
.
relation
,
extDimension
);
dim
=
dim
.
parent
;
}
if
(
covered
.
get
(
item
.
sub
.
name
)
===
""
)
{
elements
.
push
(
extDimension
+
"
AS
\"
"
+
item
.
sub
.
name
+
"
\"
"
);
covered
.
set
(
item
.
sub
.
name
,
extDimension
);
group
.
push
(
extDimension
);
}
else
{
selected
.
push
(
extDimension
+
"
=
"
+
covered
.
get
(
item
.
sub
.
name
));
}
});
});
child
.
metrics
.
forEach
((
metric
:
Metric
)
=>
{
// Only materialized views can have origin as true
let
func
=
this
.
getAggregateFunction
(
metric
.
aggregation
,
false
);
let
quotedName
=
"
\"
"
+
metric
.
name
+
"
\"
"
;
let
extMetric
=
func
+
"
(
"
+
child
.
alias
+
"
.
"
+
quotedName
+
"
) AS
"
+
quotedName
;
elements
.
push
(
extMetric
);
});
viewsQuery
.
push
(
child
.
query
+
"
AS
"
+
child
.
alias
);
});
let
projection
=
"
SELECT
"
+
elements
.
join
(
"
,
"
)
+
"
\n
"
;
let
viewsFrom
=
"
FROM
"
+
viewsQuery
.
join
(
"
,
"
)
+
"
\n
"
;
let
selection
=
(
selected
.
length
>
0
)
?
"
WHERE
"
+
selected
.
join
(
"
AND
"
)
+
"
\n
"
:
""
;
let
grouping
=
""
;
if
(
group
.
length
>
0
&&
metrics
.
length
>
0
)
{
grouping
=
"
GROUP BY
"
+
group
.
join
(
"
,
"
)
+
"
\n
"
;
}
return
"
(
"
+
projection
+
viewsFrom
+
selection
+
grouping
+
"
)
"
;
}
}
private
getAggregateFunction
(
aggrType
:
AggregationType
,
origin
:
boolean
):
string
{
private
getAggregateFunction
(
aggrType
:
AggregationType
,
origin
:
boolean
):
string
{
switch
(
aggrType
)
{
switch
(
aggrType
)
{
case
AggregationType
.
SUM
:
case
AggregationType
.
SUM
:
...
@@ -237,4 +117,116 @@ export class PostgresAdapter extends Adapter {
...
@@ -237,4 +117,116 @@ export class PostgresAdapter extends Adapter {
*/
*/
return
name
+
"
(
"
+
args
.
map
((
item
,
idx
)
=>
item
+
values
[
idx
]).
join
(
"
,
"
)
+
"
)
"
;
return
name
+
"
(
"
+
args
.
map
((
item
,
idx
)
=>
item
+
values
[
idx
]).
join
(
"
,
"
)
+
"
)
"
;
}
}
private
searchMaterializedViews
(
view
:
View
):
View
[]
{
let
r
:
View
[]
=
[];
if
(
view
.
materialized
)
{
return
[
view
];
}
else
{
let
children
=
view
.
childViews
.
map
((
item
)
=>
item
.
view
);
for
(
let
i
=
0
;
i
<
children
.
length
;
++
i
)
{
r
=
r
.
concat
(
this
.
searchMaterializedViews
(
children
[
i
]));
}
}
return
r
;
}
private
buildQuery
(
target
:
View
,
views
:
View
[])
{
const
metrics
=
target
.
metrics
;
const
dimensions
=
target
.
dimensions
;
let
dimMap
:
{[
key
:
string
]:
DimInfo
}
=
{};
let
metMap
:
{[
key
:
string
]:
View
[]}
=
{};
for
(
let
i
=
0
;
i
<
views
.
length
;
++
i
)
{
const
mets
=
views
[
i
].
metrics
;
const
dims
=
views
[
i
].
dimensions
;
for
(
let
j
=
0
;
j
<
mets
.
length
;
++
j
)
{
if
(
!
metMap
[
mets
[
j
].
name
])
{
metMap
[
mets
[
j
].
name
]
=
[
views
[
i
]];
}
else
{
metMap
[
mets
[
j
].
name
].
push
(
views
[
i
]);
}
}
for
(
let
j
=
0
;
j
<
dims
.
length
;
++
j
)
{
if
(
!
dimMap
[
dims
[
j
].
name
])
{
dimMap
[
dims
[
j
].
name
]
=
{
dim
:
dims
[
j
],
views
:
[
views
[
i
]]
};
}
else
{
dimMap
[
dims
[
j
].
name
].
views
.
push
(
views
[
i
]);
}
}
}
const
strMetrics
=
metrics
.
map
((
metric
)
=>
{
const
view
=
metMap
[
metric
.
name
][
0
];
let
func
=
this
.
getAggregateFunction
(
metric
.
aggregation
,
view
.
origin
);
let
quotedName
=
"
\"
"
+
metric
.
name
+
"
\"
"
;
let
extMetric
=
func
+
"
(view_
"
+
view
.
id
+
"
.
"
+
quotedName
+
"
)
"
;
return
extMetric
+
"
AS
"
+
quotedName
;
});
const
parsedDimensions
=
dimensions
.
map
((
dimension
)
=>
{
let
dim
=
dimension
;
while
(
!
dimMap
[
dim
.
name
])
{
// Checar exeção
dim
=
dim
.
parent
;
}
const
view
=
dimMap
[
dim
.
name
].
views
[
0
];
const
quotedDim
=
"
\"
"
+
dim
.
name
+
"
\"
"
;
const
quotedName
=
"
\"
"
+
dimension
.
name
+
"
\"
"
;
let
extDimension
=
"
view_
"
+
view
.
id
+
"
.
"
+
quotedDim
;
let
aux
=
dimension
;
while
(
aux
.
name
!==
dim
.
name
)
{
extDimension
=
this
.
translateRelation
(
aux
.
relation
,
extDimension
);
aux
=
aux
.
parent
;
}
return
{
aliased
:
extDimension
+
"
AS
"
+
quotedName
,
noalias
:
extDimension
};
});
const
strDimensions
=
parsedDimensions
.
map
((
item
)
=>
item
.
aliased
);
const
grouped
=
parsedDimensions
.
map
((
item
)
=>
item
.
noalias
);
const
elements
=
strMetrics
.
concat
(
strDimensions
);
let
joins
=
[];
for
(
let
i
in
dimMap
)
{
let
remainViews
=
dimMap
[
i
].
views
.
slice
();
let
dim
=
dimMap
[
i
].
dim
;
let
leftSide
=
this
.
buildColumn
(
dim
,
remainViews
.
shift
().
id
);
if
(
remainViews
.
length
>
0
)
{
while
(
remainViews
.
length
>
0
)
{
const
id
=
remainViews
.
shift
().
id
;
const
rightSide
=
this
.
buildColumn
(
dim
,
id
);
joins
.
push
(
leftSide
+
"
=
"
+
rightSide
);
}
}
}
const
projection
=
"
SELECT
"
+
elements
.
join
(
"
,
"
);
const
source
=
"
FROM
"
+
views
.
map
((
view
)
=>
"
view_
"
+
view
.
id
).
join
(
"
,
"
);
const
selection
=
(
joins
.
length
>
0
)
?
"
WHERE
"
+
joins
.
join
(
"
AND
"
)
:
""
;
let
grouping
=
""
;
if
(
grouped
.
length
>
0
)
{
grouping
=
"
GROUP BY
"
+
grouped
.
join
(
"
,
"
);
}
return
projection
+
source
+
selection
+
grouping
+
"
;
"
;
}
private
buildColumn
(
item
:
Metric
|
Dimension
,
id
:
string
):
string
{
const
quotedName
=
"
\"
"
+
item
.
name
+
"
\"
"
;
return
"
view_
"
+
id
+
"
.
"
+
quotedName
;
}
}
}
This diff is collapsed.
Click to expand it.
test/scenario.ts
+
5
−
0
View file @
2b5d97fa
...
@@ -152,6 +152,11 @@ const aggrView = new View({
...
@@ -152,6 +152,11 @@ const aggrView = new View({
view
:
views
[
2
],
view
:
views
[
2
],
metrics
:
[
mets
[
6
]],
metrics
:
[
mets
[
6
]],
dimensions
:
[]
dimensions
:
[]
},
{
view
:
views
[
4
],
metrics
:
[],
dimensions
:
[]
}
}
]
]
});
});
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment