Skip to content

Commit

Permalink
support ON DUPLICATE KEY in the parser
Browse files Browse the repository at this point in the history
  • Loading branch information
mfussenegger committed Jan 22, 2015
1 parent 819275f commit 436c127
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 14 deletions.
12 changes: 10 additions & 2 deletions sql-parser/src/main/java/io/crate/sql/parser/Statement.g
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ tokens {
ARRAY_NOT_LIKE;
ARRAY_LITERAL;
OBJECT_LITERAL;
ON_DUP_KEY;
KEY_VALUE;
MATCH;
MATCH_PREDICATE_IDENT;
Expand Down Expand Up @@ -586,7 +587,7 @@ specialFunction
| CURRENT_TIMESTAMP ('(' integer ')')? -> ^(CURRENT_TIMESTAMP integer?)
| SUBSTRING '(' expr FROM expr (FOR expr)? ')' -> ^(FUNCTION_CALL ^(QNAME IDENT["substr"]) expr expr expr?)
| EXTRACT '(' ident FROM expr ')' -> ^(EXTRACT ident expr)
| CAST '(' expr AS dataType ')' -> ^(CAST expr dataType)
| CAST '(' expr AS dataType ')' -> ^(CAST expr dataType)
;


Expand Down Expand Up @@ -745,7 +746,11 @@ objectKeyValue
;

insertStmt
: INSERT INTO table identList? insertSource -> ^(INSERT insertSource table identList?)
: INSERT INTO table identList? insertSource onDuplicateKey? -> ^(INSERT insertSource table identList? onDuplicateKey?)
;

onDuplicateKey
: ON DUPLICATE KEY UPDATE assignmentList -> ^(ON_DUP_KEY assignmentList)
;

insertSource
Expand Down Expand Up @@ -1021,6 +1026,7 @@ nonReserved
| PRECEDING | RANGE | REFRESH | ROW | ROWS | SCHEMA | SCHEMAS | SECOND
| SHARDS | SHOW | STRICT | SYSTEM | TABLES | TABLESAMPLE | TEXT | TIME
| TIMESTAMP | TO | TOKENIZER | TOKEN_FILTERS | TYPE | VIEW | YEAR
| DUPLICATE | KEY | VALUES
;

SELECT: 'SELECT';
Expand Down Expand Up @@ -1157,6 +1163,8 @@ INTO: 'INTO';
VALUES: 'VALUES';
DELETE: 'DELETE';
UPDATE: 'UPDATE';
KEY: 'KEY';
DUPLICATE: 'DUPLICATE';
SET: 'SET';
RESET: 'RESET';
COPY: 'COPY';
Expand Down
20 changes: 16 additions & 4 deletions sql-parser/src/main/java/io/crate/sql/parser/StatementBuilder.g
Original file line number Diff line number Diff line change
Expand Up @@ -657,16 +657,28 @@ dropTable returns [Statement value]
;

insert returns [Statement value]
: ^(INSERT values=insertValues namedTable cols=columnIdentList?)
: ^(INSERT values=insertValues namedTable cols=columnIdentList? onDuplicateKey?)
{
$value = new InsertFromValues($namedTable.value, $values.value, $cols.value);
$value = new InsertFromValues(
$namedTable.value,
$values.value,
$cols.value,
$onDuplicateKey.value);
}
| ^(INSERT subQuery=query namedTable cols=columnIdentList?)
| ^(INSERT subQuery=query namedTable cols=columnIdentList? onDuplicateKey?)
{
$value = new InsertFromSubquery($namedTable.value, $subQuery.value, $cols.value);
$value = new InsertFromSubquery(
$namedTable.value,
$subQuery.value,
$cols.value,
$onDuplicateKey.value);
}
;

onDuplicateKey returns [List<Assignment> value]
: ^(ON_DUP_KEY assignmentList) { $value = $assignmentList.value; }
;

insertValues returns [List<ValuesList> value = new ArrayList<>()]
: ^(INSERT_VALUES (valuesList { $value.add($valuesList.value); })+)
;
Expand Down
11 changes: 9 additions & 2 deletions sql-parser/src/main/java/io/crate/sql/tree/Insert.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

package io.crate.sql.tree;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;

Expand All @@ -31,12 +32,14 @@ public abstract class Insert extends Statement {

protected final Table table;

protected final List<Assignment> onDuplicateKeyAssignments;
protected final List<String> columns;


public Insert(Table table, @Nullable List<String> columns) {
public Insert(Table table, @Nullable List<String> columns, @Nullable List<Assignment> onDuplicateKeyAssignments) {
this.table = table;
this.columns = Objects.firstNonNull(columns, ImmutableList.<String>of());
this.onDuplicateKeyAssignments = MoreObjects.firstNonNull(onDuplicateKeyAssignments, ImmutableList.<Assignment>of());
this.columns = MoreObjects.firstNonNull(columns, ImmutableList.<String>of());
}

public Table table() {
Expand All @@ -47,6 +50,10 @@ public List<String> columns() {
return columns;
}

public List<Assignment> onDuplicateKeyAssignments() {
return onDuplicateKeyAssignments;
}

@Override
public int hashCode() {
return Objects.hashCode(table, columns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

package io.crate.sql.tree;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;

import javax.annotation.Nullable;
Expand All @@ -30,8 +31,11 @@ public class InsertFromSubquery extends Insert {

private final Query subQuery;

public InsertFromSubquery(Table table, Query subQuery, @Nullable List<String> columns) {
super(table, columns);
public InsertFromSubquery(Table table,
Query subQuery,
@Nullable List<String> columns,
@Nullable List<Assignment> onDuplicateKeyAssignments) {
super(table, columns, onDuplicateKeyAssignments);
this.subQuery = subQuery;
}

Expand Down Expand Up @@ -59,7 +63,7 @@ public boolean equals(Object o) {

@Override
public String toString() {
return Objects.toStringHelper(this)
return MoreObjects.toStringHelper(this)
.add("table", table)
.add("columns", columns)
.add("subquery", subQuery)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ public class InsertFromValues extends Insert {
private final List<ValuesList> valuesLists;
private final int maxValuesLength;

public InsertFromValues(Table table, List<ValuesList> valuesLists, @Nullable List<String> columns) {
super(table, columns);
public InsertFromValues(Table table,
List<ValuesList> valuesLists,
@Nullable List<String> columns,
@Nullable List<Assignment> onDuplicateKeyAssignments) {
super(table, columns, onDuplicateKeyAssignments);
this.valuesLists = valuesLists;

int i = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ public void testStatementBuilder()
printStatement("select * from t where 'source' !~ 'pattern'");
printStatement("select * from t where source_column ~ pattern_column");
printStatement("select * from t where ? !~ ?");

printStatement("insert into t (a, b) values (1, 2) on duplicate key update a = a + 1");
printStatement("insert into t (a, b) values (1, 2) on duplicate key update a = a + 1, b = 3");
printStatement("insert into t (a, b) values (1, 2), (3, 4) on duplicate key update a = values (a) + 1, b = 4");
printStatement("insert into t (a, b) values (1, 2), (3, 4) on duplicate key update a = values (a) + 1, b = values(b) - 2");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ public InsertFromSubQueryAnalyzer(AnalysisMetaData analysisMetaData, ParameterCo

@Override
public AnalyzedStatement visitInsertFromSubquery(InsertFromSubquery node, Void context) {

if (!node.onDuplicateKeyAssignments().isEmpty()) {
throw new UnsupportedOperationException("ON DUPLICATE KEY UPDATE clause is not supported");
}
TableInfo tableInfo = analysisMetaData.referenceInfos().getTableInfoUnsafe(TableIdent.of(node.table()));

SelectStatementAnalyzer selectStatementAnalyzer = new SelectStatementAnalyzer(analysisMetaData, parameterContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ public InsertFromValuesAnalyzer(AnalysisMetaData analysisMetaData, ParameterCont

@Override
public AnalyzedStatement visitInsertFromValues(InsertFromValues node, Void context) {
if (!node.onDuplicateKeyAssignments().isEmpty()) {
throw new UnsupportedOperationException("ON DUPLICATE KEY UPDATE clause is not supported");
}
TableInfo tableInfo = analysisMetaData.referenceInfos().getTableInfoUnsafe(TableIdent.of(node.table()));
TableRelation tableRelation = new TableRelation(tableInfo);
validateTable(tableInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,9 @@ public void testImplicitTypeCasting() throws Exception {
Function castFunction = (Function)outputSymbols.get(1);
assertThat(castFunction.info().ident().name(), is(ToStringFunction.NAME));
}

@Test (expected = UnsupportedOperationException.class)
public void testInsertFromValuesWithOnDuplicateKey() throws Exception {
analyze("insert into users (id, name) (select id, name from users) on duplicate key update name = substr(values (name), 1, 1)");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -786,5 +786,11 @@ public void testInvalidColumnName() throws Exception {
expectedException.expectMessage("column name \"newCol[\" is invalid");
analyze("insert into users (\"newCol[\") values(test)");
}

@Test
public void testInsertFromValuesWithOnDuplicateKey() throws Exception {
expectedException.expect(UnsupportedOperationException.class);
analyze("insert into users (id, name) values (1, 'Arthur') on duplicate key update name = substr(values (name), 1, 1)");
}
}

0 comments on commit 436c127

Please sign in to comment.