Skip to content
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-6651: createIndex doesn't support creating partial index with N1Q… #2214

Open
wants to merge 1 commit into
base: release/3.2
Choose a base branch
from

Conversation

jianminzhao
Copy link
Contributor

…L language

Extended IndexSpec to allow the where clause when the query langugage is N1QL. We put it in IndexSpec::options. In this commit, we only do it for ValueIndex and FTSIndex.

With JSON query language, the where clause can be either in the new option or in IndexSpec::expression together with the what clause. With N1QL query language, the where clause has to be in the new option, and IndexSpec::expression contains only the what clause.

This commit is to get ready for C4IndexOptions

…L language

Extended IndexSpec to allow the where clause when the query langugage is N1QL. We put it in IndexSpec::options. In this commit, we only do it for ValueIndex and FTSIndex.

With JSON query language, the where clause can be either in the new option or in IndexSpec::expression together with the what clause. With N1QL query language, the where clause has to be in the new option, and IndexSpec::expression contains only the what clause.

This commit is to get ready for C4IndexOptions
@jianminzhao jianminzhao requested review from snej and pasin January 22, 2025 16:51
@@ -170,8 +170,27 @@ TEST_CASE_METHOD(FTSTest, "Query Full-Text Stop-words In Target", "[Query][FTS]"
TEST_CASE_METHOD(FTSTest, "Query Full-Text Partial Index", "[Query][FTS]") {
// the WHERE clause prevents row 4 from being indexed/searched.
IndexSpec::FTSOptions options{"english", true};
store->createIndex("sentence", R"-({"WHAT": [[".sentence"]], "WHERE": [">", ["length()", [".sentence"]], 70]})-",
IndexSpec::kFullText, options);
switch ( GENERATE(0, 1, 2) ) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be simpler/clearer to just have three SECTION blocks. Then Catch will do the logging.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

@@ -45,6 +45,11 @@ namespace litecore {
bool ignoreDiacritics{}; ///< True to strip diacritical marks/accents from letters
bool disableStemming{}; ///< Disables stemming
const char* stopWords{}; ///< NULL for default, or comma-delimited string, or empty
const char* where;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we just add where to IndexSpec itself, since it's supported by multiple index types. Then you don't need the optionWhere method, or the ValueOptions type.

Also, it should be an alloc_slice, not a char*, since the latter has no ownership. (Yes, stopWords is a char*, which was probably a bad idea, but that was a long time ago and IIRC the thought was that it's going to point to a hardcoded string constant?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have noticed it and will make it alloc_slice when I do the C4 API, where "where" will get the value from C4IndexOptions and I cannot rely on C4 client for the storage.
I thought about adding "where" to IndexSpec, but it would a lot of code changes because of the current API,
KeyStore::createIndex(slice name, slice expression, QueryLanguage queryLanguage, IndexSpec::Type type,
IndexSpec::Options options)
I have to change the signature or add an overload.
Perhaps add an overload is easier. Having it in options is somewhat awkward.

hasWhere = true;
std::stringstream ss;
ss << "SELECT " << expression.asString() << " FROM _ WHERE " << optWhere;
result = (MutableDict*)n1ql::parse(ss.str(), &errPos);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On parse error, errPos will be wrong since the string you're parsing isn't what was given to the API. It'll be off by 7 if the error is in expression, and of course a larger variable number if the error is in optWhere.

Also, there's no way for the caller to distinguish whether the error is from the main expression or the 'where' clause ... resolving that might require a change going up to the C API.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this error position could be mysterious to the customers. In the error back to the C4,
if ( !result ) { throw Query::parseError("N1QL syntax error in index expression", errPos); }
I am thinking to include the actual expression in the error message. The actual expression may not be exactly what users passed in, but they (and we when we have to debug) find the position in the inputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants