-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CBL-6400: Port the changes to QueryParser in 3.2 branch (to support U… #2186
Conversation
Code Coverage Results:
|
…NNEST) to 4.0 (master branch)
f82a8ad
to
a1bd20c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't reviewed it all yet, but there are some changes to make.
LiteCore/Query/IndexSpec.cc
Outdated
for ( size_t pos = 0; pos != string::npos && pos < unnestPath.length(); ) { | ||
size_t next = unnestPath.find(KeyStore::kUnnestLevelSeparator, pos); | ||
if ( next == string::npos ) { | ||
splitPaths.push_back(unnestPath.substr(pos)); | ||
pos = string::npos; | ||
} else { | ||
splitPaths.push_back(unnestPath.substr(pos, next - pos)); | ||
pos = next + KeyStore::kUnnestLevelSeparator.size; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can replace this loop with a call to split
from StringUtils.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
LiteCore/Query/IndexSpec.cc
Outdated
string n1qlUnnestPaths = string(splitPaths[0]); | ||
for ( unsigned i = 1; i < splitPaths.size(); ++i ) { | ||
n1qlUnnestPaths += ", "; | ||
n1qlUnnestPaths += splitPaths[i]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, you're splitting unnestPath
with one delimiter, and then joining the pieces with a different delimiter. I think you could do this more simply by just replacing kUnnestLevelSeparator
with ", "
in unnestPath
...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
mutable FLDoc _doc = nullptr; | ||
mutable FLDoc _doc = nullptr; | ||
mutable FLDoc _unnestDoc = nullptr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to be released in the destructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
if ( currSpec ) { | ||
// If there is already index with the index name, | ||
// eiher delete the current one, or use it (return false) | ||
while ( true ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't a loop. I guess you used a while
so you could exit it with break
? That makes the code confusing IMHO; it'd be clearer just to use if
s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to if's
db().deleteIndex(*currSpec); | ||
} | ||
|
||
// the following will throw if !spec.arrayOptions() || !spec.arrayOpeionts()->unnestPath |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "arrayOpeionts"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
} | ||
|
||
// the following will throw if !spec.arrayOptions() || !spec.arrayOpeionts()->unnestPath | ||
Array::iterator itPath((const Array*)spec.unnestPaths()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this into the first clause of the for
statement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
QueryTranslator qp(db(), "", sourceTableName); | ||
qp.writeCreateIndex(spec.name, sourceTableName, (FLArrayIterator&)expressions, spec.where(), | ||
(spec.type != IndexSpec::kValue)); | ||
string hexName{spec.type == IndexSpec::kArray ? litecore::hexName(sourceTableName) : ""}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use sourceTableName
as the alternate value instead of ""
? Then you don't have to have conditionals in the following two lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to use optional.
LiteCore/Query/Translator/Node.hh
Outdated
Collation collation; // Current collation in effect | ||
bool collationApplied = true; // False if no COLLATE node generated | ||
bool hasGroupBy = false; // Current SELECT include GROUP_BY | ||
std::unordered_map<string, string> hashedTables; // hexName(tableName) -> tableName. Used for Unnest tables. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put this above the bool
s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
LiteCore/Query/Translator/Node.hh
Outdated
SourceNode* C4NULLABLE from{}; // The main source | ||
Collation collation; // Current collation in effect | ||
bool collationApplied = true; // False if no COLLATE node generated | ||
bool hasGroupBy = false; // Current SELECT include GROUP_BY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting the flag here only works for the top-level query. If there's a nested SELECT expression, the flag will be set in the nested context and the QueryTranslator won't see it.
Instead, the node whose SQL generation depends on hasGroupBy
should make that an instance variable, and set it when the node is constructed by looking at its parent SELECT statement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. good point. Passed hasGroupBy from ctx to the UnnestNode.
std::optional<string> hexName; | ||
if ( spec.type == IndexSpec::kArray ) hexName.emplace(litecore::hexName(sourceTableName)); | ||
QueryTranslator qp(db(), "", hexName.value_or(sourceTableName)); | ||
qp.writeCreateIndex(spec.name, hexName.value_or(sourceTableName), (FLArrayIterator&)expressions, spec.where(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant was that it can be simplified to this:
std::optional<string> hexName; | |
if ( spec.type == IndexSpec::kArray ) hexName.emplace(litecore::hexName(sourceTableName)); | |
QueryTranslator qp(db(), "", hexName.value_or(sourceTableName)); | |
qp.writeCreateIndex(spec.name, hexName.value_or(sourceTableName), (FLArrayIterator&)expressions, spec.where(), | |
string name = ( spec.type == IndexSpec::kArray ) ? hexName(sourceTableName) : sourceTableName; | |
QueryTranslator qp(db(), "", name); | |
qp.writeCreateIndex(spec.name, name, (FLArrayIterator&)expressions, spec.where(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -124,6 +124,8 @@ namespace litecore::qt { | |||
|
|||
void writeSQL(SQLWriter&, slice sqliteFnName, ExprNode* C4NULLABLE param) const; | |||
|
|||
void hasGroupBy() { _hasGroupBy = true; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name hasGroupBy
is confusing because it sounds like it's an accessor, not a setter.
But this method isn't needed anyway...
LiteCore/Query/Translator/Node.hh
Outdated
Collation collation; // Current collation in effect | ||
std::unordered_map<string, string> hashedTables; // hexName(tableName) -> tableName. Used for Unnest tables. | ||
bool collationApplied = true; // False if no COLLATE node generated | ||
bool hasGroupBy = false; // Current SELECT include GROUP_BY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hasGroupBy isn't needed anymore
@@ -60,6 +61,8 @@ namespace litecore { | |||
} else if ( auto p = dynamic_cast<ParameterNode*>(&node) ) { | |||
// Capture the parameter names: | |||
_parameters.emplace(p->name()); | |||
} else if ( auto prop = dynamic_cast<PropertyNode*>(&node) ) { | |||
if ( ctx.hasGroupBy ) prop->hasGroupBy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this isn't what I meant. The _hasGroupBy
flag should be set by the PropertyNode's constructor itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But at the time PropertyNode is constructed, we haven't parsed GROUP_BY. PropertyNode is constructed when source->parseChildExprs(ctx) is executed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SourceNode doesn't have to have parsed GROUP_BY yet, it just needs to check whether it exists. Add a flag SelectNode::_hasGroupBy
that's set early in the parse
method. PropertyNode can check that flag via an accessor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. Done.
LiteCore/Query/Translator/Node.hh
Outdated
std::vector<SourceNode*> sources; // All sources | ||
SourceNode* C4NULLABLE from{}; // The main source | ||
Collation collation; // Current collation in effect | ||
std::unordered_map<string, string> hashedTables; // hexName(tableName) -> tableName. Used for Unnest tables. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only thing that useshashedTables
is one method of QueryTranslator; it doesn't belong here. It should be a member of QueryTranslator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Done
@@ -362,6 +378,7 @@ namespace litecore::qt { | |||
} | |||
addChild(_groupBy, group); | |||
} | |||
ctx.hasGroupBy = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this flag is a good idea. The context already has a reference to the SelectNode, so just add a bool hasGroupBy()
accessor to SelectNode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed as suggested
e17d975
to
649a232
Compare
The two failed tests with Jenkins check all passed all tests but timed out afterwards (for some technical reason.) |
…NNEST) to 4.0 (master branch)