Skip to content
Snippets Groups Projects
Commit 3f958668 authored by Timm Fitschen's avatar Timm Fitschen Committed by Florian Spreckelsen
Browse files

FIX: Fix wildcard queries and keywords in specific strings

Fixes for #31 and #116
parent b501152d
No related branches found
No related tags found
1 merge request!21Release v0.4.0
......@@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
* #31 - Queries with keywords in the path (e.g. `... STORED AT 0in.txt`)
* #116 - Queries `FIND [ANY VERSION OF] *` and `FIND [ANY VERSION OF] ENTITY`.
### Security
## [0.3.0] - 2021-02-10
......
......@@ -23,15 +23,15 @@
lexer grammar CQLLexer;
AS_A:
[Aa][Ss] (EMPTY_SPACE? A)?
[Aa][Ss] (WHITE_SPACE_f? A)? WHITE_SPACE_f?
;
IS_REFERENCED:
(IS_f EMPTY_SPACE?)? [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee][Dd]
(IS_f WHITE_SPACE_f?)? [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee][Dd] WHITE_SPACE_f?
;
BY:
[Bb][Yy]
[Bb][Yy] WHITE_SPACE_f?
;
fragment
......@@ -50,69 +50,73 @@ VERSION_f:
;
ANY_VERSION_OF:
(ANY_f EMPTY_SPACE VERSION_f EMPTY_SPACE OF_f)
(ANY_f WHITE_SPACE_f VERSION_f WHITE_SPACE_f OF_f) WHITE_SPACE_f?
;
SELECT:
[Ss][Ee][Ll][Ee][Cc][Tt] -> pushMode(SELECT_MODE)
[Ss][Ee][Ll][Ee][Cc][Tt] WHITE_SPACE_f? -> pushMode(SELECT_MODE)
;
INSERTED:
[Ii][Nn][Ss][Ee][Rr][Tt][Ee][Dd]
[Ii][Nn][Ss][Ee][Rr][Tt][Ee][Dd] WHITE_SPACE_f?
;
CREATED:
[Cc][Rr][Ee][Aa][Tt][Ee][Dd]
[Cc][Rr][Ee][Aa][Tt][Ee][Dd] WHITE_SPACE_f?
;
UPDATED:
[Uu][Pp][Dd][Aa][Tt][Ee][Dd]
[Uu][Pp][Dd][Aa][Tt][Ee][Dd] WHITE_SPACE_f?
;
ON:
[Oo][Nn]
[Oo][Nn] WHITE_SPACE_f?
;
IN:
[Ii][Nn]
[Ii][Nn] WHITE_SPACE_f?
;
IS_STORED_AT:
(IS_f EMPTY_SPACE?)? [Ss][Tt][Oo][Rr][Ee][Dd] (EMPTY_SPACE? AT)?
(IS_f WHITE_SPACE_f?)? [Ss][Tt][Oo][Rr][Ee][Dd] (WHITE_SPACE_f? AT)? WHITE_SPACE_f?
;
AT:
[Aa][Tt]
[Aa][Tt] WHITE_SPACE_f?
;
FIND:
[Ff][Ii][Nn][Dd]
[Ff][Ii][Nn][Dd] WHITE_SPACE_f?
;
COUNT:
[Cc][Oo][Uu][Nn][Tt]
[Cc][Oo][Uu][Nn][Tt] WHITE_SPACE_f?
;
AND:
(
[Aa][Nn][Dd]
)
| '&'
(
(
[Aa][Nn][Dd]
)
| '&'
) WHITE_SPACE_f?
;
OR:
(
[Oo][Rr]
)
| '|'
(
(
[Oo][Rr]
)
| '|'
) WHITE_SPACE_f?
;
LPAREN:
'('
'(' WHITE_SPACE_f?
;
RPAREN:
')'
')' WHITE_SPACE_f?
;
SINGLE_QUOTE_START:
......@@ -131,19 +135,19 @@ OPERATOR:
| '>'
| '!='
| '->'
| [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee]([Ss]|EMPTY_SPACE? [Tt][Oo]) (EMPTY_SPACE? A {_input.LA(1) == ' '}?)? {setText("->");}
| [Rr][Ee][Ff][Ee][Rr][Ee][Nn][Cc][Ee]([Ss]|WHITE_SPACE_f? [Tt][Oo]) (WHITE_SPACE_f? A {_input.LA(1) == ' '}?)? {setText("->");}
;
LIKE:
[Ll][Ii][Kk][Ee]
[Ll][Ii][Kk][Ee] WHITE_SPACE_f?
;
IS_NULL:
IS_f EMPTY_SPACE NULL_f
IS_f WHITE_SPACE_f NULL_f WHITE_SPACE_f?
;
IS_NOT_NULL:
IS_f EMPTY_SPACE NOT_f EMPTY_SPACE NULL_f
IS_f WHITE_SPACE_f NOT_f WHITE_SPACE_f NULL_f WHITE_SPACE_f?
;
fragment
......@@ -163,7 +167,7 @@ NOT_f:
fragment
DOESNT_f:
DOES_f EMPTY_SPACE? NOT_f
DOES_f WHITE_SPACE_f? NOT_f
| DOES_f [Nn] SINGLE_QUOTE [Tt]
;
......@@ -244,88 +248,92 @@ WASNT_f:
;
NEGATION:
'!'
| DOESNT_f (WHITE_SPACE? HAVE_A_f)?
| DONT_f (WHITE_SPACE? HAVE_A_f)?
| HASNT_f (WHITE_SPACE? BEEN_f)?
| ISNT_f (WHITE_SPACE? BEEN_f)?
| NOT_f (WHITE_SPACE? BEEN_f)?
| WERENT_f (WHITE_SPACE? BEEN_f)?
| WASNT_f (WHITE_SPACE? BEEN_f)?
| HAVENT_f (WHITE_SPACE? BEEN_f)?
| HADNT_f (WHITE_SPACE? BEEN_f)?
(
'!'
| DOESNT_f (WHITE_SPACE? HAVE_A_f)?
| DONT_f (WHITE_SPACE? HAVE_A_f)?
| HASNT_f (WHITE_SPACE? BEEN_f)?
| ISNT_f (WHITE_SPACE? BEEN_f)?
| NOT_f (WHITE_SPACE? BEEN_f)?
| WERENT_f (WHITE_SPACE? BEEN_f)?
| WASNT_f (WHITE_SPACE? BEEN_f)?
| HAVENT_f (WHITE_SPACE? BEEN_f)?
| HADNT_f (WHITE_SPACE? BEEN_f)?
) WHITE_SPACE_f?
;
WITH:
[Ww][Ii][Tt][Hh]
[Ww][Ii][Tt][Hh] WHITE_SPACE_f?
;
THE:
[Tt][Hh][Ee]
[Tt][Hh][Ee] WHITE_SPACE_f?
;
GREATEST:
[Gg][Rr][Ee][Aa][Tt][Ee][Ss][Tt]
[Gg][Rr][Ee][Aa][Tt][Ee][Ss][Tt] WHITE_SPACE_f?
;
SMALLEST:
[Ss][Mm][Aa][Ll][Ll][Ee][Ss][Tt]
[Ss][Mm][Aa][Ll][Ll][Ee][Ss][Tt] WHITE_SPACE_f?
;
A:
[Aa][Nn]?
[Aa][Nn]? WHITE_SPACE_f?
;
ME:
[Mm][Ee]
[Mm][Ee] WHITE_SPACE_f?
;
SOMEONE:
[Ss][Oo][Mm][Ee][Oo][Nn][Ee]
[Ss][Oo][Mm][Ee][Oo][Nn][Ee] WHITE_SPACE_f?
;
ELSE:
[Ee][Ll][Ss][Ee]
[Ee][Ll][Ss][Ee] WHITE_SPACE_f?
;
WHERE:
[Ww][Hh][Ee][Rr][Ee]
[Ww][Hh][Ee][Rr][Ee] WHITE_SPACE_f?
;
WHICH:
[Ww][Hh][Ii][Cc][Hh]
[Ww][Hh][Ii][Cc][Hh] WHITE_SPACE_f?
;
HAS_A:
(HAS_f | HAD_f | HAVE_f | WERE_f | WAS_f | IS_f)
(
(EMPTY_SPACE? A)
| (EMPTY_SPACE? BEEN_f)
)?
(HAS_f | HAD_f | HAVE_f | WERE_f | WAS_f | IS_f)
(
(WHITE_SPACE_f? A)
| (WHITE_SPACE_f? BEEN_f)
)?
) WHITE_SPACE_f?
;
PROPERTY:
[Pp][Rr][Oo][Pp][Ee][Rr][Tt]([Yy]|[Ii][Ee][Ss])
[Pp][Rr][Oo][Pp][Ee][Rr][Tt]([Yy]|[Ii][Ee][Ss]) WHITE_SPACE_f?
;
RECORDTYPE:
[Rr][Ee][Cc][Oo][Rr][Dd][Tt][Yy][Pp][Ee]([Ss])?
[Rr][Ee][Cc][Oo][Rr][Dd][Tt][Yy][Pp][Ee]([Ss])? WHITE_SPACE_f?
;
RECORD:
[Rr][Ee][Cc][Oo][Rr][Dd]([Ss])?
[Rr][Ee][Cc][Oo][Rr][Dd]([Ss])? WHITE_SPACE_f?
;
FILE:
[Ff][Ii][Ll][Ee]([Ss])?
[Ff][Ii][Ll][Ee]([Ss])? WHITE_SPACE_f?
;
ENTITY:
[Ee][Nn][Tt][Ii][Tt]([Yy]|[Ii][Ee][Ss])
[Ee][Nn][Tt][Ii][Tt]([Yy]|[Ii][Ee][Ss]) WHITE_SPACE_f?
;
QUERYTEMPLATE:
[Qq][Uu][Ee][Rr][yY][Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee]
[Qq][Uu][Ee][Rr][yY][Tt][Ee][Mm][Pp][Ll][Aa][Tt][Ee] WHITE_SPACE_f?
;
fragment
......@@ -334,12 +342,12 @@ IS_f:
;
fragment
EMPTY_SPACE:
WHITE_SPACE_f:
[ \t\n\r]+
;
WHITE_SPACE:
[ \t\n\r]+ -> channel(HIDDEN)
[ \t\n\r]+
;
fragment
......@@ -365,12 +373,11 @@ REGEXP_END:
;
ID:
[Ii][Dd]
[Ii][Dd] WHITE_SPACE_f?
;
// Multiple slashes should be allowed in paths instead of a single slash.
SLASHES:
'/'+
SLASH:
'/'
;
STAR:
......@@ -382,26 +389,26 @@ DOT:
;
QMARK:
'?'
'?' WHITE_SPACE_f?
;
BUT:
[Bb][Uu][Tt]
[Bb][Uu][Tt] WHITE_SPACE_f?
;
ESC_REGEXP_END:
ESC_MARKER
'>>'
'>>' WHITE_SPACE_f?
;
ESC_STAR:
ESC_MARKER
'*'
'*' WHITE_SPACE_f?
;
ESC_BS:
ESC_MARKER
'\\'
'\\' WHITE_SPACE_f?
;
fragment
......@@ -410,7 +417,7 @@ ESC_MARKER:
;
TODAY:
[Tt][Oo][Dd][Aa][Yy]
[Tt][Oo][Dd][Aa][Yy] WHITE_SPACE_f?
;
HYPHEN:
......@@ -422,11 +429,17 @@ COLON:
;
NUM:
NUM_f
| DOT NUM_f
| NUM_f DOT NUM_f
;
NUM_f:
('0'..'9')+
;
TXT:
('a'..'z' | 'A'..'Z' | '_' | '-' {_input.LA(1) != '>'}? | '+' | '&' | ';' | ',' | '$' | ':' | '%' | '^' | '~' {_input.LA(1) != '='}? | '`' | '´' | 'ö' | 'ä' | 'ß' | 'ü' | 'Ö' | 'Ä' | 'Ü' | '@' | '[' | ']' | '{' | '}' )+
('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '-' {_input.LA(1) != '>'}? | '+' | '&' | ';' | ',' | '$' | ':' | '%' | '^' | '~' {_input.LA(1) != '='}? | '`' | '´' | 'ö' | 'ä' | 'ß' | 'ü' | 'Ö' | 'Ä' | 'Ü' | '@' | '[' | ']' | '{' | '}' )+
;
UNKNOWN_CHAR: . ;
......@@ -473,7 +486,7 @@ mode DOUBLE_QUOTE_MODE;
mode SELECT_MODE;
FROM:
[Ff][Rr][Oo][Mm] -> mode(DEFAULT_MODE)
[Ff][Rr][Oo][Mm]([ \t\n\r])? -> mode(DEFAULT_MODE)
;
SELECT_DOT:
......
......@@ -46,15 +46,15 @@ cq returns [Query.Type t, List<Query.Selection> s, Query.Pattern e, Query.Role r
| FIND {$t = Query.Type.FIND;}
| COUNT {$t = Query.Type.COUNT;})
(version {$v = $version.v;})?
(
(
role {$r = $role.r;}
(entity {$e = $entity.ep;})?
) | entity {$e = $entity.ep;}
)
( role {$r = $role.r;} )?
(
entity_filter {$filter = $entity_filter.filter;}
)??
|
entity WHITE_SPACE?{$e = $entity.ep;}
(
entity_filter {$filter = $entity_filter.filter;}
)?
)?
EOF
;
......@@ -100,7 +100,7 @@ entity_filter returns [EntityFilterInterface filter]
which_exp
(
(
LPAREN
LPAREN WHITE_SPACE?
(
filter_expression {$filter = $filter_expression.efi;}
| conjunction {$filter = $conjunction.c;}
......@@ -120,7 +120,7 @@ which_exp:
| HAS_A (PROPERTY)?
| WITH (A (PROPERTY)?)?
| WHERE
| DOT
| DOT WHITE_SPACE?
;
filter_expression returns [EntityFilterInterface efi]
......@@ -148,6 +148,7 @@ idfilter returns [IDFilter filter] locals [String o, String v, String a]
ID
(
OPERATOR {$o = $OPERATOR.text;}
WHITE_SPACE?
value {$v = $value.str;}
)?
;
......@@ -195,15 +196,14 @@ username returns [Query.Pattern ep] locals [int type]
$ep = new Query.Pattern($text, Query.Pattern.TYPE_NORMAL);
}
:
( STAR {$type = Query.Pattern.TYPE_LIKE;} | ESC_STAR | TXT | DOT | ESC_REGEXP_END | COLON )+
( STAR {$type = Query.Pattern.TYPE_LIKE;} | ~(STAR | WHITE_SPACE) )+
;
transaction_time returns [String tqp]
:
(
(ON | IN)
(value {$tqp = $value.text;}
| entity {$tqp = $entity.ep.toString();})
(value {$tqp = $value.text;})
) | TODAY {$tqp = TransactionFilter.TODAY;}
;
......@@ -249,10 +249,10 @@ pov returns [POV filter] locals [Query.Pattern p, String o, String v, String a]
property {$p = $property.pp; $a=$property.agg;}
(
(
LIKE {$o = $LIKE.text;}
LIKE {$o = $LIKE.text.trim();}
( like_pattern {$v = $like_pattern.ep.toString();}
| value {$v = $value.str;} )
| OPERATOR {$o = $OPERATOR.text;} value {$v = $value.str;}
| OPERATOR {$o = $OPERATOR.text;} WHITE_SPACE? value {$v = $value.str;}
)
| IS_NULL {$o = "0";}
| IS_NOT_NULL {$o = "!0";}
......@@ -266,12 +266,12 @@ pov returns [POV filter] locals [Query.Pattern p, String o, String v, String a]
( like_pattern {$v = $like_pattern.ep.toString();}
| value {$v = $value.str;} )
)
| ( OPERATOR {$o = $OPERATOR.text;} value {$v = $value.str;}
| ( OPERATOR {$o = $OPERATOR.text;} WHITE_SPACE? value {$v = $value.str;}
( AS_A
property {$p = $property.pp;} )?
)
)
WHITE_SPACE?
;
......@@ -296,9 +296,11 @@ backreference returns [Backreference ref] locals [Query.Pattern e, Query.Pattern
IS_REFERENCED
(BY A? entity {$e=$entity.ep;})?
(
WHITE_SPACE?
AS_A
property {$p=$property.pp;}
)?
WHITE_SPACE?
;
storedat returns [StoredAt filter] locals [String loc]
......@@ -311,6 +313,7 @@ storedat returns [StoredAt filter] locals [String loc]
:
IS_STORED_AT
location {$loc = $location.str;}
WHITE_SPACE?
;
conjunction returns [Conjunction c] locals [Conjunction dummy]
......@@ -321,7 +324,7 @@ conjunction returns [Conjunction c] locals [Conjunction dummy]
(
f1 = filter_expression {$c.add($f1.efi);}
|
LPAREN
LPAREN WHITE_SPACE?
(
f4 = filter_expression {$c.add($f4.efi);}
| disjunction {$c.add($disjunction.d);}
......@@ -330,6 +333,7 @@ conjunction returns [Conjunction c] locals [Conjunction dummy]
RPAREN
)
(
WHITE_SPACE?
AND
(
( which_exp | A (PROPERTY)?? )
......@@ -337,7 +341,7 @@ conjunction returns [Conjunction c] locals [Conjunction dummy]
(
f2 = filter_expression {$c.add($f2.efi);}
| (
LPAREN
LPAREN WHITE_SPACE?
(
f3 = filter_expression {$c.add($f3.efi);}
| disjunction {$c.add($disjunction.d);}
......@@ -357,7 +361,7 @@ disjunction returns [Disjunction d]
(
f1 = filter_expression {$d.add($f1.efi);}
|
LPAREN
LPAREN WHITE_SPACE?
(
f4 = filter_expression {$d.add($f4.efi);}
| conjunction {$d.add($conjunction.c);}
......@@ -373,7 +377,7 @@ disjunction returns [Disjunction d]
(
f2 = filter_expression {$d.add($f2.efi);}
| (
LPAREN
LPAREN WHITE_SPACE?
(
f3 = filter_expression {$d.add($f3.efi);}
| conjunction {$d.add($conjunction.c);}
......@@ -393,7 +397,7 @@ negation returns [Negation n]
(
f1 = filter_expression {$n = new Negation($f1.efi);}
| (
LPAREN
LPAREN WHITE_SPACE?
(
f2 = filter_expression {$n = new Negation($f2.efi);}
| disjunction {$n = new Negation($disjunction.d);}
......@@ -408,9 +412,10 @@ entity returns [Query.Pattern ep]
:
regexp_pattern {$ep = $regexp_pattern.ep;}
| like_pattern {$ep = $like_pattern.ep;}
| ( double_quoted {$ep = $double_quoted.ep;} )
| ( double_quoted {$ep = $double_quoted.ep;} )
| ( single_quoted {$ep = $single_quoted.ep;} )
| (~(SINGLE_QUOTE_START|DOUBLE_QUOTE_START|WHITE_SPACE|WHICH|DOT|WHERE|HAS_A|WITH|STAR|AND|OR))+? {$ep = new Query.Pattern((String) $text, Query.Pattern.TYPE_NORMAL);}
| ENTITY {$ep = new Query.Pattern((String) $text.trim(), Query.Pattern.TYPE_NORMAL);}
| ( ~(ENTITY |WHITE_SPACE | DOT) )+ {$ep = new Query.Pattern((String) $text.trim(), Query.Pattern.TYPE_NORMAL);}
;
regexp_pattern returns [Query.Pattern ep] locals [StringBuffer sb]
......@@ -428,12 +433,10 @@ like_pattern returns [Query.Pattern ep] locals [StringBuffer sb]
$sb = new StringBuffer();
}
:
(m=~(WHITE_SPACE|WHICH|DOT|WHERE|HAS_A|WITH|STAR|LIKE|OPERATOR|AS_A|AND|OR|IS_STORED_AT|IS_REFERENCED) {$sb.append($m.text);})*?
(
STAR {$sb.append('*');}
(m=~(WHITE_SPACE|WHICH|DOT|WHERE|HAS_A|WITH|STAR|LIKE|OPERATOR|AS_A|AND|OR) {$sb.append($m.text);})*?
)+? {$ep = new Query.Pattern((String) $sb.toString(), Query.Pattern.TYPE_LIKE);}
~(WHITE_SPACE|DOT|LIKE|OPERATOR|AS_A|AND|OR|IS_STORED_AT|IS_REFERENCED)*?
STAR
~(WHITE_SPACE|DOT|STAR)*?
{$ep = new Query.Pattern((String) $text, Query.Pattern.TYPE_LIKE);}
;
property returns [Query.Pattern pp, String agg]locals [StringBuffer sb]
......@@ -446,10 +449,11 @@ property returns [Query.Pattern pp, String agg]locals [StringBuffer sb]
(
regexp_pattern {$pp = $regexp_pattern.ep;}
| like_pattern {$pp = $like_pattern.ep;}
| ( double_quoted {$pp = $double_quoted.ep;} )
| ( double_quoted {$pp = $double_quoted.ep;} )
| ( single_quoted {$pp = $single_quoted.ep;} )
| ((m=TXT | m=NUM | m=REGEXP_MARKER | m=ENTITY){$sb.append($m.text);})+ {$pp = new Query.Pattern($sb.toString(), Query.Pattern.TYPE_NORMAL);}
)
WHITE_SPACE?
;
minmax returns [String agg]
......@@ -462,29 +466,37 @@ minmax returns [String agg]
value returns [String str]
:
number {$str = $text;}
number_with_unit {$str = $number_with_unit.text;}
| datetime {$str = $datetime.text;}
| atom {$str = $atom.ep.toString();}
WHITE_SPACE?
;
number_with_unit
:
HYPHEN??
NUM
(WHITE_SPACE?? unit)?
;
number
unit
:
HYPHEN?? NUM* (DOT NUM+)?
TXT
| NUM SLASH TXT
;
location returns [String str]
:
atom {$str = $atom.ep.str;}
|
SLASHES ?
((WHICH | WITH)+ SLASHES |( TXT | COLON | HYPHEN | NUM | DOT | ESC_STAR | ESC_BS | ESC_REGEXP_END | STAR )+ SLASHES ?)* {$str = $text; }
(~WHITE_SPACE)+ {$str = $text; }
;
atom returns [Query.Pattern ep]
:
double_quoted {$ep = $double_quoted.ep;}
| single_quoted {$ep = $single_quoted.ep;}
| (TXT | NUM | REGEXP_MARKER | STAR | A )+ {$ep = new Query.Pattern($text, Query.Pattern.TYPE_NORMAL);}
| (~(WHITE_SPACE | DOT ))+ {$ep = new Query.Pattern($text, Query.Pattern.TYPE_NORMAL);}
;
single_quoted returns [Query.Pattern ep] locals [StringBuffer sb, int patternType]
......
......@@ -181,6 +181,28 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
public Integer id;
public String version;
@Override
public String toString() {
if (version == null) {
return Integer.toString(id);
}
return Integer.toString(id) + "@" + version;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof IdVersionPair) {
IdVersionPair that = (IdVersionPair) obj;
return this.id == that.id && this.version == that.version;
}
return false;
}
@Override
public int hashCode() {
return toString().hashCode();
}
}
private static boolean filterEntitiesWithoutRetrievePermisions =
......@@ -445,7 +467,13 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
}
}
public void parse() throws ParsingException {
/**
* Parse the query and run optimize() if the parameter `optimize` is true.
*
* @param optimize whether to run optimize() immediately.
* @throws ParsingException
*/
public void parse(boolean optimize) throws ParsingException {
final long t1 = System.currentTimeMillis();
CQLLexer lexer;
lexer = new CQLLexer(CharStreams.fromString(this.query));
......@@ -471,29 +499,96 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
if (t2 - t1 > 1000) {
addBenchmark("LONG_PARSING: " + this.query, t2 - t1);
}
if (optimize) {
optimize();
}
}
/**
* Parse the query and run optimize() immediately.
*
* @throws ParsingException
*/
public void parse() throws ParsingException {
parse(true);
}
/**
* Optimize the query after parsing. The optimization is purely based on formal rules.
*
* <p>Implemented rules:
*
* <ol>
* <li>FIND * -> FIND ENTITY (which basically prevents to copy the complete entity table just to
* read out the ids immediately).
* </ol>
*/
public void optimize() {
// basic optimization
if (this.entity != null
&& this.entity.type == Pattern.TYPE_LIKE
&& this.entity.str.equals("*")) {
this.entity = null;
if (this.role == null) {
this.role = Role.ENTITY;
}
}
}
private String executeStrategy(boolean versioned) throws QueryException {
if (this.entity != null) {
return sourceStrategy(initQuery(versioned));
} else if (this.role == Role.ENTITY && this.filter == null) {
return "entities";
} else {
return targetStrategy(initQuery(versioned));
}
}
/**
* Generate a SQL statement which reads out the resulting ids (and version ids if `versioned` is
* true).
*
* <p>If the parameter `resultSetTableName` is "entities" actually the entity_version table is
* used to fetch all ids.
*
* @param resultSetTableName name of the table with all the resulting entities
* @param versioned whether the query was versioned
* @return an SQL statement
* @throws QueryException
*/
private String generateSelectStatementForResultSet(
final String resultSetTableName, boolean versioned) {
if (resultSetTableName.equals("entities")) {
return "SELECT entity_id AS id"
+ (versioned ? ", version AS version" : "")
+ " FROM entity_version"
+ (versioned ? "" : " WHERE `_iversion` = 1");
}
return "SELECT results.id AS id"
+ (versioned ? ", ev.version AS version" : "")
+ " FROM `"
+ resultSetTableName
+ "` AS results"
+ (versioned
? " JOIN entity_version AS ev ON (results.id = ev.entity_id AND results._iversion = ev._iversion)"
: "");
}
/**
* Return a list of all resulting entities (versions of entities if `versioned` is true).
*
* @param resultSetTableName name of the table with all the resulting entities
* @param versioned whether the query was versioned
* @return list of results of this query.
* @throws QueryException
*/
private List<IdVersionPair> getResultSet(final String resultSetTableName, boolean versioned)
throws QueryException {
ResultSet finishResultSet = null;
try {
final String sql =
"Select results.id AS id"
+ (versioned ? ", ev.version AS version" : "")
+ " from `"
+ resultSetTableName
+ "` AS results"
+ (versioned
? " JOIN entity_version AS ev ON (results.id = ev.entity_id AND results._iversion = ev._iversion)"
: "");
final String sql = generateSelectStatementForResultSet(resultSetTableName, versioned);
final PreparedStatement finish = getConnection().prepareStatement(sql);
finishResultSet = finish.executeQuery();
final List<IdVersionPair> rs = new LinkedList<>();
......@@ -869,4 +964,12 @@ public class Query implements QueryInterface, ToElementable, TransactionInterfac
if (this.filter != null) sb.append(this.filter.getCacheKey());
return sb.toString();
}
public Pattern getEntity() {
return this.entity;
}
public Role getRole() {
return this.role;
}
}
package org.caosdb.server.query;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import org.caosdb.server.CaosDBServer;
......@@ -48,4 +49,16 @@ public class QueryTest {
"ename@(ref1,null)SUB(POV(pname,>,val1)",
getCacheKey("FIND ename WHICH IS REFERENCED BY ref1 WITH pname > val1 "));
}
@Test
public void testOptimizationOfFindStar() {
Query q = new Query("FIND *");
q.parse(false);
assertEquals("*", q.getEntity().str);
assertNull(q.getRole());
q.optimize();
assertNull(q.getEntity());
assertEquals(Query.Role.ENTITY, q.getRole());
}
}
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment