Skip to content

Commit

Permalink
feat: proper : JSon operator
Browse files Browse the repository at this point in the history
- `:` is allowed as delimiter in table names (for INFORMIX)
- otherwise `:` will return a JSON expression and can't be used as column delimiter
- see #1134 and #2001

Signed-off-by: Andreas Reichel <[email protected]>
  • Loading branch information
manticore-projects committed Nov 16, 2024
1 parent 7acf9d5 commit f80800c
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
20 changes: 18 additions & 2 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,7 @@ MergeOperation MergeWhenNotMatched() : {
{ return mi; }
}

// table names seem to allow ":" delimiters, e.g. for Informix see #1134
ObjectNames RelObjectNames() : {
String token = null;
Token delimiter = null;
Expand All @@ -1984,16 +1985,31 @@ ObjectNames RelObjectNames() : {
{ return new ObjectNames(data, delimiters); }
}

// See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx
// column names do not allow ":" delimeters as those represent JSON `GET` operators
ObjectNames ColumnIdentifier() : {
String token = null;
Token delimiter = null;
List<String> data = new ArrayList<String>();
List<String> delimiters = new ArrayList<String>();
} {
token = RelObjectNameExt() { data.add(token); }
(
LOOKAHEAD (2) ( delimiter = "." ) { delimiters.add(delimiter.image); } (( delimiter = "." ) { data.add(null); delimiters.add(delimiter.image); })*
token = RelObjectNameExt2() { data.add(token); }
) *

{ return new ObjectNames(data, delimiters); }
}

// See: http://technet.microsoft.com/en-us/library/ms187879%28v=sql.105%29.aspx
Column Column() #Column :
{
ObjectNames data = null;
ArrayConstructor arrayConstructor = null;
Token tk = null;
}
{
data = RelObjectNames()
data = ColumnIdentifier()
[ LOOKAHEAD(2) <K_COMMENT> tk=<S_CHAR_LITERAL> ]
// @todo: we better should return a SEQUENCE instead of a COLUMN
[ LOOKAHEAD(2) "." <K_NEXTVAL> { data.getNames().add("nextval"); } ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
package net.sf.jsqlparser.expression;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.statement.select.PlainSelect;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
Expand Down Expand Up @@ -40,7 +42,15 @@ void testIssue1792() throws JSQLParserException {
@Test
void testSnowflakeGetOperator() throws JSQLParserException {
String sqlStr = "SELECT v:'attr[0].name' FROM vartab;";
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
PlainSelect st = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true);
Assertions.assertInstanceOf(JsonExpression.class, st.getSelectItem(0).getExpression());
}

@Test
void testDataBricksExtractPathOperator() throws JSQLParserException {
String sqlStr = "SELECT C1:PRICE J FROM VALUES('{\"price\":5}')AS T(C1)";
PlainSelect st = (PlainSelect) assertSqlCanBeParsedAndDeparsed(sqlStr, true);
Assertions.assertInstanceOf(JsonExpression.class, st.getSelectItem(0).getExpression());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
package net.sf.jsqlparser.statement.select;

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.schema.Column;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.util.List;
Expand All @@ -24,12 +27,13 @@ public class ExpressionDelimiterTest {
public void testColumnWithDifferentDelimiters() throws JSQLParserException {
String statement = "SELECT mytable.mycolumn:parent:child FROM mytable";
PlainSelect parsed = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement);
Column column = parsed.getSelectItem(0).getExpression(Column.class);
assertEquals(":", column.getTableDelimiter());
assertEquals(List.of(":", "."), column.getTable().getNamePartDelimiters());
Assertions.assertInstanceOf(JsonExpression.class, parsed.getSelectItem(0).getExpression());
}

// I don't know what kind of Operator ".:." shall present
// please rework
@Test
@Disabled
public void testColumnWithEmptyNameParts() throws JSQLParserException {
String statement = "SELECT mytable.:.child FROM mytable";
PlainSelect parsed = (PlainSelect) assertSqlCanBeParsedAndDeparsed(statement);
Expand Down

0 comments on commit f80800c

Please sign in to comment.