1111
1212import java .util .stream .Stream ;
1313import net .sf .jsqlparser .JSQLParserException ;
14+ import net .sf .jsqlparser .expression .TernaryExpression ;
15+ import net .sf .jsqlparser .expression .Function ;
16+ import net .sf .jsqlparser .statement .piped .FromQuery ;
17+ import net .sf .jsqlparser .statement .piped .SelectPipeOperator ;
1418import net .sf .jsqlparser .expression .NotExpression ;
1519import net .sf .jsqlparser .expression .MapExpression ;
1620import net .sf .jsqlparser .expression .JdbcNamedParameter ;
2428import net .sf .jsqlparser .schema .Column ;
2529import net .sf .jsqlparser .schema .Table ;
2630import net .sf .jsqlparser .statement .select .PlainSelect ;
31+ import net .sf .jsqlparser .statement .select .SampleClause ;
2732import net .sf .jsqlparser .statement .select .WithItem ;
2833import org .junit .jupiter .api .Test ;
2934import org .junit .jupiter .params .ParameterizedTest ;
@@ -77,6 +82,26 @@ public void testGroupsAsIdentifier() throws JSQLParserException {
7782 assertSqlCanBeParsedAndDeparsed ("CREATE TABLE mytable (groups INT)" , true );
7883 }
7984
85+ // sample and extend are non-reserved in the common dialects and reach the
86+ // parser as ordinary table and column names in downstream rewriting tools.
87+ @ Test
88+ public void testSampleExtendAsIdentifier () throws JSQLParserException {
89+ assertSqlCanBeParsedAndDeparsed ("SELECT sample, extend FROM mytable" , true );
90+ assertSqlCanBeParsedAndDeparsed ("SELECT mytable.extend FROM mytable" , true );
91+ assertSqlCanBeParsedAndDeparsed ("SELECT * FROM mytable WHERE extend = 'x'" , true );
92+ assertSqlCanBeParsedAndDeparsed ("UPDATE mytable SET sample = 1, extend = 'x' WHERE id = 1" ,
93+ true );
94+ assertSqlCanBeParsedAndDeparsed ("INSERT INTO mytable (sample, extend) VALUES (1, 'x')" ,
95+ true );
96+ assertSqlCanBeParsedAndDeparsed ("SELECT * FROM sample" , true );
97+ assertSqlCanBeParsedAndDeparsed ("DELETE FROM sample WHERE extend = 'x'" , true );
98+ assertSqlCanBeParsedAndDeparsed ("INSERT INTO sample (extend) VALUES ('x')" , true );
99+ assertSqlCanBeParsedAndDeparsed ("SELECT a AS sample, b AS extend FROM mytable" , true );
100+ }
101+
102+ @ ParameterizedTest
103+ @ ValueSource (strings = {"sample" , "extend" , "SaMpLe" , "ExTeNd" })
104+ void testSampleExtendImplicitAliases (String keyword ) throws JSQLParserException {
80105 // exists is a non-reserved keyword in the common dialects and reaches the
81106 // parser as an ordinary column name in downstream rewriting tools.
82107 @ Test
@@ -116,7 +141,7 @@ void testExistsImplicitAliases(String keyword) throws JSQLParserException {
116141 }
117142
118143 @ ParameterizedTest
119- @ ValueSource (strings = {"exists" , "ExIsTs" })
144+ @ ValueSource (strings = {"exists" , "ExIsTs" , "sample" , "extend" , "SaMpLe" , "ExTeNd" })
120145 void testExistsCte (String keyword ) throws JSQLParserException {
121146 PlainSelect select = (PlainSelect ) assertSqlCanBeParsedAndDeparsed (
122147 "WITH " + keyword + "(x) AS (SELECT 1) SELECT x FROM " + keyword , true );
@@ -130,7 +155,7 @@ void testExistsCte(String keyword) throws JSQLParserException {
130155 }
131156
132157 @ ParameterizedTest
133- @ ValueSource (strings = {"exists" , "ExIsTs" })
158+ @ ValueSource (strings = {"exists" , "ExIsTs" , "sample" , "extend" , "SaMpLe" , "ExTeNd" })
134159 void testExistsExpressionContexts (String keyword ) throws JSQLParserException {
135160 PlainSelect select = (PlainSelect ) CCJSqlParserUtil .parse (
136161 "SELECT ALL " + keyword + " FROM mytable" );
@@ -142,7 +167,7 @@ void testExistsExpressionContexts(String keyword) throws JSQLParserException {
142167 }
143168
144169 @ ParameterizedTest
145- @ ValueSource (strings = {"exists" , "ExIsTs" })
170+ @ ValueSource (strings = {"exists" , "ExIsTs" , "sample" , "extend" , "SaMpLe" , "ExTeNd" })
146171 void testExistsTernaryOperand (String keyword ) throws JSQLParserException {
147172 PlainSelect select = (PlainSelect ) assertSqlCanBeParsedAndDeparsed (
148173 "SELECT flag ? " + keyword + " : 0 FROM mytable" , true );
@@ -152,6 +177,38 @@ void testExistsTernaryOperand(String keyword) throws JSQLParserException {
152177 .getColumnName ());
153178 }
154179
180+ @ ParameterizedTest
181+ @ ValueSource (strings = {"SAMPLE (10)" , "SAMPLE BLOCK (10) SEED (1)" ,
182+ "SAMPLE 0.1 OFFSET 1000" , "USING SAMPLE 10 PERCENT (BERNOULLI)" ,
183+ "TABLESAMPLE SYSTEM (10)" })
184+ void testSampleClauseStaysClause (String clause ) throws JSQLParserException {
185+ PlainSelect select = (PlainSelect ) assertSqlCanBeParsedAndDeparsed (
186+ "SELECT * FROM mytable " + clause , true );
187+ Table table = assertInstanceOf (Table .class , select .getFromItem ());
188+ assertNull (table .getAlias ());
189+ SampleClause sample = table .getSampleClause ();
190+ assertNotNull (sample );
191+ assertEquals (" " + clause , sample .toString ());
192+ }
193+
194+ @ ParameterizedTest
195+ @ ValueSource (strings = {"sample" , "extend" , "SaMpLe" , "ExTeNd" })
196+ void testSampleExtendPipeExpression (String keyword ) throws JSQLParserException {
197+ FromQuery query = (FromQuery ) assertSqlCanBeParsedAndDeparsed (
198+ "FROM " + keyword + " |> EXTEND " + keyword + " AS x" , true );
199+ SelectPipeOperator operator = assertInstanceOf (SelectPipeOperator .class ,
200+ query .getPipeOperators ().get (0 ));
201+ assertEquals ("EXTEND" , operator .getOperatorName ());
202+ assertEquals (keyword , assertInstanceOf (Column .class ,
203+ operator .getSelectItems ().get (0 ).getExpression ()).getColumnName ());
204+ assertSqlCanBeParsedAndDeparsed (
205+ "FROM mytable |> EXTEND " + keyword + "(x) AS x" , true );
206+ PlainSelect select = (PlainSelect ) CCJSqlParserUtil .parse (
207+ "SELECT ALL " + keyword + "(x) FROM mytable" );
208+ assertEquals (keyword , assertInstanceOf (Function .class ,
209+ select .getSelectItem (0 ).getExpression ()).getName ());
210+ }
211+
155212 @ Test
156213 void testExistsColumnWithOracleJoin () throws JSQLParserException {
157214 PlainSelect select = (PlainSelect ) assertSqlCanBeParsedAndDeparsed (
@@ -253,6 +310,8 @@ void testExistsBeforeNestedTernary() throws JSQLParserException {
253310 assertEquals ("exists" , assertInstanceOf (Column .class , map .getEntries ().get (0 ).getKey ())
254311 .getColumnName ());
255312 assertInstanceOf (TernaryExpression .class , map .getEntries ().get (0 ).getValue ());
313+ }
314+
256315 // ERRORS introduces Exasol's IMPORT/EXPORT error clauses but is an ordinary name elsewhere,
257316 // e.g. a DuckDB column holding the errors of an upstream step.
258317 @ Test
0 commit comments