Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
blendb
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
23
Issues
23
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
C3SL
blendb
Commits
41c54077
Commit
41c54077
authored
Aug 10, 2017
by
Lucas Fernandes de Oliveira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue
#31
: Add >, <, >=, <= operators to filters
Signed-off-by:
Lucas Fernandes de Oliveira
<
lfo14@inf.ufpr.br
>
parent
329ffcd5
Pipeline
#11290
passed with stage
in 43 seconds
Changes
7
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
258 additions
and
29 deletions
+258
-29
postgres.spec.ts
src/adapter/postgres.spec.ts
+39
-1
postgres.ts
src/adapter/postgres.ts
+10
-0
engine.spec.ts
src/core/engine.spec.ts
+61
-0
engine.ts
src/core/engine.ts
+7
-1
filter.spec.ts
src/core/filter.spec.ts
+4
-0
filter.ts
src/core/filter.ts
+83
-19
scenario.ts
test/scenario.ts
+54
-8
No files found.
src/adapter/postgres.spec.ts
View file @
41c54077
...
...
@@ -228,7 +228,45 @@ describe("postgres adapter", () => {
adapter
.
getDataFromView
(
view
,
(
err
,
result
)
=>
{
expect
(
err
).
to
.
be
.
a
(
"
null
"
);
expect
(
result
).
to
.
be
.
an
(
"
array
"
);
expect
(
result
).
to
.
have
.
length
(
4
);
expect
(
result
).
to
.
have
.
length
(
2
);
expect
(
result
[
0
]).
to
.
be
.
an
(
"
object
"
);
let
keys
:
string
[]
=
[];
keys
=
keys
.
concat
(
view
.
metrics
.
map
((
item
)
=>
item
.
name
));
keys
=
keys
.
concat
(
view
.
dimensions
.
map
((
item
)
=>
item
.
name
));
result
.
forEach
((
row
)
=>
{
expect
(
row
).
to
.
be
.
an
(
"
object
"
);
expect
(
row
).
to
.
have
.
all
.
keys
(
keys
);
});
done
();
});
});
it
(
"
should get data from view, using > AND < operators on filters
"
,
(
done
)
=>
{
let
view
=
adapterScenario
.
gtltView
;
adapter
.
getDataFromView
(
view
,
(
err
,
result
)
=>
{
expect
(
err
).
to
.
be
.
a
(
"
null
"
);
expect
(
result
).
to
.
be
.
an
(
"
array
"
);
expect
(
result
).
to
.
have
.
length
(
1
);
expect
(
result
[
0
]).
to
.
be
.
an
(
"
object
"
);
let
keys
:
string
[]
=
[];
keys
=
keys
.
concat
(
view
.
metrics
.
map
((
item
)
=>
item
.
name
));
keys
=
keys
.
concat
(
view
.
dimensions
.
map
((
item
)
=>
item
.
name
));
result
.
forEach
((
row
)
=>
{
expect
(
row
).
to
.
be
.
an
(
"
object
"
);
expect
(
row
).
to
.
have
.
all
.
keys
(
keys
);
});
done
();
});
});
it
(
"
should get data from view, using >= AND <= operators on filters
"
,
(
done
)
=>
{
let
view
=
adapterScenario
.
geleView
;
adapter
.
getDataFromView
(
view
,
(
err
,
result
)
=>
{
expect
(
err
).
to
.
be
.
a
(
"
null
"
);
expect
(
result
).
to
.
be
.
an
(
"
array
"
);
expect
(
result
).
to
.
have
.
length
(
3
);
expect
(
result
[
0
]).
to
.
be
.
an
(
"
object
"
);
let
keys
:
string
[]
=
[];
keys
=
keys
.
concat
(
view
.
metrics
.
map
((
item
)
=>
item
.
name
));
...
...
src/adapter/postgres.ts
View file @
41c54077
...
...
@@ -268,6 +268,14 @@ export class PostgresAdapter extends Adapter {
return
"
=
"
;
case
FilterOperator
.
NOTEQUAL
:
return
"
!=
"
;
case
FilterOperator
.
GREATER
:
return
"
>
"
;
case
FilterOperator
.
LOWER
:
return
"
<
"
;
case
FilterOperator
.
GREATEREQ
:
return
"
>=
"
;
case
FilterOperator
.
LOWEREQ
:
return
"
<=
"
;
default
:
return
""
;
}
...
...
@@ -280,6 +288,8 @@ export class PostgresAdapter extends Adapter {
return
"
::DATE
"
;
case
"
integer
"
:
return
"
::INTEGER
"
;
case
"
boolean
"
:
return
"
::BOOLEAN
"
;
default
:
return
""
;
}
...
...
src/core/engine.spec.ts
View file @
41c54077
...
...
@@ -270,4 +270,65 @@ describe("engine class", () => {
}
expect
(
error
).
to
.
be
.
true
;
});
it
(
"
should throw an exception, when a operator does not suit
"
,
()
=>
{
const
operators
=
[
"
>
"
,
"
<
"
,
"
<=
"
,
"
>=
"
];
for
(
let
i
=
0
;
i
<
operators
.
length
;
++
i
)
{
let
error
:
boolean
=
false
;
let
strFilter
=
"
dim:3
"
+
operators
[
i
]
+
"
joao
"
;
let
exeption
=
"
Filter could not be created: Operator
\"
"
+
operators
[
i
]
+
"
\"
is invalid for target
\"
dim:3
\"
"
;
try
{
engine
.
parseClause
(
strFilter
);
}
catch
(
e
){
error
=
true
;
expect
(
e
.
message
).
to
.
be
.
equal
(
exeption
);
}
}
});
it
(
"
should parse clauses with several operators for dates and integers
"
,
()
=>
{
const
operators
:
{[
key
:
string
]:
FilterOperator
}
=
{
"
>
"
:
FilterOperator
.
GREATER
,
"
<
"
:
FilterOperator
.
LOWER
,
"
<=
"
:
FilterOperator
.
LOWEREQ
,
"
>=
"
:
FilterOperator
.
GREATEREQ
,
"
==
"
:
FilterOperator
.
EQUAL
,
"
!=
"
:
FilterOperator
.
NOTEQUAL
};
for
(
let
op
in
operators
)
{
const
strFilter
=
"
dim:0
"
+
op
+
"
0
"
;
const
clause
=
engine
.
parseClause
(
strFilter
);
expect
(
clause
).
to
.
be
.
an
(
"
object
"
);
expect
(
clause
).
to
.
have
.
property
(
"
filters
"
);
expect
(
clause
).
to
.
have
.
property
(
"
id
"
);
expect
(
clause
.
filters
).
to
.
be
.
an
(
"
array
"
);
expect
(
clause
.
filters
).
to
.
have
.
length
(
1
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
id
"
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
target
"
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
operator
"
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
value
"
);
expect
(
clause
.
filters
[
0
].
target
).
to
.
be
.
equal
(
dim
[
0
]);
expect
(
clause
.
filters
[
0
].
value
).
to
.
be
.
equal
(
"
0
"
);
expect
(
clause
.
filters
[
0
].
operator
).
to
.
be
.
equal
(
operators
[
op
]);
}
for
(
let
op
in
operators
)
{
const
strFilter
=
"
dim:2
"
+
op
+
"
0
"
;
const
clause
=
engine
.
parseClause
(
strFilter
);
expect
(
clause
).
to
.
be
.
an
(
"
object
"
);
expect
(
clause
).
to
.
have
.
property
(
"
filters
"
);
expect
(
clause
).
to
.
have
.
property
(
"
id
"
);
expect
(
clause
.
filters
).
to
.
be
.
an
(
"
array
"
);
expect
(
clause
.
filters
).
to
.
have
.
length
(
1
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
id
"
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
target
"
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
operator
"
);
expect
(
clause
.
filters
[
0
]).
to
.
have
.
property
(
"
value
"
);
expect
(
clause
.
filters
[
0
].
target
).
to
.
be
.
equal
(
dim
[
2
]);
expect
(
clause
.
filters
[
0
].
value
).
to
.
be
.
equal
(
"
0
"
);
expect
(
clause
.
filters
[
0
].
operator
).
to
.
be
.
equal
(
operators
[
op
]);
}
});
});
src/core/engine.ts
View file @
41c54077
...
...
@@ -124,11 +124,17 @@ export class Engine {
throw
new
Error
(
"
Filter could not be created:
\"
"
+
segment
.
target
+
"
\"
was not found
"
);
}
return
new
Filter
({
const
filter
=
new
Filter
({
target
:
target
,
operator
:
op
,
value
:
segment
.
value
});
if
(
!
filter
.
isValid
)
{
throw
new
Error
(
"
Filter could not be created: Operator
\"
"
+
segment
.
operator
+
"
\"
is invalid for target
\"
"
+
segment
.
target
+
"
\"
"
);
}
return
filter
;
}
else
{
throw
new
Error
(
"
Filter could not be created: Operator on
\"
"
+
strFilter
+
"
\"
could not be extracted
"
);
...
...
src/core/filter.spec.ts
View file @
41c54077
...
...
@@ -26,6 +26,10 @@ describe("filter class", () => {
it
(
"
should correctly parse the operators
"
,
()
=>
{
expect
(
Filter
.
parseOperator
(
"
==
"
)).
to
.
be
.
equal
(
FilterOperator
.
EQUAL
);
expect
(
Filter
.
parseOperator
(
"
!=
"
)).
to
.
be
.
equal
(
FilterOperator
.
NOTEQUAL
);
expect
(
Filter
.
parseOperator
(
"
>
"
)).
to
.
be
.
equal
(
FilterOperator
.
GREATER
);
expect
(
Filter
.
parseOperator
(
"
<
"
)).
to
.
be
.
equal
(
FilterOperator
.
LOWER
);
expect
(
Filter
.
parseOperator
(
"
>=
"
)).
to
.
be
.
equal
(
FilterOperator
.
GREATEREQ
);
expect
(
Filter
.
parseOperator
(
"
<=
"
)).
to
.
be
.
equal
(
FilterOperator
.
LOWEREQ
);
expect
(
Filter
.
parseOperator
(
"
?=
"
)).
to
.
be
.
equal
(
FilterOperator
.
NONE
);
});
});
src/core/filter.ts
View file @
41c54077
...
...
@@ -37,7 +37,11 @@ export interface StrFilterOptions {
export
enum
FilterOperator
{
NONE
,
EQUAL
,
NOTEQUAL
NOTEQUAL
,
GREATER
,
LOWER
,
GREATEREQ
,
LOWEREQ
}
export
class
Filter
{
...
...
@@ -45,12 +49,14 @@ export class Filter {
public
readonly
target
:
Metric
|
Dimension
;
public
readonly
operator
:
FilterOperator
;
public
readonly
value
:
string
;
public
readonly
isValid
:
boolean
;
constructor
(
options
:
FilterOptions
)
{
this
.
target
=
options
.
target
;
this
.
operator
=
options
.
operator
;
this
.
value
=
options
.
value
;
this
.
id
=
Hash
.
sha1
(
options
.
target
.
name
+
options
.
operator
+
options
.
value
);
this
.
isValid
=
Filter
.
isTypeValid
(
options
);
}
public
static
parseOperator
(
op
:
string
):
FilterOperator
{
...
...
@@ -59,6 +65,14 @@ export class Filter {
return
FilterOperator
.
EQUAL
;
case
"
!=
"
:
return
FilterOperator
.
NOTEQUAL
;
case
"
>
"
:
return
FilterOperator
.
GREATER
;
case
"
<
"
:
return
FilterOperator
.
LOWER
;
case
"
>=
"
:
return
FilterOperator
.
GREATEREQ
;
case
"
<=
"
:
return
FilterOperator
.
LOWEREQ
;
default
:
return
FilterOperator
.
NONE
;
}
...
...
@@ -66,30 +80,80 @@ export class Filter {
public
static
segment
(
strFilter
:
string
):
StrFilterOptions
{
for
(
let
i
=
0
;
i
<
strFilter
.
length
;
++
i
)
{
if
(
strFilter
[
i
]
===
"
=
"
)
{
if
(
strFilter
[
i
+
1
]
===
"
=
"
)
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
==
"
,
value
:
strFilter
.
slice
(
i
+
2
)
};
}
switch
(
strFilter
[
i
]){
case
"
=
"
:
if
(
strFilter
[
i
+
1
]
===
"
=
"
)
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
==
"
,
value
:
strFilter
.
slice
(
i
+
2
)
};
}
break
;
case
"
!
"
:
if
(
strFilter
[
i
+
1
]
===
"
=
"
)
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
!=
"
,
value
:
strFilter
.
slice
(
i
+
2
)
};
}
break
;
case
"
>
"
:
if
(
strFilter
[
i
+
1
]
===
"
=
"
)
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
>=
"
,
value
:
strFilter
.
slice
(
i
+
2
)
};
}
else
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
>
"
,
value
:
strFilter
.
slice
(
i
+
1
)
};
}
case
"
<
"
:
if
(
strFilter
[
i
+
1
]
===
"
=
"
)
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
<=
"
,
value
:
strFilter
.
slice
(
i
+
2
)
};
}
else
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
<
"
,
value
:
strFilter
.
slice
(
i
+
1
)
};
}
default
:
break
;
}
}
return
null
;
}
if
(
strFilter
[
i
]
===
"
!
"
)
{
if
(
strFilter
[
i
+
1
]
===
"
=
"
)
{
return
{
target
:
strFilter
.
slice
(
0
,
i
),
operator
:
"
!=
"
,
value
:
strFilter
.
slice
(
i
+
2
)
}
;
}
private
static
isTypeValid
(
op
:
FilterOptions
):
boolean
{
if
(
op
.
operator
===
FilterOperator
.
GREATER
||
op
.
operator
===
FilterOperator
.
LOWER
||
op
.
operator
===
FilterOperator
.
GREATEREQ
||
op
.
operator
===
FilterOperator
.
LOWEREQ
)
{
if
(
op
.
target
.
dataType
===
"
date
"
||
op
.
target
.
dataType
===
"
integer
"
)
{
return
true
;
}
else
{
return
false
;
}
}
return
null
;
else
{
return
true
;
}
}
}
test/scenario.ts
View file @
41c54077
...
...
@@ -48,6 +48,8 @@ interface AdapterScenario {
multiFilterView
:
View
;
multiClauseView
:
View
;
notEqualView
:
View
;
gtltView
:
View
;
geleView
:
View
;
}
interface
DataCtrlScenario
{
...
...
@@ -74,10 +76,30 @@ const filters: { [key: string]: Filter } = {
operator
:
FilterOperator
.
EQUAL
,
value
:
"
2017-01-03
"
}),
"
dim:3
"
:
new
Filter
({
target
:
dims
[
3
],
"
dim:0:gt
"
:
new
Filter
({
target
:
dims
[
0
],
operator
:
FilterOperator
.
GREATER
,
value
:
"
2017-01-02
"
}),
"
dim:0:lt
"
:
new
Filter
({
target
:
dims
[
0
],
operator
:
FilterOperator
.
LOWER
,
value
:
"
2017-01-04
"
}),
"
dim:0:ge
"
:
new
Filter
({
target
:
dims
[
0
],
operator
:
FilterOperator
.
GREATEREQ
,
value
:
"
2017-01-02
"
}),
"
dim:0:le
"
:
new
Filter
({
target
:
dims
[
0
],
operator
:
FilterOperator
.
LOWEREQ
,
value
:
"
2017-01-04
"
}),
"
dim:5
"
:
new
Filter
({
target
:
dims
[
5
],
operator
:
FilterOperator
.
NOTEQUAL
,
value
:
"
dim:3:1
"
value
:
"
true
"
}),
"
dim:7
"
:
new
Filter
({
target
:
dims
[
7
],
...
...
@@ -88,8 +110,12 @@ const filters: { [key: string]: Filter } = {
const
clauses
:
{
[
key
:
string
]:
Clause
}
=
{
"
view0dim7
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:7
"
]]}),
"
view0gt
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:0:gt
"
]]}),
"
view0lt
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:0:lt
"
]]}),
"
view0ge
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:0:ge
"
]]}),
"
view0le
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:0:le
"
]]}),
"
view0dim0
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:0:0
"
],
filters
[
"
dim:0:1
"
]]}),
"
view
3dim3
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:3
"
]]})
"
view
7dim5
"
:
new
Clause
({
filters
:
[
filters
[
"
dim:5
"
]]})
};
const
wrongMet
=
new
Metric
({
...
...
@@ -206,11 +232,29 @@ const multiClauseView = new View({
const
notEqualView
=
new
View
({
metrics
:
[],
dimensions
:
[
dims
[
3
]],
dimensions
:
[
dims
[
4
],
dims
[
5
]],
materialized
:
false
,
origin
:
false
,
childViews
:
[
views
[
7
]],
clauses
:
[
clauses
.
view7dim5
]
});
const
gtltView
=
new
View
({
metrics
:
[],
dimensions
:
[
dims
[
0
]],
materialized
:
false
,
origin
:
false
,
childViews
:
[
views
[
0
]],
clauses
:
[
clauses
.
view0gt
,
clauses
.
view0lt
]
});
const
geleView
=
new
View
({
metrics
:
[],
dimensions
:
[
dims
[
0
]],
materialized
:
false
,
origin
:
false
,
childViews
:
[
views
[
3
]],
clauses
:
[
clauses
.
view
3dim3
]
childViews
:
[
views
[
0
]],
clauses
:
[
clauses
.
view
0ge
,
clauses
.
view0le
]
});
const
subDimView
=
new
View
({
...
...
@@ -265,7 +309,9 @@ export const adapterScenario: AdapterScenario = {
clauseView
:
clauseView
,
multiFilterView
:
multiFilterView
,
multiClauseView
:
multiClauseView
,
notEqualView
:
notEqualView
notEqualView
:
notEqualView
,
gtltView
:
gtltView
,
geleView
:
geleView
};
export
const
dataCtrlScenario
:
DataCtrlScenario
=
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment