Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/select/First.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* #%L
* JSQLParser library
* %%
* Copyright (C) 2015 JSQLParser
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
package net.sf.jsqlparser.statement.select;

import net.sf.jsqlparser.expression.JdbcParameter;

/**
* A FIRST clause in the form [FIRST row_count] the alternative form
* [LIMIT row_count] is also supported.
*
* Initial implementation was done for informix special syntax:
* http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0156.htm
*/
public class First {
public enum Keyword {
FIRST,
LIMIT
}

private Keyword keyword;
private Long rowCount;
private JdbcParameter jdbcParameter;

public Long getRowCount() {
return rowCount;
}

public void setRowCount(Long rowCount) {
this.rowCount = rowCount;
}

public JdbcParameter getJdbcParameter() {
return jdbcParameter;
}

public void setJdbcParameter(JdbcParameter jdbcParameter) {
this.jdbcParameter = jdbcParameter;
}

public Keyword getKeyword() {
return keyword;
}

public void setKeyword(Keyword keyword) {
this.keyword = keyword;
}

@Override
public String toString() {
String result = keyword.name() + " ";

result += jdbcParameter != null ? jdbcParameter.toString() : rowCount;

return result;
}
}
27 changes: 27 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/select/PlainSelect.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class PlainSelect implements SelectBody {
private Limit limit;
private Offset offset;
private Fetch fetch;
private Skip skip;
private First first;
private Top top;
private OracleHierarchicalExpression oracleHierarchical = null;
private boolean oracleSiblings = false;
Expand Down Expand Up @@ -170,6 +172,22 @@ public void setTop(Top top) {
this.top = top;
}

public Skip getSkip() {
return skip;
}

public void setSkip(Skip skip) {
this.skip = skip;
}

public First getFirst() {
return first;
}

public void setFirst(First first) {
this.first = first;
}

public Distinct getDistinct() {
return distinct;
}
Expand Down Expand Up @@ -246,6 +264,15 @@ public String toString() {
sql.append("(");
}
sql.append("SELECT ");

if (skip != null) {
sql.append(skip).append(" ");
}

if (first != null) {
sql.append(first).append(" ");
}

if (distinct != null) {
sql.append(distinct).append(" ");
}
Expand Down
61 changes: 61 additions & 0 deletions src/main/java/net/sf/jsqlparser/statement/select/Skip.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* #%L
* JSQLParser library
* %%
* Copyright (C) 2015 JSQLParser
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
package net.sf.jsqlparser.statement.select;

import net.sf.jsqlparser.expression.JdbcParameter;

/**
* A skip clause in the form [SKIP row_count]
*
* Initial implementation was done for informix special syntax:
* http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0156.htm
*/
public class Skip {

private Long rowCount;
private JdbcParameter jdbcParameter;

public Long getRowCount() {
return rowCount;
}

public void setRowCount(Long rowCount) {
this.rowCount = rowCount;
}

public JdbcParameter getJdbcParameter() {
return jdbcParameter;
}

public void setJdbcParameter(JdbcParameter jdbcParameter) {
this.jdbcParameter = jdbcParameter;
}

@Override
public String toString() {
String result = "SKIP ";

result += jdbcParameter != null ? jdbcParameter.toString() : rowCount;

return result;
}
}
11 changes: 11 additions & 0 deletions src/main/java/net/sf/jsqlparser/util/deparser/SelectDeParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ public void visit(PlainSelect plainSelect) {
buffer.append("(");
}
buffer.append("SELECT ");

Skip skip = plainSelect.getSkip();
if (skip != null) {
buffer.append(skip).append(" ");
}

First first = plainSelect.getFirst();
if (first != null) {
buffer.append(first).append(" ");
}

if (plainSelect.getDistinct() != null) {
buffer.append("DISTINCT ");
if (plainSelect.getDistinct().getOnSelectItems() != null) {
Expand Down
43 changes: 42 additions & 1 deletion src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_KEEP:"KEEP">
| <K_GROUP_CONCAT:"GROUP_CONCAT">
| <K_SEPARATOR:"SEPARATOR">
| <K_SKIP: "SKIP">
}

TOKEN : /* Numeric Constants */
Expand Down Expand Up @@ -638,13 +639,19 @@ PlainSelect PlainSelect():
Offset offset = null;
Fetch fetch = null;
Top top = null;
Skip skip = null;
First first = null;
OracleHierarchicalExpression oracleHierarchicalQueryClause = null;
List<Table> intoTables = null;
Table updateTable = null;
}
{
<K_SELECT>

[LOOKAHEAD(<K_SKIP> (<S_LONG> | "?")) skip = Skip() { plainSelect.setSkip(skip); } ]

[LOOKAHEAD((<K_FIRST> | <K_LIMIT>) (<S_LONG> | "?")) first = First() { plainSelect.setFirst(first); } ]

[
<K_ALL>
|
Expand All @@ -656,7 +663,6 @@ PlainSelect PlainSelect():

[top = Top() { plainSelect.setTop(top); } ]


selectItems=SelectItemsList()

[intoTables = IntoClause() { plainSelect.setIntoTables(intoTables); } ]
Expand Down Expand Up @@ -1299,6 +1305,41 @@ Top Top():
}
}

// according to http://www-01.ibm.com/support/knowledgecenter/SSGU8G_12.1.0/com.ibm.sqls.doc/ids_sqs_0156.htm
Skip Skip():
{
Skip skip = new Skip();
Token token = null;
}
{
<K_SKIP>
(
token=<S_LONG> { skip.setRowCount(Long.parseLong(token.image)); }
| "?" { skip.setJdbcParameter(new JdbcParameter()); } [ LOOKAHEAD(2) token = <S_LONG> { skip.getJdbcParameter().setIndex(Integer.valueOf(token.image)); } ]
)
{
return skip;
}
}

First First():
{
First first = new First();
Token token = null;
}
{
( <K_FIRST> { first.setKeyword(First.Keyword.FIRST); }
| <K_LIMIT> { first.setKeyword(First.Keyword.LIMIT); }
)
(
token=<S_LONG> { first.setRowCount(Long.parseLong(token.image)); }
| "?" { first.setJdbcParameter(new JdbcParameter()); } [ LOOKAHEAD(2) token = <S_LONG> { first.getJdbcParameter().setIndex(Integer.valueOf(token.image)); } ]
)
{
return first;
}
}

Expression Expression() #Expression :
{
Expression retval = null;
Expand Down
86 changes: 86 additions & 0 deletions src/test/java/net/sf/jsqlparser/test/select/SelectTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,93 @@ public void testTopWithParenthesis() throws JSQLParserException {

assertStatementCanBeDeparsedAs(select, statement);
}

public void testSkip() throws JSQLParserException {
final String firstColumnName = "alias.columnName1";
final String secondColumnName = "alias.columnName2";
final String statement = "SELECT SKIP 5 " + firstColumnName + ", " + secondColumnName + " FROM schemaName.tableName alias ORDER BY " + secondColumnName + " DESC";
final Select select = (Select) parserManager.parse(new StringReader(statement));

final PlainSelect selectBody = (PlainSelect) select.getSelectBody();

final Skip skip = selectBody.getSkip();
assertEquals((long) 5, (long) skip.getRowCount());
assertNull(skip.getJdbcParameter());

final List<SelectItem> selectItems = selectBody.getSelectItems();
assertEquals(2, selectItems.size());
assertEquals(firstColumnName, selectItems.get(0).toString());
assertEquals(secondColumnName, selectItems.get(1).toString());

assertStatementCanBeDeparsedAs(select, statement);
}

public void testFirst() throws JSQLParserException {
final String firstColumnName = "alias.columnName1";
final String secondColumnName = "alias.columnName2";
final String statement = "SELECT FIRST 5 " + firstColumnName + ", " + secondColumnName + " FROM schemaName.tableName alias ORDER BY " + secondColumnName + " DESC";
final Select select = (Select) parserManager.parse(new StringReader(statement));

final PlainSelect selectBody = (PlainSelect) select.getSelectBody();

final First limit = selectBody.getFirst();
assertEquals((long) 5, (long) limit.getRowCount());
assertNull(limit.getJdbcParameter());
assertEquals(First.Keyword.FIRST, limit.getKeyword());

final List<SelectItem> selectItems = selectBody.getSelectItems();
assertEquals(2, selectItems.size());
assertEquals(firstColumnName, selectItems.get(0).toString());
assertEquals(secondColumnName, selectItems.get(1).toString());

assertStatementCanBeDeparsedAs(select, statement);
}

public void testFirstWithKeywordLimit() throws JSQLParserException {
final String firstColumnName = "alias.columnName1";
final String secondColumnName = "alias.columnName2";
final String statement = "SELECT LIMIT ? " + firstColumnName + ", " + secondColumnName + " FROM schemaName.tableName alias ORDER BY " + secondColumnName + " DESC";
final Select select = (Select) parserManager.parse(new StringReader(statement));

final PlainSelect selectBody = (PlainSelect) select.getSelectBody();

final First limit = selectBody.getFirst();
assertNull(limit.getRowCount());
assertNotNull(limit.getJdbcParameter());
assertNull(limit.getJdbcParameter().getIndex());
assertEquals(First.Keyword.LIMIT, limit.getKeyword());

final List<SelectItem> selectItems = selectBody.getSelectItems();
assertEquals(2, selectItems.size());
assertEquals(firstColumnName, selectItems.get(0).toString());
assertEquals(secondColumnName, selectItems.get(1).toString());

assertStatementCanBeDeparsedAs(select, statement);
}

public void testSkipFirst() throws JSQLParserException {
final String statement = "SELECT SKIP ?1 FIRST ?2 c1, c2 FROM t1";
final Select select = (Select) parserManager.parse(new StringReader(statement));

final PlainSelect selectBody = (PlainSelect) select.getSelectBody();

final Skip skip = selectBody.getSkip();
assertNotNull(skip.getJdbcParameter());
assertNotNull(skip.getJdbcParameter().getIndex());
assertEquals((int) 1, (int) skip.getJdbcParameter().getIndex());
final First first = selectBody.getFirst();
assertNotNull(first.getJdbcParameter());
assertNotNull(first.getJdbcParameter().getIndex());
assertEquals((int) 2, (int) first.getJdbcParameter().getIndex());

final List<SelectItem> selectItems = selectBody.getSelectItems();
assertEquals(2, selectItems.size());
assertEquals("c1", selectItems.get(0).toString());
assertEquals("c2", selectItems.get(1).toString());

assertStatementCanBeDeparsedAs(select, statement);
}

public void testSelectItems() throws JSQLParserException {
String statement = "SELECT myid AS MYID, mycol, tab.*, schema.tab.*, mytab.mycol2, myschema.mytab.mycol, myschema.mytab.* FROM mytable WHERE mytable.col = 9";
Select select = (Select) parserManager.parse(new StringReader(statement));
Expand Down