@@ -166,6 +166,46 @@ PARSER_END(CCJSqlParser)
166166TOKEN_MGR_DECLS : {
167167 public FeatureConfiguration configuration = new FeatureConfiguration();
168168
169+ // Identify the index of the quoting/escaping tokens
170+ public int charLiteralIndex = -1;
171+ public int squaredBracketOpenIndex = -1;
172+ {
173+ for (int i=0;i<CCJSqlParserConstants.tokenImage.length;i++) {
174+ if ( CCJSqlParserConstants.tokenImage[i].equals("<S_CHAR_LITERAL>") ) {
175+ charLiteralIndex = i;
176+ break;
177+ }
178+ }
179+ for (int i=0;i<CCJSqlParserConstants.tokenImage.length;i++) {
180+ if (CCJSqlParserConstants.tokenImage[i].equals("\"[\"")) {
181+ squaredBracketOpenIndex = i;
182+ break;
183+ }
184+ }
185+ }
186+
187+ // Finds first occurrence of "\\'"
188+ public static int indexOfSequence(String s, String target) {
189+ int len = s.length();
190+ for (int i = 0; i < len - 1; i++) {
191+ if (s.charAt(i) == '\\' && s.charAt(i + 1) == '\'') {
192+ return i;
193+ }
194+ }
195+ return -1;
196+ }
197+
198+ // Finds last occurrence of "\\''"
199+ public static int lastIndexOfSequence(String s, String target) {
200+ int len = s.length();
201+ for (int i = len - 3; i >= 0; i--) {
202+ if (s.charAt(i) == '\\' && s.charAt(i + 1) == '\'' && s.charAt(i + 2) == '\'') {
203+ return i;
204+ }
205+ }
206+ return -1;
207+ }
208+
169209 public void CommonTokenAction(Token t)
170210 {
171211 t.absoluteBegin = getCurrentTokenAbsolutePosition();
@@ -614,6 +654,7 @@ TOKEN : /* Statement Separators */
614654TOKEN : /* Operators */
615655{
616656 <OP_GREATERTHANEQUALS: ">" (<WHITESPACE>)* "=">
657+ | <OP_COSINESIMILARITY: "<=>">
617658| <OP_MINORTHANEQUALS: "<" (<WHITESPACE>)* "=">
618659| <OP_NOTEQUALSSTANDARD: "<" (<WHITESPACE>)* ">">
619660| <OP_NOTEQUALSBANG: "!" (<WHITESPACE>)* "=">
@@ -738,33 +779,33 @@ TOKEN:
738779 // which contains the <SPECIAL_ESC>, then we will need to
739780 // 1) break the <S_CHAR_LITERAL> at <SPECIAL_ESC> close it with a "'"
740781 // 2) continue tokenizing after that <SPECIAL_ESC> with a new <S_CHAR_LITERAL> or any other Token
741- if ( !configuration.getAsBoolean(Feature.allowBackslashEscapeCharacter) && matchedToken.image.contains("\\'") ) {
742- matchedToken.image = image.substring( 0, image.indexOf("\\'") + 1 ) + "'";
743- for (int i=0;i<CCJSqlParserConstants.tokenImage.length;i++) {
744- if ( CCJSqlParserConstants.tokenImage[i].equals("<S_CHAR_LITERAL>") ) {
745- matchedToken.kind = i;
746- }
782+ boolean allowEscape = configuration.getAsBoolean(Feature.allowBackslashEscapeCharacter);
783+ String img = matchedToken.image;
784+ int pos;
785+ if (!allowEscape) {
786+ pos = indexOfSequence(img, "\\'");
787+ if (pos > 0) {
788+ matchedToken.image = image.substring(0, pos + 1) + "'";
789+ matchedToken.kind = charLiteralIndex;
790+ input_stream.backup(image.length() - matchedToken.image.length());
747791 }
748- input_stream.backup(image.length() - matchedToken.image.length() );
749- } else if ( configuration.getAsBoolean(Feature.allowBackslashEscapeCharacter) && matchedToken.image.contains("\\''") ) {
750- matchedToken.image = image.substring( 0, image.lastIndexOf("\\'") + 3);
751- for (int i=0;i<CCJSqlParserConstants.tokenImage.length;i++) {
752- if ( CCJSqlParserConstants.tokenImage[i].equals("<S_CHAR_LITERAL>") ) {
753- matchedToken.kind = i;
754- }
792+ } else {
793+ pos = lastIndexOfSequence(img, "\\''");
794+ if (pos > 0) {
795+ matchedToken.image = image.substring(0, pos + 3);
796+ matchedToken.kind = charLiteralIndex;
797+ input_stream.backup(image.length() - matchedToken.image.length());
755798 }
756- input_stream.backup(image.length() - matchedToken.image.length() );
757- }
799+ }
758800 }
759801| < S_QUOTED_IDENTIFIER: "\"" ( "\"\"" | ~["\n","\r","\""])* "\"" | "$$" (~["$"])* "$$" | ("`" (~["\n","\r","`"])+ "`") | ( "[" (~["\n","\r","]"])* "]" ) >
760802 {
761- if ( !configuration.getAsBoolean(Feature.allowSquareBracketQuotation) && matchedToken.image.charAt(0) == '[' ) {
803+ if ( !configuration.getAsBoolean(Feature.allowSquareBracketQuotation)
804+ && matchedToken.image.charAt(0) == '[' ) {
805+
762806 matchedToken.image = "[";
763- for (int i=0;i<CCJSqlParserConstants.tokenImage.length;i++) {
764- if (CCJSqlParserConstants.tokenImage[i].equals("\"[\"")) {
765- matchedToken.kind = i;
766- }
767- }
807+ // `squaredBracketOpenIndex` defined in TokenManagerDeclaration above
808+ matchedToken.kind = squaredBracketOpenIndex;
768809 input_stream.backup(image.length() - 1);
769810 }
770811 }
@@ -4614,7 +4655,7 @@ Expression RegularCondition() #RegularCondition:
46144655 | "-#" { result = new JsonOperator("-#"); }
46154656 | "<->" { result = new GeometryDistance("<->"); }
46164657 | "<#>" { result = new GeometryDistance("<#>"); }
4617- | "<=>" { result = new CosineSimilarity(); }
4658+ | <OP_COSINESIMILARITY> { result = new CosineSimilarity(); }
46184659 )
46194660
46204661 ( LOOKAHEAD(2) <K_PRIOR> rightExpression=ComparisonItem() { oraclePrior = EqualsTo.ORACLE_PRIOR_END; }
0 commit comments