Details
-
Bug
-
Resolution: Fixed
-
Major
-
None
-
Security Level: Public
-
None
Description
Hi, trying to convert a query from N1QL to Swift-N1QL i received many errors and strange behavior when i start use constant values instead of field name.
N1QL query
SELECT
|
key1 as key1,
|
10 as key2,
|
"" as key3,
|
true as key4,
|
'2020-02-12T15:18:24.573Z' as key5,
|
["A","B"] as key6,
|
1.1 as key7,
|
{"A":"B"} as key8
|
FROM `test-bucket`
|
Query result
[
|
{
|
"key1": "value1",
|
"key2": 10,
|
"key3": "A",
|
"key4": true,
|
"key5": "2020-02-12T15:18:24.573Z",
|
"key6": [
|
"A",
|
"B"
|
],
|
"key7": 1.1,
|
"key8": {
|
"A": "B"
|
}
|
}
|
]
|
So, if i try to do the same query from Couchbase Lite SDK (in this case Swift version), in the query result i missed the values of keys 3 and 5.
Query converted to Swift language
let query = QueryBuilder
|
.select(
|
SelectResult.expression(Expression.property("key1")),
|
SelectResult.expression(Expression.value(10)).as("key2"),
|
SelectResult.expression(Expression.value("A")).as("key3"),
|
SelectResult.expression(Expression.value(true)).as("key4"),
|
SelectResult.expression(Expression.value(Date())).as("key5"),
|
SelectResult.expression(Expression.value(["A","B"])).as("key6"),
|
SelectResult.expression(Expression.value(1.1)).as("key7"),
|
SelectResult.expression(Expression.value(["A":"B"])).as("key8")
|
)
|
.from(DataSource.database(database))
|
Result from CouchbaseLiteSwift
po array.first!.toDictionary()
|
▿ 6 elements
|
▿ 0 : 2 elements
|
- key : "key1"
|
- value : value1
|
▿ 1 : 2 elements
|
- key : "key2"
|
- value : 10
|
▿ 2 : 2 elements
|
- key : "key4"
|
- value : 1
|
▿ 3 : 2 elements
|
- key : "key6"
|
▿ value : 2 elements
|
- 0 : A
|
- 1 : B
|
▿ 4 : 2 elements
|
- key : "key7"
|
- value : 1.1
|
▿ 5 : 2 elements
|
- key : "key8"
|
▿ value : 1 element
|
▿ 0 : 2 elements
|
- key : A
|
- value : B
|
As you can see the keys 3 and 5 is missing.
Trying to debug the problem i found that the expression SelectResult.expression(Expression.value("A")).as("key3") use the string "A" as a field path and not as a plain string.
In fact running query.explain() i get this result
SELECT fl_result(fl_value(_doc.body, 'key1')), fl_result(10) AS "key2", fl_result(fl_value(_doc.body, 'A')) AS "key3", fl_result(fl_bool(1)) AS "key4", fl_result(fl_value(_doc.body, '2020-02-12T16:38:45.738Z')) AS "key5", fl_result(array_of('A', 'B')) AS "key6", fl_result(1.1000000000000001) AS "key7", fl_result(dict_of('A', 'B')) AS "key8" FROM kv_default AS _doc WHERE (_doc.flags & 1 = 0)
|
|
2|0|0| SCAN TABLE kv_default AS _doc
|
|
{"WHAT":[[".key1"],["AS",10,"key2"],["AS","A","key3"],["AS",true,"key4"],["AS","2020-02-12T16:38:45.738Z","key5"],["AS",["[]","A","B"],"key6"],["AS",1.1000000000000001,"key7"],["AS",{"A":"B"},"key8"]]}
|
Why key3 is evaluated in this way fl_result(fl_value(_doc.body, 'A')) AS "key3" and not in this way fl_result(fl_value('A')) AS "key3"?
Furthermore if i try to use an alias for database then i receive a fatal error
2020-02-12 18:13:29.386587+0100 CouchbaseQueryIssueTestCase[99001:1630323] CouchbaseLite Database WARNING: Invalid LiteCore query: property 'A.' does not begin with a declared 'AS' alias
|
Error Domain=CouchbaseLite Code=23 "property 'A.' does not begin with a declared 'AS' alias" UserInfo={NSLocalizedDescription=property 'A.' does not begin with a declared 'AS' alias}
|
Test case to reproduce the issue
let database: Database
|
do {
|
database = try Database(name: "testDB")
|
} catch {
|
fatalError("Error opening database")
|
}
|
|
let mutableDoc = MutableDocument()
|
.setString("value1", forKey: "key1")
|
|
do {
|
try database.saveDocument(mutableDoc)
|
} catch {
|
fatalError("Error saving document")
|
}
|
|
let query = QueryBuilder
|
.select(
|
SelectResult.expression(Expression.property("key1")),
|
SelectResult.expression(Expression.value(10)).as("key2"),
|
SelectResult.expression(Expression.value("A")).as("key3"),
|
SelectResult.expression(Expression.value(true)).as("key4"),
|
SelectResult.expression(Expression.value(Date())).as("key5"),
|
SelectResult.expression(Expression.value(["A","B"])).as("key6"),
|
SelectResult.expression(Expression.value(1.1)).as("key7"),
|
SelectResult.expression(Expression.value(["A":"B"])).as("key8")
|
)
|
.from(DataSource.database(database))
|
|
do {
|
print(try query.explain())
|
let array = try query.execute().allResults()
|
|
let keysCount = array.first!.keys.count
|
let valuesCount = array.first!.toDictionary().map { (_,value) in value }.count
|
assert(keysCount == valuesCount)
|
} catch {
|
print(error)
|
}
|
This issue can be reproduced also with Couchbase Lite Java CE & EE so i think the problem is in the core layer.