22
33import static io .stargate .sgv2 .jsonapi .exception .ErrorFormatters .errFmtApiColumnDef ;
44import static io .stargate .sgv2 .jsonapi .exception .ErrorFormatters .errFmtCqlIdentifier ;
5- import static io .stargate .sgv2 .jsonapi .exception .ErrorFormatters .errFmtJoin ;
65import static io .stargate .sgv2 .jsonapi .exception .ErrorFormatters .errVars ;
76import static io .stargate .sgv2 .jsonapi .util .JsonUtil .arrayNodeToVector ;
87
1716import io .stargate .sgv2 .jsonapi .service .schema .tables .ApiColumnDef ;
1817import io .stargate .sgv2 .jsonapi .service .schema .tables .ApiColumnDefContainer ;
1918import io .stargate .sgv2 .jsonapi .util .CqlIdentifierUtil ;
20- import io .stargate .sgv2 .jsonapi .util .JsonUtil ;
2119import java .util .ArrayList ;
2220import java .util .List ;
2321import java .util .Map ;
@@ -33,53 +31,10 @@ public TableSortClauseBuilder(TableSchemaObject table) {
3331 @ Override
3432 protected SortClause buildClauseFromDefinition (ObjectNode sortNode ) {
3533 // First, resolve the paths to column definitions
36- var sortExprDefs = resolveColumns (sortNode );
37-
38- // Then split into "special" (vector/vectorize, lexical) and regular expressions
39- var lexicalExprs = new ArrayList <SortExpressionDefinition >();
40- var vectorExprs = new ArrayList <SortExpressionDefinition >();
41- var regularExprs = new ArrayList <SortExpressionDefinition >();
42-
43- for (SortExpressionDefinition sortExprDef : sortExprDefs ) {
44- var column = sortExprDef .column ;
45- switch (column .type ().typeName ()) {
46- case VECTOR -> vectorExprs .add (sortExprDef );
47- case ASCII , TEXT -> {
48- if (sortExprDef .sortValue .isTextual ()) {
49- lexicalExprs .add (sortExprDef );
50- } else {
51- regularExprs .add (sortExprDef );
52- }
53- }
54- default -> regularExprs .add (sortExprDef );
55- }
56- }
57-
58- // Lexical(s)? Must have but one expression, cannot be combined with other sorts
59- // Ditto for vector/vectorize
60- if (!lexicalExprs .isEmpty () || !vectorExprs .isEmpty ()) {
61- if (sortExprDefs .size () > 1 ) {
62- throw SortException .Code .CANNOT_SORT_ON_SPECIAL_WITH_OTHERS .get (
63- errVars (
64- schema ,
65- map -> {
66- map .put ("lexicalSorts" , columnsDesc (lexicalExprs ));
67- map .put ("regularSorts" , columnsDesc (regularExprs ));
68- map .put ("vectorSorts" , columnsDesc (vectorExprs ));
69- }));
70- }
71-
72- if (!lexicalExprs .isEmpty ()) {
73- return new SortClause (List .of (buildLexicalSortExpression (lexicalExprs .getFirst ())));
74- }
75-
76- return new SortClause (List .of (buildVectorOrVectorizeSortExpression (vectorExprs .getFirst ())));
77- }
78-
79- // Otherwise, we can build regular sort expression(s)
34+ List <SortExpressionDefinition > sortExprDefs = resolveColumns (sortNode );
8035 final List <SortExpression > sortExpressions = new ArrayList <>();
81- for (SortExpressionDefinition exprDef : regularExprs ) {
82- sortExpressions .add (buildRegularSortExpression ( exprDef ));
36+ for (SortExpressionDefinition sortExprDef : sortExprDefs ) {
37+ sortExpressions .add (buildSortExpression ( sortExprDef ));
8338 }
8439 return new SortClause (sortExpressions );
8540 }
@@ -115,98 +70,32 @@ private List<SortExpressionDefinition> resolveColumns(ObjectNode sortNode) {
11570 return sortExprDefs ;
11671 }
11772
118- protected SortExpression buildLexicalSortExpression (SortExpressionDefinition lexicalExpr ) {
119- // caller validated JsonNode is textual; for now nothing more to validate
120- return SortExpression .tableLexicalSort (lexicalExpr .path (), lexicalExpr .sortValue .textValue ());
121- }
73+ protected SortExpression buildSortExpression (SortExpressionDefinition exprDef ) {
74+ final String path = exprDef .path ();
75+ final JsonNode innerValue = exprDef .sortValue ();
12276
123- protected SortExpression buildVectorOrVectorizeSortExpression (
124- SortExpressionDefinition vectorExpr ) {
125- final String path = vectorExpr .path ();
126- final JsonNode exprValue = vectorExpr .sortValue ();
77+ float [] vectorFloats = tryDecodeBinaryVector (path , innerValue );
12778
128- // So we know we have a Vector column; now can check if value is a binary vector or an array
129- // of floats, or a string to vectorize.
130- // For Vectorize, further checks are done in the TableSortClauseResolver.
131-
132- // First: vector data either as EJSON binary or as JSON Array (of floats)
133- float [] vectorFloats = tryDecodeBinaryVector (path , exprValue );
79+ // handle table vector sort
13480 if (vectorFloats != null ) {
13581 return SortExpression .tableVectorSort (path , vectorFloats );
13682 }
137- if (exprValue instanceof ArrayNode innerArray ) {
83+ if (innerValue instanceof ArrayNode innerArray ) {
84+ // TODO: HACK: quick support for tables, if the value is an array we will assume the
85+ // column is a vector then need to check on table pathway that the sort is correct.
86+ // NOTE: does not check if there are more than one sort expression, the
87+ // TableSortClauseResolver will take care of that so we can get proper ApiExceptions
13888 return SortExpression .tableVectorSort (path , arrayNodeToVector (innerArray ));
13989 }
140-
141- // Otherwise, check if it is a String to vectorize
142- if (exprValue .isTextual ()) {
143- return SortExpression .tableVectorizeSort (path , exprValue .textValue ());
90+ if (innerValue .isTextual ()) {
91+ // TODO: HACK: quick support for tables, if the value is an text we will assume the column
92+ // is a vector and the user wants to do vectorize then need to check on table pathway that
93+ // the sort is correct.
94+ // NOTE: does not check if there are more than one sort expression, the
95+ // TableSortClauseResolver will take care of that so we can get proper ApiExceptions
96+ // this is also why we do not break the look here
97+ return SortExpression .tableVectorizeSort (path , innerValue .textValue ());
14498 }
145-
146- // Otherwise, invalid (cannot be a regular sort as it is a Vector column)
147- throw SortException .Code .INVALID_VECTOR_SORT_EXPRESSION .get (
148- errVars (
149- schema ,
150- map -> {
151- map .put ("jsonType" , JsonUtil .nodeTypeAsString (exprValue ));
152- }));
153- }
154-
155- /**
156- * Helper method to build a "non-special" sort expression for given definition; validates
157- * expression value and builds the {@link SortExpression} object.
158- */
159- private SortExpression buildRegularSortExpression (SortExpressionDefinition exprDef ) {
160- JsonNode sortValue = exprDef .sortValue ();
161-
162- // First: valid cases
163- if (sortValue .isInt ()) {
164- // Yes, we have an integer value. But is it valid?
165- if (sortValue .intValue () == 1 ) {
166- return SortExpression .sort (exprDef .path (), true );
167- }
168- if (sortValue .intValue () == -1 ) {
169- return SortExpression .sort (exprDef .path (), false );
170- }
171- } else if (sortValue .isArray ()) {
172- // Special checking for ArrayNode and String to give less confusing error messages
173-
174- throw SortException .Code .CANNOT_VECTOR_SORT_NON_VECTOR_COLUMNS .get (
175- errVars (
176- schema ,
177- map -> {
178- map .put (
179- "vectorColumns" ,
180- errFmtApiColumnDef (
181- schema .apiTableDef ().allColumns ().filterVectorColumnsToList ()));
182- map .put ("sortColumns" , exprDef .path ());
183- }));
184- } else if (sortValue .isTextual ()) {
185- // We only end up here for non-TEXT/ASCII/VECTOR columns (other cases are handled
186- // by caller and further validated later on)
187- throw SortException .Code .CANNOT_VECTORIZE_SORT_NON_VECTOR_COLUMN .get (
188- errVars (
189- schema ,
190- map -> {
191- map .put (
192- "vectorColumns" ,
193- errFmtApiColumnDef (
194- schema .apiTableDef ().allColumns ().filterVectorColumnsToList ()));
195- map .put ("sortColumns" , exprDef .path ());
196- }));
197- }
198-
199- // Otherwise general failure message wrt use of 1 or -1 for Regular sort expression
200- throw SortException .Code .INVALID_REGULAR_SORT_EXPRESSION .get (
201- errVars (
202- schema ,
203- map -> {
204- map .put ("jsonExpr" , sortValue .toString ());
205- map .put ("jsonType" , JsonUtil .nodeTypeAsString (sortValue ));
206- }));
207- }
208-
209- private String columnsDesc (List <SortExpressionDefinition > sortExprDefs ) {
210- return errFmtJoin (sortExprDefs .stream ().map (SortExpressionDefinition ::path ).toList ());
99+ return super .buildRegularSortExpression (path , innerValue );
211100 }
212101}
0 commit comments