Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,28 @@ public SortClause buildClauseFromDefinition(ObjectNode sortNode) {

JsonNode lexicalNode = sortNode.get(DocumentConstants.Fields.LEXICAL_CONTENT_FIELD);
if (lexicalNode != null) {
// We can also check if lexical sort supported by the collection:
if (!schema.lexicalConfig().enabled()) {
throw SchemaException.Code.LEXICAL_NOT_ENABLED_FOR_COLLECTION.get(errVars(schema));
}
if (sortNode.size() > 1) {
throw ErrorCodeV1.INVALID_SORT_CLAUSE.toApiException(
"if sorting by '%s' no other sort expressions allowed",
DocumentConstants.Fields.LEXICAL_CONTENT_FIELD);
}
if (!lexicalNode.isTextual()) {
throw ErrorCodeV1.INVALID_SORT_CLAUSE.toApiException(
"if sorting by '%s' value must be String, not %s",
DocumentConstants.Fields.LEXICAL_CONTENT_FIELD, JsonUtil.nodeTypeAsString(lexicalNode));
// Typical we need a String, but "old" 1/-1 still allowed: so bail out
// if we got a Number
if (lexicalNode.isNumber()) {
; // do nothing, yet, fall-through to next block
} else {
// We can also check if lexical sort supported by the collection:
if (!schema.lexicalConfig().enabled()) {
throw SchemaException.Code.LEXICAL_NOT_ENABLED_FOR_COLLECTION.get(errVars(schema));
}
if (sortNode.size() > 1) {
throw ErrorCodeV1.INVALID_SORT_CLAUSE.toApiException(
"if sorting by '%s' no other sort expressions allowed",
DocumentConstants.Fields.LEXICAL_CONTENT_FIELD);
}
if (!lexicalNode.isTextual()) {
throw ErrorCodeV1.INVALID_SORT_CLAUSE.toApiException(
"if sorting by '%s' value must be String, not %s",
DocumentConstants.Fields.LEXICAL_CONTENT_FIELD,
JsonUtil.nodeTypeAsString(lexicalNode));
}
return SortClause.immutable(SortExpression.collectionLexicalSort(lexicalNode.textValue()));
}
return SortClause.immutable(SortExpression.collectionLexicalSort(lexicalNode.textValue()));
}
JsonNode vectorNode = sortNode.get(DocumentConstants.Fields.VECTOR_EMBEDDING_FIELD);
if (vectorNode != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,6 @@ public Uni<FindResponse> getDocuments(
QueryExecutor queryExecutor,
String pageState,
IDCollectionFilter additionalIdFilter) {

// ensure we pass failure down if read type is not DOCUMENT or KEY
// COUNT is not supported
switch (readType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,34 @@ void findManyWithLexicalAndOtherFilter() {
.body("data.documents", hasSize(1))
.body("data.documents[0]._id", is("lexical-4"));
}

// [data-api#2109] Non-lexical sort on $lexical column should also work
@Test
void findManyWithNonLexicalSort() {
givenHeadersPostJsonThenOkNoErrors(
keyspaceName,
COLLECTION_WITH_LEXICAL,
"""
{
"find": {
"projection": {"$lexical": 1 },
"sort" : {"$lexical": 1 }
}
}
""")
.body("$", responseIsFindSuccess())
.body("data.documents", hasSize(5))
.body("data.documents[0]._id", is("lexical-4"))
.body("data.documents[1]._id", is("lexical-3"))
.body("data.documents[2]._id", is("lexical-5"))
.body("data.documents[3]._id", is("lexical-2"))
.body("data.documents[4]._id", is("lexical-1"));
}
}

@DisabledIfSystemProperty(named = TEST_PROP_LEXICAL_DISABLED, matches = "true")
@Nested
@Order(2)
@Order(3)
class HappyCasesFindOne {
@Test
void findOneWithLexicalSortBiking() {
Expand Down Expand Up @@ -221,7 +244,7 @@ void findOneWithOnlyLexicalFilter() {

@DisabledIfSystemProperty(named = TEST_PROP_LEXICAL_DISABLED, matches = "true")
@Nested
@Order(3)
@Order(4)
class FailingCasesFindMany {
@Test
void failSortIfLexicalDisabledForCollection() {
Expand Down Expand Up @@ -269,15 +292,15 @@ void failForBadLexicalSortValueType() {
"""
{
"find": {
"sort" : {"$lexical": -1 }
"sort" : {"$lexical": false }
}
}
""")
.body("errors", hasSize(1))
.body("errors[0].errorCode", is("INVALID_SORT_CLAUSE"))
.body(
"errors[0].message",
containsString("if sorting by '$lexical' value must be String, not Number"));
containsString("if sorting by '$lexical' value must be String, not Boolean"));
}

@Test
Expand Down
Loading