DATAJDBC-335 - Add DSL and renderer for Insert, Update, and Delete.
We now provide Statement builders for Insert, Update, and Delete statements.
Table myTable = SQL.table("mytable");
Insert insert = StatementBuilder.insert().into(myTable).values(SQL.bindMarker()).build();
Update update = StatementBuilder.update(table).set(myTable.column("foo").set(SQL.bindMarker())).build();
Delete delete = StatementBuilder.delete().from(table).where(myTable.column("foo").isEqualTo(SQL.literal("bar"))).build();
Original pull request: #121.
This commit is contained in:
committed by
Jens Schauder
parent
2aa44a38fd
commit
a11c121407
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Validator for statements to import columns.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
abstract class AbstractImportValidator implements Visitor {
|
||||
|
||||
Set<Table> requiredByWhere = new HashSet<>();
|
||||
Set<Table> from = new HashSet<>();
|
||||
Visitable parent;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Visitor#enter(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public void enter(Visitable segment) {
|
||||
|
||||
if (segment instanceof Table && parent instanceof From) {
|
||||
from.add((Table) segment);
|
||||
}
|
||||
|
||||
if (segment instanceof Where) {
|
||||
|
||||
segment.visit(item -> {
|
||||
|
||||
if (item instanceof Table) {
|
||||
requiredByWhere.add((Table) item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (segment instanceof Join || segment instanceof OrderByField || segment instanceof From
|
||||
|| segment instanceof Select || segment instanceof Where || segment instanceof SimpleFunction) {
|
||||
parent = segment;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Visitor#leave(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public void leave(Visitable segment) {}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Assign a {@link Expression} to a {@link Column}.
|
||||
* <p/>
|
||||
* Results in a rendered assignment: {@code <column> = <value>} (e.g. {@code col = 'foo'}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class AssignValue extends AbstractSegment implements Assignment {
|
||||
|
||||
private final Column column;
|
||||
private final Expression value;
|
||||
|
||||
private AssignValue(Column column, Expression value) {
|
||||
super(column, value);
|
||||
this.column = column;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AssignValue value} assignment to a {@link Column} given an {@link Expression}.
|
||||
*
|
||||
* @param target target column, must not be {@literal null}.
|
||||
* @param value assignment value, must not be {@literal null}.
|
||||
* @return the {@link AssignValue}.
|
||||
*/
|
||||
public static AssignValue create(Column target, Expression value) {
|
||||
|
||||
Assert.notNull(target, "Target column must not be null!");
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
return new AssignValue(target, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the target {@link Column}.
|
||||
*/
|
||||
public Column getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value to assign.
|
||||
*/
|
||||
public Expression getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuilder builder = new StringBuilder(32);
|
||||
return builder.append(this.column).append(" = ").append(this.value).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* Update assignment to a {@link Column}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface Assignment extends Segment {}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* Factory for common {@link Assignment}s.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see SQL
|
||||
* @see Expressions
|
||||
* @see Functions
|
||||
*/
|
||||
public abstract class Assignments {
|
||||
|
||||
/**
|
||||
* Creates a {@link AssignValue value} assignment to a {@link Column} given an {@link Expression}.
|
||||
*
|
||||
* @param target target column, must not be {@literal null}.
|
||||
* @param value assignment value, must not be {@literal null}.
|
||||
* @return the {@link AssignValue}.
|
||||
*/
|
||||
public static AssignValue value(Column target, Expression value) {
|
||||
return AssignValue.create(target, value);
|
||||
}
|
||||
|
||||
// Utility constructor.
|
||||
private Assignments() {}
|
||||
}
|
||||
@@ -200,6 +200,20 @@ public class Column extends AbstractSegment implements Expression, Named {
|
||||
return isNull().not();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Methods for Assignment creation.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Creates a value {@link AssignValue assignment}.
|
||||
*
|
||||
* @param value the value to assign.
|
||||
* @return the {@link AssignValue} assignment.
|
||||
*/
|
||||
public AssignValue set(Expression value) {
|
||||
return Assignments.value(this, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Named#getName()
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default {@link Delete} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DefaultDelete implements Delete {
|
||||
|
||||
private final From from;
|
||||
private final @Nullable Where where;
|
||||
|
||||
DefaultDelete(Table table, @Nullable Condition where) {
|
||||
|
||||
this.from = new From(table);
|
||||
this.where = where != null ? new Where(where) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Visitable#visit(org.springframework.data.relational.core.sql.Visitor)
|
||||
*/
|
||||
@Override
|
||||
public void visit(Visitor visitor) {
|
||||
|
||||
Assert.notNull(visitor, "Visitor must not be null!");
|
||||
|
||||
visitor.enter(this);
|
||||
|
||||
from.visit(visitor);
|
||||
|
||||
if (where != null) {
|
||||
where.visit(visitor);
|
||||
}
|
||||
|
||||
visitor.leave(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("DELETE ").append(this.from);
|
||||
|
||||
if (this.where != null) {
|
||||
builder.append(' ').append(this.where);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default {@link SelectBuilder} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DefaultDeleteBuilder implements DeleteBuilder, DeleteBuilder.DeleteWhereAndOr, DeleteBuilder.DeleteWhere {
|
||||
|
||||
private Table from;
|
||||
private @Nullable Condition where;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.DeleteBuilder#from(org.springframework.data.relational.core.sql.Table)
|
||||
*/
|
||||
@Override
|
||||
public DeleteWhere from(Table table) {
|
||||
|
||||
Assert.notNull(table, "Table must not be null!");
|
||||
|
||||
this.from = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.DeleteBuilder.DeleteWhere#where(org.springframework.data.relational.core.sql.Condition)
|
||||
*/
|
||||
@Override
|
||||
public DeleteWhereAndOr where(Condition condition) {
|
||||
|
||||
Assert.notNull(condition, "Where Condition must not be null!");
|
||||
this.where = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.DeleteBuilder.DeleteWhereAndOr#and(org.springframework.data.relational.core.sql.Condition)
|
||||
*/
|
||||
@Override
|
||||
public DeleteWhereAndOr and(Condition condition) {
|
||||
|
||||
Assert.notNull(condition, "Condition must not be null!");
|
||||
this.where = this.where.and(condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.DeleteBuilder.DeleteWhereAndOr#or(org.springframework.data.relational.core.sql.Condition)
|
||||
*/
|
||||
@Override
|
||||
public DeleteWhereAndOr or(Condition condition) {
|
||||
|
||||
Assert.notNull(condition, "Condition must not be null!");
|
||||
this.where = this.where.or(condition);
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.DeleteBuilder.BuildDelete#build()
|
||||
*/
|
||||
@Override
|
||||
public Delete build() {
|
||||
|
||||
DefaultDelete delete = new DefaultDelete(this.from, this.where);
|
||||
|
||||
DeleteValidator.validate(delete);
|
||||
|
||||
return delete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default {@link Insert} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DefaultInsert implements Insert {
|
||||
|
||||
private final Into into;
|
||||
private final List<Column> columns;
|
||||
private final Values values;
|
||||
|
||||
DefaultInsert(@Nullable Table into, List<Column> columns, List<Expression> values) {
|
||||
this.into = new Into(into);
|
||||
this.columns = new ArrayList<>(columns);
|
||||
this.values = new Values(new ArrayList<>(values));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Visitable#visit(org.springframework.data.relational.core.sql.Visitor)
|
||||
*/
|
||||
@Override
|
||||
public void visit(Visitor visitor) {
|
||||
|
||||
Assert.notNull(visitor, "Visitor must not be null!");
|
||||
|
||||
visitor.enter(this);
|
||||
|
||||
into.visit(visitor);
|
||||
columns.forEach(it -> it.visit(visitor));
|
||||
values.visit(visitor);
|
||||
|
||||
visitor.leave(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("INSERT ").append(this.into);
|
||||
|
||||
if (!this.columns.isEmpty()) {
|
||||
builder.append(" (").append(StringUtils.collectionToDelimitedString(this.columns, ", ")).append(")");
|
||||
}
|
||||
|
||||
builder.append(" ").append(this.values);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default {@link InsertBuilder} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DefaultInsertBuilder
|
||||
implements InsertBuilder, InsertBuilder.InsertIntoColumnsAndValuesWithBuild, InsertBuilder.InsertValuesWithBuild {
|
||||
|
||||
private Table into;
|
||||
private List<Column> columns = new ArrayList<>();
|
||||
private List<Expression> values = new ArrayList<>();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder#into(org.springframework.data.relational.core.sql.Table)
|
||||
*/
|
||||
@Override
|
||||
public InsertIntoColumnsAndValues into(Table table) {
|
||||
|
||||
Assert.notNull(table, "Insert Into Table must not be null!");
|
||||
|
||||
this.into = table;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValues#column(org.springframework.data.relational.core.sql.Column)
|
||||
*/
|
||||
@Override
|
||||
public InsertIntoColumnsAndValuesWithBuild column(Column column) {
|
||||
|
||||
Assert.notNull(column, "Column must not be null!");
|
||||
|
||||
this.columns.add(column);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValues#columns(org.springframework.data.relational.core.sql.Column[])
|
||||
*/
|
||||
@Override
|
||||
public InsertIntoColumnsAndValuesWithBuild columns(Column... columns) {
|
||||
|
||||
Assert.notNull(columns, "Columns must not be null!");
|
||||
|
||||
return columns(Arrays.asList(columns));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValues#columns(java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public InsertIntoColumnsAndValuesWithBuild columns(Collection<Column> columns) {
|
||||
|
||||
Assert.notNull(columns, "Columns must not be null!");
|
||||
|
||||
this.columns.addAll(columns);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValuesWithBuild#value(org.springframework.data.relational.core.sql.Expression)
|
||||
*/
|
||||
@Override
|
||||
public InsertValuesWithBuild value(Expression value) {
|
||||
|
||||
Assert.notNull(value, "Value must not be null!");
|
||||
|
||||
this.values.add(value);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValuesWithBuild#values(org.springframework.data.relational.core.sql.Expression[])
|
||||
*/
|
||||
@Override
|
||||
public InsertValuesWithBuild values(Expression... values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
|
||||
return values(Arrays.asList(values));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValuesWithBuild#values(java.util.Collection)
|
||||
*/
|
||||
@Override
|
||||
public InsertValuesWithBuild values(Collection<? extends Expression> values) {
|
||||
|
||||
Assert.notNull(values, "Values must not be null!");
|
||||
|
||||
this.values.addAll(values);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.InsertBuilder.BuildInsert#build()
|
||||
*/
|
||||
@Override
|
||||
public Insert build() {
|
||||
return new DefaultInsert(this.into, this.columns, this.values);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class DefaultSelect implements Select {
|
||||
|
||||
this.distinct = distinct;
|
||||
this.selectList = new SelectList(new ArrayList<>(selectList));
|
||||
this.from = new From(from);
|
||||
this.from = new From(new ArrayList<>(from));
|
||||
this.limit = limit;
|
||||
this.offset = offset;
|
||||
this.joins = new ArrayList<>(joins);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default {@link Update} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DefaultUpdate implements Update {
|
||||
|
||||
private final Table table;
|
||||
private final List<Assignment> assignments;
|
||||
private final @Nullable Where where;
|
||||
|
||||
DefaultUpdate(Table table, List<Assignment> assignments, @Nullable Condition where) {
|
||||
this.table = table;
|
||||
this.assignments = new ArrayList<>(assignments);
|
||||
this.where = where != null ? new Where(where) : null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Visitable#visit(org.springframework.data.relational.core.sql.Visitor)
|
||||
*/
|
||||
@Override
|
||||
public void visit(Visitor visitor) {
|
||||
|
||||
Assert.notNull(visitor, "Visitor must not be null!");
|
||||
|
||||
visitor.enter(this);
|
||||
|
||||
this.table.visit(visitor);
|
||||
this.assignments.forEach(it -> it.visit(visitor));
|
||||
|
||||
if (this.where != null) {
|
||||
this.where.visit(visitor);
|
||||
}
|
||||
|
||||
visitor.leave(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
StringBuilder builder = new StringBuilder(32);
|
||||
builder.append("UPDATE ").append(table);
|
||||
|
||||
if (!assignments.isEmpty()) {
|
||||
builder.append(" SET ").append(StringUtils.collectionToDelimitedString(this.assignments, ", "));
|
||||
}
|
||||
|
||||
if (this.where != null) {
|
||||
builder.append(" WHERE ").append(this.where);
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.relational.core.sql.UpdateBuilder.UpdateAssign;
|
||||
import org.springframework.data.relational.core.sql.UpdateBuilder.UpdateAssignAnd;
|
||||
import org.springframework.data.relational.core.sql.UpdateBuilder.UpdateWhere;
|
||||
import org.springframework.data.relational.core.sql.UpdateBuilder.UpdateWhereAndOr;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Default {@link UpdateBuilder} implementation.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DefaultUpdateBuilder implements UpdateBuilder, UpdateWhere, UpdateWhereAndOr, UpdateAssign, UpdateAssignAnd {
|
||||
|
||||
private Table table;
|
||||
private List<Assignment> assignments = new ArrayList<>();
|
||||
private @Nullable Condition where;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder#table(org.springframework.data.relational.core.sql.Table)
|
||||
*/
|
||||
@Override
|
||||
public UpdateAssign table(Table table) {
|
||||
|
||||
Assert.notNull(table, "Table must not be null!");
|
||||
|
||||
this.table = table;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder.UpdateAssign#set(org.springframework.data.relational.core.sql.Assignment)
|
||||
*/
|
||||
@Override
|
||||
public DefaultUpdateBuilder set(Assignment assignment) {
|
||||
|
||||
Assert.notNull(assignment, "Assignment must not be null!");
|
||||
|
||||
this.assignments.add(assignment);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder.UpdateAssignAnd#and(org.springframework.data.relational.core.sql.Assignment)
|
||||
*/
|
||||
@Override
|
||||
public DefaultUpdateBuilder and(Assignment assignment) {
|
||||
return set(assignment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder.UpdateWhere#where(org.springframework.data.relational.core.sql.Condition)
|
||||
*/
|
||||
@Override
|
||||
public UpdateWhereAndOr where(Condition condition) {
|
||||
|
||||
Assert.notNull(condition, "Condition must not be null!");
|
||||
|
||||
this.where = condition;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder.UpdateWhereAndOr#and(org.springframework.data.relational.core.sql.Condition)
|
||||
*/
|
||||
@Override
|
||||
public UpdateWhereAndOr and(Condition condition) {
|
||||
|
||||
Assert.notNull(condition, "Condition must not be null!");
|
||||
|
||||
this.where = this.where.and(condition);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder.UpdateWhereAndOr#or(org.springframework.data.relational.core.sql.Condition)
|
||||
*/
|
||||
@Override
|
||||
public UpdateWhereAndOr or(Condition condition) {
|
||||
|
||||
Assert.notNull(condition, "Condition must not be null!");
|
||||
|
||||
this.where = this.where.and(condition);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.UpdateBuilder.BuildUpdate#build()
|
||||
*/
|
||||
@Override
|
||||
public Update build() {
|
||||
return new DefaultUpdate(this.table, this.assignments, this.where);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* AST for a {@code DELETE} statement. Visiting order:
|
||||
* <ol>
|
||||
* <li>Self</li>
|
||||
* <li>{@link Table FROM tables} clause</li>
|
||||
* <li>{@link Where WHERE} condition</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
* @see DeleteBuilder
|
||||
* @see SQL
|
||||
*/
|
||||
public interface Delete extends Segment, Visitable {
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeleteBuilder}.
|
||||
*
|
||||
* @return a new {@link DeleteBuilder}.
|
||||
*/
|
||||
static DeleteBuilder builder() {
|
||||
return new DefaultDeleteBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* Entry point to construct a {@link Delete} statement.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
*/
|
||||
public interface DeleteBuilder {
|
||||
|
||||
/**
|
||||
* Declare a {@link Table} for {@code DELETE FROM}.
|
||||
*
|
||||
* @param table the table to {@code DELETE FROM} must not be {@literal null}.
|
||||
* @return {@code this} builder.
|
||||
* @see From
|
||||
* @see SQL#table(String)
|
||||
*/
|
||||
DeleteWhere from(Table table);
|
||||
|
||||
/**
|
||||
* Interface exposing {@code WHERE} methods.
|
||||
*/
|
||||
interface DeleteWhere extends BuildDelete {
|
||||
|
||||
/**
|
||||
* Apply a {@code WHERE} clause.
|
||||
*
|
||||
* @param condition the {@code WHERE} condition.
|
||||
* @return {@code this} builder.
|
||||
* @see Where
|
||||
* @see Condition
|
||||
*/
|
||||
DeleteWhereAndOr where(Condition condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code AND}/{@code OR} combinator methods for {@code WHERE} {@link Condition}s.
|
||||
*/
|
||||
interface DeleteWhereAndOr extends BuildDelete {
|
||||
|
||||
/**
|
||||
* Combine the previous {@code WHERE} {@link Condition} using {@code AND}.
|
||||
*
|
||||
* @param condition the condition, must not be {@literal null}.
|
||||
* @return {@code this} builder.
|
||||
* @see Condition#and(Condition)
|
||||
*/
|
||||
DeleteWhereAndOr and(Condition condition);
|
||||
|
||||
/**
|
||||
* Combine the previous {@code WHERE} {@link Condition} using {@code OR}.
|
||||
*
|
||||
* @param condition the condition, must not be {@literal null}.
|
||||
* @return {@code this} builder.
|
||||
* @see Condition#or(Condition)
|
||||
*/
|
||||
DeleteWhereAndOr or(Condition condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing the {@link Delete} build method.
|
||||
*/
|
||||
interface BuildDelete {
|
||||
|
||||
/**
|
||||
* Build the {@link Delete} statement and verify basic relationship constraints such as all referenced columns have
|
||||
* a {@code FROM} table import.
|
||||
*
|
||||
* @return the build and immutable {@link Delete} statement.
|
||||
*/
|
||||
Delete build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* Validator for {@link Delete} statements.
|
||||
* <p/>
|
||||
* Validates that all {@link Column}s using a table qualifier have a table import from the {@code FROM} clause.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DeleteValidator extends AbstractImportValidator {
|
||||
|
||||
public static void validate(Delete select) {
|
||||
new DeleteValidator().doValidate(select);
|
||||
}
|
||||
|
||||
private void doValidate(Delete select) {
|
||||
|
||||
select.visit(this);
|
||||
|
||||
for (Table table : requiredByWhere) {
|
||||
if (!from.contains(table)) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Required table [%s] by a WHERE predicate not imported by FROM %s", table, from));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* AST for a {@code INSERT} statement. Visiting order:
|
||||
* <ol>
|
||||
* <li>Self</li>
|
||||
* <li>{@link Into INTO table} clause</li>
|
||||
* <li>{@link Column columns}</li>
|
||||
* <li>{@link Values VALUEs}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
* @see InsertBuilder
|
||||
* @see SQL
|
||||
*/
|
||||
public interface Insert extends Segment, Visitable {
|
||||
|
||||
/**
|
||||
* Creates a new {@link InsertBuilder}.
|
||||
*
|
||||
* @return a new {@link InsertBuilder}.
|
||||
*/
|
||||
static InsertBuilder builder() {
|
||||
return new DefaultInsertBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Entry point to construct an {@link Insert} statement.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
*/
|
||||
public interface InsertBuilder {
|
||||
|
||||
/**
|
||||
* Declare a {@link Table} to {@code INSERT INTO}.
|
||||
*
|
||||
* @param table the table to {@code INSERT INTO} must not be {@literal null}.
|
||||
* @return {@code this} builder.
|
||||
* @see Into
|
||||
* @see SQL#table(String)
|
||||
*/
|
||||
InsertIntoColumnsAndValues into(Table table);
|
||||
|
||||
/**
|
||||
* Interface exposing {@code WHERE} methods.
|
||||
*/
|
||||
interface InsertIntoColumnsAndValues extends InsertValues {
|
||||
|
||||
/**
|
||||
* Add a {@link Column} to the {@code INTO} column list. Calling this method multiple times will add the
|
||||
* {@link Column} multiple times.
|
||||
*
|
||||
* @param column the column.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
InsertIntoColumnsAndValuesWithBuild column(Column column);
|
||||
|
||||
/**
|
||||
* Add a one or more {@link Column} to the {@code INTO} column list. Calling this method multiple times will add the
|
||||
* {@link Column} multiple times.
|
||||
*
|
||||
* @param columns the columns.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
InsertIntoColumnsAndValuesWithBuild columns(Column... columns);
|
||||
|
||||
/**
|
||||
* Add a one or more {@link Column} to the {@code INTO} column list. Calling this method multiple times will add the
|
||||
* {@link Column} multiple times.
|
||||
*
|
||||
* @param columns the columns.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
InsertIntoColumnsAndValuesWithBuild columns(Collection<Column> columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code value} methods to add values to the {@code INSERT} statement and the build method.
|
||||
*/
|
||||
interface InsertIntoColumnsAndValuesWithBuild extends InsertIntoColumnsAndValues, InsertValues, BuildInsert {
|
||||
|
||||
/**
|
||||
* Add a {@link Expression value} to the {@code VALUES} list. Calling this method multiple times will add a
|
||||
* {@link Expression value} multiple times.
|
||||
*
|
||||
* @param value the value to use.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
@Override
|
||||
InsertValuesWithBuild value(Expression value);
|
||||
|
||||
/**
|
||||
* Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
|
||||
* a {@link Expression values} multiple times.
|
||||
*
|
||||
* @param values the values.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
@Override
|
||||
InsertValuesWithBuild values(Expression... values);
|
||||
|
||||
/**
|
||||
* Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
|
||||
* a {@link Expression values} multiple times.
|
||||
*
|
||||
* @param values the values.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
@Override
|
||||
InsertValuesWithBuild values(Collection<? extends Expression> values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code value} methods to add values to the {@code INSERT} statement and the build method.
|
||||
*/
|
||||
interface InsertValuesWithBuild extends InsertValues, BuildInsert {
|
||||
|
||||
/**
|
||||
* Add a {@link Expression value} to the {@code VALUES} list. Calling this method multiple times will add a
|
||||
* {@link Expression value} multiple times.
|
||||
*
|
||||
* @param value the value to use.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
@Override
|
||||
InsertValuesWithBuild value(Expression value);
|
||||
|
||||
/**
|
||||
* Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
|
||||
* a {@link Expression values} multiple times.
|
||||
*
|
||||
* @param values the values.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
@Override
|
||||
InsertValuesWithBuild values(Expression... values);
|
||||
|
||||
/**
|
||||
* Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
|
||||
* a {@link Expression values} multiple times.
|
||||
*
|
||||
* @param values the values.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
@Override
|
||||
InsertValuesWithBuild values(Collection<? extends Expression> values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code value} methods to add values to the {@code INSERT} statement.
|
||||
*/
|
||||
interface InsertValues {
|
||||
|
||||
/**
|
||||
* Add a {@link Expression value} to the {@code VALUES} list. Calling this method multiple times will add a
|
||||
* {@link Expression value} multiple times.
|
||||
*
|
||||
* @param value the value to use.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
InsertValuesWithBuild value(Expression value);
|
||||
|
||||
/**
|
||||
* Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
|
||||
* a {@link Expression values} multiple times.
|
||||
*
|
||||
* @param values the values.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
InsertValuesWithBuild values(Expression... values);
|
||||
|
||||
/**
|
||||
* Add one or more {@link Expression values} to the {@code VALUES} list. Calling this method multiple times will add
|
||||
* a {@link Expression values} multiple times.
|
||||
*
|
||||
* @param values the values.
|
||||
* @return {@code this} builder.
|
||||
* @see Column
|
||||
*/
|
||||
InsertValuesWithBuild values(Collection<? extends Expression> values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing the {@link Insert} build method.
|
||||
*/
|
||||
interface BuildInsert {
|
||||
|
||||
/**
|
||||
* Build the {@link Insert} statement.
|
||||
*
|
||||
* @return the build and immutable {@link Insert} statement.
|
||||
*/
|
||||
Insert build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@code INTO} clause.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class Into extends AbstractSegment {
|
||||
|
||||
private final List<Table> tables;
|
||||
|
||||
Into(Table... tables) {
|
||||
this(Arrays.asList(tables));
|
||||
}
|
||||
|
||||
Into(List<Table> tables) {
|
||||
|
||||
super(tables.toArray(new Table[] {}));
|
||||
|
||||
this.tables = tables;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "INTO " + StringUtils.collectionToDelimitedString(tables, ", ");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a literal.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class Literal<T> extends AbstractSegment implements Expression {
|
||||
|
||||
private @Nullable T content;
|
||||
|
||||
Literal(@Nullable T content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the content of the literal.
|
||||
*/
|
||||
@Nullable
|
||||
public T getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
if (this.content == null) {
|
||||
return "NULL";
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a {@link Number} literal.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class NumericLiteral extends Literal<Number> {
|
||||
|
||||
NumericLiteral(@Nullable Number content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Literal#getContent()
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Number getContent() {
|
||||
return super.getContent();
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.data.relational.core.sql.BindMarker.NamedBindMarker;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -77,6 +78,45 @@ public abstract class SQL {
|
||||
return new NamedBindMarker(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link StringLiteral} from the {@code content}.
|
||||
*
|
||||
* @param content the literal content.
|
||||
* @return a new {@link StringLiteral}.
|
||||
*/
|
||||
public static StringLiteral literalOf(@Nullable CharSequence content) {
|
||||
return new StringLiteral(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link NumericLiteral} from the {@code content}.
|
||||
*
|
||||
* @param content the literal content.
|
||||
* @return a new {@link NumericLiteral}.
|
||||
*/
|
||||
public static NumericLiteral literalOf(@Nullable Number content) {
|
||||
return new NumericLiteral(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Literal} from the {@code content}.
|
||||
*
|
||||
* @param content the literal content.
|
||||
* @return a new {@link Literal}.
|
||||
*/
|
||||
public static <T> Literal<T> literalOf(@Nullable T content) {
|
||||
return new Literal<>(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code NULL} {@link Literal}.
|
||||
*
|
||||
* @return a new {@link Literal}.
|
||||
*/
|
||||
public static <T> Literal<T> nullLiteral() {
|
||||
return new Literal<>(null);
|
||||
}
|
||||
|
||||
// Utility constructor.
|
||||
private SQL() {}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.Collection;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
*/
|
||||
public interface SelectBuilder {
|
||||
|
||||
|
||||
@@ -27,18 +27,14 @@ import java.util.Set;
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class SelectValidator implements Visitor {
|
||||
class SelectValidator extends AbstractImportValidator {
|
||||
|
||||
private int selectFieldCount;
|
||||
private Set<Table> requiredBySelect = new HashSet<>();
|
||||
private Set<Table> requiredByWhere = new HashSet<>();
|
||||
private Set<Table> requiredByOrderBy = new HashSet<>();
|
||||
|
||||
private Set<Table> from = new HashSet<>();
|
||||
private Set<Table> join = new HashSet<>();
|
||||
|
||||
private Visitable parent;
|
||||
|
||||
public static void validate(Select select) {
|
||||
new SelectValidator().doValidate(select);
|
||||
}
|
||||
@@ -80,6 +76,8 @@ class SelectValidator implements Visitor {
|
||||
@Override
|
||||
public void enter(Visitable segment) {
|
||||
|
||||
super.enter(segment);
|
||||
|
||||
if (segment instanceof AsteriskFromTable && parent instanceof Select) {
|
||||
|
||||
Table table = ((AsteriskFromTable) segment).getTable();
|
||||
@@ -97,10 +95,6 @@ class SelectValidator implements Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
if (segment instanceof Table && parent instanceof From) {
|
||||
from.add((Table) segment);
|
||||
}
|
||||
|
||||
if (segment instanceof Column && parent instanceof OrderByField) {
|
||||
|
||||
Table table = ((Column) segment).getTable();
|
||||
@@ -123,17 +117,5 @@ class SelectValidator implements Visitor {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (segment instanceof Join || segment instanceof OrderByField || segment instanceof From
|
||||
|| segment instanceof Select || segment instanceof Where || segment instanceof SimpleFunction) {
|
||||
parent = segment;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Visitor#leave(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public void leave(Visitable segment) {}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import static org.springframework.data.relational.core.sql.UpdateBuilder.*;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.data.relational.core.sql.DeleteBuilder.DeleteWhere;
|
||||
import org.springframework.data.relational.core.sql.InsertBuilder.InsertIntoColumnsAndValues;
|
||||
import org.springframework.data.relational.core.sql.SelectBuilder.SelectAndFrom;
|
||||
|
||||
/**
|
||||
@@ -32,7 +36,7 @@ import org.springframework.data.relational.core.sql.SelectBuilder.SelectAndFrom;
|
||||
public abstract class StatementBuilder {
|
||||
|
||||
/**
|
||||
* Creates a new {@link SelectBuilder} by specifying a {@code SELECT} column.
|
||||
* Creates a new {@link SelectBuilder} and includes the {@code SELECT} columns.
|
||||
*
|
||||
* @param expression the select list expression.
|
||||
* @return the {@link SelectBuilder} containing {@link Expression}.
|
||||
@@ -43,7 +47,7 @@ public abstract class StatementBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SelectBuilder} by specifying one or more {@code SELECT} columns.
|
||||
* Creates a new {@link SelectBuilder} and includes one or more {@code SELECT} columns.
|
||||
*
|
||||
* @param expressions the select list expressions.
|
||||
* @return the {@link SelectBuilder} containing {@link Expression}s.
|
||||
@@ -54,10 +58,10 @@ public abstract class StatementBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Include one or more {@link Expression}s in the select list.
|
||||
* Creates a new {@link SelectBuilder} and includes one or more {@link Expression}s in the select list.
|
||||
*
|
||||
* @param expressions the expressions to include.
|
||||
* @return {@code this} builder.
|
||||
* @return the {@link SelectBuilder} containing {@link Expression}s.
|
||||
* @see Table#columns(String...)
|
||||
*/
|
||||
public static SelectAndFrom select(Collection<? extends Expression> expressions) {
|
||||
@@ -74,7 +78,68 @@ public abstract class StatementBuilder {
|
||||
return Select.builder();
|
||||
}
|
||||
|
||||
private StatementBuilder() {
|
||||
|
||||
/**
|
||||
* Creates a new {@link InsertBuilder} and declare the {@link Table} to insert into.
|
||||
*
|
||||
* @param table the table to insert into.
|
||||
* @return the new {@link InsertBuilder}.
|
||||
* @see Table#create(String)
|
||||
*/
|
||||
public static InsertIntoColumnsAndValues insert(Table table) {
|
||||
return insert().into(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link InsertBuilder}.
|
||||
*
|
||||
* @return the new {@link InsertBuilder}.
|
||||
* @see InsertBuilder
|
||||
*/
|
||||
public static InsertBuilder insert() {
|
||||
return Insert.builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link UpdateBuilder} and declare the {@link Table} for the update.
|
||||
*
|
||||
* @param table the table for the update.
|
||||
* @return the new {@link UpdateBuilder}.
|
||||
* @see Table#create(String)
|
||||
*/
|
||||
public static UpdateAssign update(Table table) {
|
||||
return update().table(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link UpdateBuilder}.
|
||||
*
|
||||
* @return the new {@link UpdateBuilder}.
|
||||
* @see UpdateBuilder
|
||||
*/
|
||||
public static UpdateBuilder update() {
|
||||
return Update.builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeleteBuilder} and declares the {@link Table} to delete from.
|
||||
*
|
||||
* @param table the table to delete from.
|
||||
* @return {@code this} builder.
|
||||
* @see Table#columns(String...)
|
||||
*/
|
||||
public static DeleteWhere delete(Table table) {
|
||||
return delete().from(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DeleteBuilder}.
|
||||
*
|
||||
* @return the new {@link DeleteBuilder}.
|
||||
* @see DeleteBuilder
|
||||
*/
|
||||
public static DeleteBuilder delete() {
|
||||
return Delete.builder();
|
||||
}
|
||||
|
||||
private StatementBuilder() {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Represents a {@link CharSequence} literal.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class StringLiteral extends Literal<CharSequence> {
|
||||
|
||||
StringLiteral(@Nullable CharSequence content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Literal#getContent()
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public CharSequence getContent() {
|
||||
return super.getContent();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.Literal#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "'" + super.toString() + "'";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* AST for aa {@code UPDATE} statement. Visiting order:
|
||||
* <ol>
|
||||
* <li>Self</li>
|
||||
* <li>{@link Table table}</li>
|
||||
* <li>{@link Assignments assignments}</li>
|
||||
* <li>{@link Where WHERE} condition</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
* @see SelectBuilder
|
||||
* @see SQL
|
||||
*/
|
||||
public interface Update extends Segment, Visitable {
|
||||
|
||||
/**
|
||||
* Creates a new {@link UpdateBuilder}.
|
||||
*
|
||||
* @return a new {@link UpdateBuilder}.
|
||||
*/
|
||||
static UpdateBuilder builder() {
|
||||
return new DefaultUpdateBuilder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
/**
|
||||
* Entry point to construct an {@link Update} statement.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see StatementBuilder
|
||||
*/
|
||||
public interface UpdateBuilder {
|
||||
|
||||
/**
|
||||
* Configure the {@link Table} to which the update is applied.
|
||||
*
|
||||
* @param count the top count.
|
||||
* @return {@code this} {@link SelectBuilder}.
|
||||
*/
|
||||
UpdateAssign table(Table table);
|
||||
|
||||
/**
|
||||
* Interface exposing {@code SET} methods.
|
||||
*/
|
||||
interface UpdateAssign {
|
||||
|
||||
/**
|
||||
* Apply a {@link Assignment SET assignment}.
|
||||
*
|
||||
* @param assignment a single {@link Assignment column assignment}.
|
||||
* @return {@code this} builder.
|
||||
* @see Assignment
|
||||
*/
|
||||
UpdateAssignAnd set(Assignment assignment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code SET} methods.
|
||||
*/
|
||||
interface UpdateAssignAnd extends UpdateWhere {
|
||||
|
||||
/**
|
||||
* Apply a {@link Assignment SET assignment}.
|
||||
*
|
||||
* @param assignment a single {@link Assignment column assignment}.
|
||||
* @return {@code this} builder.
|
||||
* @see Assignment
|
||||
*/
|
||||
UpdateAssignAnd and(Assignment assignment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code WHERE} methods.
|
||||
*/
|
||||
interface UpdateWhere extends BuildUpdate {
|
||||
|
||||
/**
|
||||
* Apply a {@code WHERE} clause.
|
||||
*
|
||||
* @param condition the {@code WHERE} condition.
|
||||
* @return {@code this} builder.
|
||||
* @see Where
|
||||
* @see Condition
|
||||
*/
|
||||
UpdateWhereAndOr where(Condition condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing {@code AND}/{@code OR} combinator methods for {@code WHERE} {@link Condition}s.
|
||||
*/
|
||||
interface UpdateWhereAndOr extends BuildUpdate {
|
||||
|
||||
/**
|
||||
* Combine the previous {@code WHERE} {@link Condition} using {@code AND}.
|
||||
*
|
||||
* @param condition the condition, must not be {@literal null}.
|
||||
* @return {@code this} builder.
|
||||
* @see Condition#and(Condition)
|
||||
*/
|
||||
UpdateWhereAndOr and(Condition condition);
|
||||
|
||||
/**
|
||||
* Combine the previous {@code WHERE} {@link Condition} using {@code OR}.
|
||||
*
|
||||
* @param condition the condition, must not be {@literal null}.
|
||||
* @return {@code this} builder.
|
||||
* @see Condition#or(Condition)
|
||||
*/
|
||||
UpdateWhereAndOr or(Condition condition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface exposing the {@link Update} build method.
|
||||
*/
|
||||
interface BuildUpdate {
|
||||
|
||||
/**
|
||||
* Build the {@link Update}.
|
||||
*
|
||||
* @return the build and immutable {@link Update} statement.
|
||||
*/
|
||||
Update build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@code VALUES} clause.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public class Values extends AbstractSegment {
|
||||
|
||||
private final List<Expression> tables;
|
||||
|
||||
Values(Expression... tables) {
|
||||
this(Arrays.asList(tables));
|
||||
}
|
||||
|
||||
Values(List<Expression> expressions) {
|
||||
|
||||
super(expressions.toArray(new Expression[0]));
|
||||
|
||||
this.tables = expressions;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VALUES(" + StringUtils.collectionToDelimitedString(tables, ", ") + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Assignment;
|
||||
import org.springframework.data.relational.core.sql.Column;
|
||||
import org.springframework.data.relational.core.sql.Expression;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.data.relational.core.sql.Visitor} rendering {@link Assignment}. Uses a
|
||||
* {@link RenderTarget} to call back for render results.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
* @see Assignment
|
||||
*/
|
||||
class AssignmentVisitor extends TypedSubtreeVisitor<Assignment> {
|
||||
|
||||
private final ColumnVisitor columnVisitor;
|
||||
private final ExpressionVisitor expressionVisitor;
|
||||
private final RenderTarget target;
|
||||
private final StringBuilder part = new StringBuilder();
|
||||
|
||||
AssignmentVisitor(RenderContext context, RenderTarget target) {
|
||||
this.columnVisitor = new ColumnVisitor(context, part::append);
|
||||
this.expressionVisitor = new ExpressionVisitor(context);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.FilteredSubtreeVisitor#enterNested(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation enterNested(Visitable segment) {
|
||||
|
||||
if (segment instanceof Column) {
|
||||
return Delegation.delegateTo(columnVisitor);
|
||||
}
|
||||
|
||||
if (segment instanceof Expression) {
|
||||
return Delegation.delegateTo(expressionVisitor);
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Cannot provide visitor for " + segment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.FilteredSubtreeVisitor#leaveNested(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveNested(Visitable segment) {
|
||||
|
||||
if (segment instanceof Column) {
|
||||
if (part.length() != 0) {
|
||||
part.append(" = ");
|
||||
}
|
||||
return super.leaveNested(segment);
|
||||
}
|
||||
|
||||
if (segment instanceof Expression) {
|
||||
part.append(expressionVisitor.getRenderedPart());
|
||||
}
|
||||
|
||||
return super.leaveNested(segment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.FilteredSubtreeVisitor#leaveMatched(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveMatched(Assignment segment) {
|
||||
|
||||
target.onRendered(new StringBuilder(part));
|
||||
part.setLength(0);
|
||||
|
||||
return super.leaveMatched(segment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Column;
|
||||
import org.springframework.data.relational.core.sql.Table;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Renderer for {@link Column}s.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class ColumnVisitor extends TypedSubtreeVisitor<Column> {
|
||||
|
||||
private final RenderContext context;
|
||||
private final RenderTarget target;
|
||||
|
||||
private @Nullable String tableName;
|
||||
|
||||
ColumnVisitor(RenderContext context, RenderTarget target) {
|
||||
this.context = context;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#leaveMatched(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveMatched(Column segment) {
|
||||
|
||||
String column = context.getNamingStrategy().getName(segment);
|
||||
StringBuilder builder = new StringBuilder(
|
||||
tableName != null ? tableName.length() + column.length() : column.length());
|
||||
if (tableName != null) {
|
||||
builder.append(tableName);
|
||||
}
|
||||
builder.append(column);
|
||||
|
||||
target.onRendered(builder);
|
||||
return super.leaveMatched(segment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#leaveNested(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveNested(Visitable segment) {
|
||||
|
||||
if (segment instanceof Table) {
|
||||
tableName = context.getNamingStrategy().getReferenceName((Table) segment) + '.';
|
||||
}
|
||||
|
||||
return super.leaveNested(segment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Delete;
|
||||
import org.springframework.data.relational.core.sql.From;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
import org.springframework.data.relational.core.sql.Where;
|
||||
|
||||
/**
|
||||
* {@link PartRenderer} for {@link Delete} statements.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class DeleteStatementVisitor extends DelegatingVisitor implements PartRenderer {
|
||||
|
||||
private StringBuilder builder = new StringBuilder();
|
||||
private StringBuilder from = new StringBuilder();
|
||||
private StringBuilder where = new StringBuilder();
|
||||
|
||||
private FromClauseVisitor fromClauseVisitor;
|
||||
private WhereClauseVisitor whereClauseVisitor;
|
||||
|
||||
DeleteStatementVisitor(RenderContext context) {
|
||||
|
||||
this.fromClauseVisitor = new FromClauseVisitor(context, it -> {
|
||||
|
||||
if (from.length() != 0) {
|
||||
from.append(", ");
|
||||
}
|
||||
|
||||
from.append(it);
|
||||
});
|
||||
|
||||
this.whereClauseVisitor = new WhereClauseVisitor(context, where::append);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.DelegatingVisitor#doEnter(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public Delegation doEnter(Visitable segment) {
|
||||
|
||||
if (segment instanceof From) {
|
||||
return Delegation.delegateTo(fromClauseVisitor);
|
||||
}
|
||||
|
||||
if (segment instanceof Where) {
|
||||
return Delegation.delegateTo(whereClauseVisitor);
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.DelegatingVisitor#doLeave(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public Delegation doLeave(Visitable segment) {
|
||||
|
||||
if (segment instanceof Delete) {
|
||||
|
||||
builder.append("DELETE ");
|
||||
|
||||
if (from.length() != 0) {
|
||||
builder.append("FROM ").append(from);
|
||||
}
|
||||
|
||||
if (where.length() != 0) {
|
||||
builder.append(" WHERE ").append(where);
|
||||
}
|
||||
|
||||
return Delegation.leave();
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.PartRenderer#getRenderedPart()
|
||||
*/
|
||||
@Override
|
||||
public CharSequence getRenderedPart() {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import org.springframework.data.relational.core.sql.BindMarker;
|
||||
import org.springframework.data.relational.core.sql.Column;
|
||||
import org.springframework.data.relational.core.sql.Condition;
|
||||
import org.springframework.data.relational.core.sql.Expression;
|
||||
import org.springframework.data.relational.core.sql.Literal;
|
||||
import org.springframework.data.relational.core.sql.Named;
|
||||
import org.springframework.data.relational.core.sql.SubselectExpression;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
@@ -71,6 +72,8 @@ class ExpressionVisitor extends TypedSubtreeVisitor<Expression> implements PartR
|
||||
} else {
|
||||
value = segment.toString();
|
||||
}
|
||||
} else if (segment instanceof Literal) {
|
||||
value = segment.toString();
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Column;
|
||||
import org.springframework.data.relational.core.sql.Insert;
|
||||
import org.springframework.data.relational.core.sql.Into;
|
||||
import org.springframework.data.relational.core.sql.Values;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
|
||||
/**
|
||||
* {@link PartRenderer} for {@link Insert} statements.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class InsertStatementVisitor extends DelegatingVisitor implements PartRenderer {
|
||||
|
||||
private StringBuilder builder = new StringBuilder();
|
||||
private StringBuilder into = new StringBuilder();
|
||||
private StringBuilder columns = new StringBuilder();
|
||||
private StringBuilder values = new StringBuilder();
|
||||
|
||||
private IntoClauseVisitor intoClauseVisitor;
|
||||
private ColumnVisitor columnVisitor;
|
||||
private ValuesVisitor valuesVisitor;
|
||||
|
||||
InsertStatementVisitor(RenderContext context) {
|
||||
|
||||
this.intoClauseVisitor = new IntoClauseVisitor(context, it -> {
|
||||
|
||||
if (into.length() != 0) {
|
||||
into.append(", ");
|
||||
}
|
||||
|
||||
into.append(it);
|
||||
});
|
||||
|
||||
this.columnVisitor = new ColumnVisitor(context, it -> {
|
||||
|
||||
if (columns.length() != 0) {
|
||||
columns.append(", ");
|
||||
}
|
||||
|
||||
columns.append(it);
|
||||
});
|
||||
|
||||
this.valuesVisitor = new ValuesVisitor(context, values::append);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.DelegatingVisitor#doEnter(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public Delegation doEnter(Visitable segment) {
|
||||
|
||||
if (segment instanceof Into) {
|
||||
return Delegation.delegateTo(this.intoClauseVisitor);
|
||||
}
|
||||
|
||||
if (segment instanceof Column) {
|
||||
return Delegation.delegateTo(this.columnVisitor);
|
||||
}
|
||||
|
||||
if (segment instanceof Values) {
|
||||
return Delegation.delegateTo(this.valuesVisitor);
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.DelegatingVisitor#doLeave(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public Delegation doLeave(Visitable segment) {
|
||||
|
||||
if (segment instanceof Insert) {
|
||||
|
||||
builder.append("INSERT");
|
||||
|
||||
if (into.length() != 0) {
|
||||
builder.append(" INTO ").append(into);
|
||||
}
|
||||
|
||||
if (columns.length() != 0) {
|
||||
builder.append(" (").append(columns).append(")");
|
||||
}
|
||||
|
||||
if (values.length() != 0) {
|
||||
builder.append(" VALUES(").append(values).append(")");
|
||||
}
|
||||
|
||||
return Delegation.leave();
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.PartRenderer#getRenderedPart()
|
||||
*/
|
||||
@Override
|
||||
public CharSequence getRenderedPart() {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Into;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
|
||||
/**
|
||||
* Renderer for {@link Into}. Uses a {@link RenderTarget} to call back for render results.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class IntoClauseVisitor extends TypedSubtreeVisitor<Into> {
|
||||
|
||||
private final FromTableVisitor visitor;
|
||||
private final RenderTarget parent;
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
private boolean first = true;
|
||||
|
||||
IntoClauseVisitor(RenderContext context, RenderTarget parent) {
|
||||
|
||||
this.visitor = new FromTableVisitor(context, it -> {
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
builder.append(", ");
|
||||
}
|
||||
|
||||
builder.append(it);
|
||||
});
|
||||
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#enterNested(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation enterNested(Visitable segment) {
|
||||
return Delegation.delegateTo(visitor);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#leaveMatched(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveMatched(Into segment) {
|
||||
parent.onRendered(builder);
|
||||
return super.leaveMatched(segment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Delete;
|
||||
import org.springframework.data.relational.core.sql.Insert;
|
||||
import org.springframework.data.relational.core.sql.Select;
|
||||
import org.springframework.data.relational.core.sql.Update;
|
||||
|
||||
/**
|
||||
* SQL renderer for {@link Select} and {@link Delete} statements.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
public interface Renderer {
|
||||
|
||||
/**
|
||||
* Render the {@link Select} AST into a SQL statement.
|
||||
*
|
||||
* @param select the statement to render, must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
String render(Select select);
|
||||
|
||||
/**
|
||||
* Render the {@link Insert} AST into a SQL statement.
|
||||
*
|
||||
* @param insert the statement to render, must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
String render(Insert insert);
|
||||
|
||||
/**
|
||||
* Render the {@link Update} AST into a SQL statement.
|
||||
*
|
||||
* @param update the statement to render, must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
String render(Update update);
|
||||
|
||||
/**
|
||||
* Render the {@link Delete} AST into a SQL statement.
|
||||
*
|
||||
* @param delete the statement to render, must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
String render(Delete delete);
|
||||
}
|
||||
@@ -15,49 +15,48 @@
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Delete;
|
||||
import org.springframework.data.relational.core.sql.Insert;
|
||||
import org.springframework.data.relational.core.sql.Select;
|
||||
import org.springframework.data.relational.core.sql.Update;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Naive SQL renderer that does not consider dialect specifics. This class is to evaluate requirements of a SQL
|
||||
* renderer.
|
||||
* SQL renderer for {@link Select} and {@link Delete} statements.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
* @since 1.1
|
||||
* @see RenderContext
|
||||
*/
|
||||
public class SqlRenderer {
|
||||
public class SqlRenderer implements Renderer {
|
||||
|
||||
private final Select select;
|
||||
private final RenderContext context;
|
||||
|
||||
private SqlRenderer(Select select, RenderContext context) {
|
||||
private SqlRenderer(RenderContext context) {
|
||||
|
||||
Assert.notNull(context, "RenderContext must not be null!");
|
||||
|
||||
this.context = context;
|
||||
|
||||
Assert.notNull(select, "Select must not be null!");
|
||||
|
||||
this.select = select;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SqlRenderer}.
|
||||
*
|
||||
* @param select must not be {@literal null}.
|
||||
* @return the renderer.
|
||||
*/
|
||||
public static SqlRenderer create(Select select) {
|
||||
return new SqlRenderer(select, new SimpleRenderContext(NamingStrategies.asIs()));
|
||||
public static SqlRenderer create() {
|
||||
return new SqlRenderer(new SimpleRenderContext(NamingStrategies.asIs()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link SqlRenderer} using a {@link RenderContext}.
|
||||
*
|
||||
* @param select must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @return the renderer.
|
||||
*/
|
||||
public static SqlRenderer create(Select select, RenderContext context) {
|
||||
return new SqlRenderer(select, context);
|
||||
public static SqlRenderer create(RenderContext context) {
|
||||
return new SqlRenderer(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,8 +65,38 @@ public class SqlRenderer {
|
||||
* @param select must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
public static String render(Select select) {
|
||||
return create(select).render();
|
||||
public static String toString(Select select) {
|
||||
return create().render(select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a {@link Insert} statement into its SQL representation.
|
||||
*
|
||||
* @param insert must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
public static String toString(Insert insert) {
|
||||
return create().render(insert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a {@link Update} statement into its SQL representation.
|
||||
*
|
||||
* @param update must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
public static String toString(Update update) {
|
||||
return create().render(update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a {@link Delete} statement into its SQL representation.
|
||||
*
|
||||
* @param delete must not be {@literal null}.
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
public static String toString(Delete delete) {
|
||||
return create().render(delete);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,11 +104,54 @@ public class SqlRenderer {
|
||||
*
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
public String render() {
|
||||
@Override
|
||||
public String render(Select select) {
|
||||
|
||||
SelectStatementVisitor visitor = new SelectStatementVisitor(context);
|
||||
select.visit(visitor);
|
||||
|
||||
return visitor.getRenderedPart().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the {@link Insert} AST into a SQL statement.
|
||||
*
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
@Override
|
||||
public String render(Insert insert) {
|
||||
|
||||
InsertStatementVisitor visitor = new InsertStatementVisitor(context);
|
||||
insert.visit(visitor);
|
||||
|
||||
return visitor.getRenderedPart().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the {@link Update} AST into a SQL statement.
|
||||
*
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
@Override
|
||||
public String render(Update update) {
|
||||
|
||||
UpdateStatementVisitor visitor = new UpdateStatementVisitor(context);
|
||||
update.visit(visitor);
|
||||
|
||||
return visitor.getRenderedPart().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the {@link Delete} AST into a SQL statement.
|
||||
*
|
||||
* @return the rendered statement.
|
||||
*/
|
||||
@Override
|
||||
public String render(Delete delete) {
|
||||
|
||||
DeleteStatementVisitor visitor = new DeleteStatementVisitor(context);
|
||||
delete.visit(visitor);
|
||||
|
||||
return visitor.getRenderedPart().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Assignment;
|
||||
import org.springframework.data.relational.core.sql.Table;
|
||||
import org.springframework.data.relational.core.sql.Update;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
import org.springframework.data.relational.core.sql.Where;
|
||||
|
||||
/**
|
||||
* {@link PartRenderer} for {@link Update} statements.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class UpdateStatementVisitor extends DelegatingVisitor implements PartRenderer {
|
||||
|
||||
private StringBuilder builder = new StringBuilder();
|
||||
private StringBuilder table = new StringBuilder();
|
||||
private StringBuilder assignments = new StringBuilder();
|
||||
private StringBuilder where = new StringBuilder();
|
||||
|
||||
private FromTableVisitor tableVisitor;
|
||||
private AssignmentVisitor assignmentVisitor;
|
||||
private WhereClauseVisitor whereClauseVisitor;
|
||||
|
||||
UpdateStatementVisitor(RenderContext context) {
|
||||
|
||||
this.tableVisitor = new FromTableVisitor(context, it -> {
|
||||
|
||||
if (table.length() != 0) {
|
||||
table.append(", ");
|
||||
}
|
||||
|
||||
table.append(it);
|
||||
});
|
||||
|
||||
this.assignmentVisitor = new AssignmentVisitor(context, it -> {
|
||||
|
||||
if (assignments.length() != 0) {
|
||||
assignments.append(", ");
|
||||
}
|
||||
|
||||
assignments.append(it);
|
||||
});
|
||||
|
||||
this.whereClauseVisitor = new WhereClauseVisitor(context, where::append);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.DelegatingVisitor#doEnter(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public Delegation doEnter(Visitable segment) {
|
||||
|
||||
if (segment instanceof Table) {
|
||||
return Delegation.delegateTo(this.tableVisitor);
|
||||
}
|
||||
|
||||
if (segment instanceof Assignment) {
|
||||
return Delegation.delegateTo(this.assignmentVisitor);
|
||||
}
|
||||
|
||||
if (segment instanceof Where) {
|
||||
return Delegation.delegateTo(this.whereClauseVisitor);
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.DelegatingVisitor#doLeave(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
public Delegation doLeave(Visitable segment) {
|
||||
|
||||
if (segment instanceof Update) {
|
||||
|
||||
builder.append("UPDATE");
|
||||
|
||||
if (table.length() != 0) {
|
||||
builder.append(" ").append(table);
|
||||
}
|
||||
|
||||
if (assignments.length() != 0) {
|
||||
builder.append(" SET ").append(assignments);
|
||||
}
|
||||
|
||||
if (where.length() != 0) {
|
||||
builder.append(" WHERE ").append(where);
|
||||
}
|
||||
|
||||
return Delegation.leave();
|
||||
}
|
||||
|
||||
return Delegation.retain();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.PartRenderer#getRenderedPart()
|
||||
*/
|
||||
@Override
|
||||
public CharSequence getRenderedPart() {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Expression;
|
||||
import org.springframework.data.relational.core.sql.Values;
|
||||
import org.springframework.data.relational.core.sql.Visitable;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Renderer for {@link Values}. Uses a {@link RenderTarget} to call back for render results.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.1
|
||||
*/
|
||||
class ValuesVisitor extends TypedSubtreeVisitor<Values> {
|
||||
|
||||
private final RenderTarget parent;
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
private final RenderContext context;
|
||||
|
||||
private @Nullable ExpressionVisitor current;
|
||||
private boolean first = true;
|
||||
|
||||
ValuesVisitor(RenderContext context, RenderTarget parent) {
|
||||
|
||||
this.context = context;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#enterNested(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation enterNested(Visitable segment) {
|
||||
|
||||
if (segment instanceof Expression) {
|
||||
this.current = new ExpressionVisitor(context);
|
||||
return Delegation.delegateTo(this.current);
|
||||
}
|
||||
|
||||
return super.enterNested(segment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#leaveNested(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveNested(Visitable segment) {
|
||||
|
||||
if (this.current != null) {
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
builder.append(", ");
|
||||
}
|
||||
|
||||
builder.append(this.current.getRenderedPart());
|
||||
this.current = null;
|
||||
}
|
||||
|
||||
return super.leaveNested(segment);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.sql.render.TypedSubtreeVisitor#leaveMatched(org.springframework.data.relational.core.sql.Visitable)
|
||||
*/
|
||||
@Override
|
||||
Delegation leaveMatched(Values segment) {
|
||||
parent.onRendered(builder);
|
||||
return super.leaveMatched(segment);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class CapturingVisitor implements Visitor {
|
||||
|
||||
final List<Visitable> enter = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void enter(Visitable segment) {
|
||||
enter.add(segment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leave(Visitable segment) {
|
||||
leave.add(segment);
|
||||
}
|
||||
|
||||
final List<Visitable> leave = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DeleteBuilder}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DeleteBuilderUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void simpleDelete() {
|
||||
|
||||
DeleteBuilder builder = StatementBuilder.delete();
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column foo = table.column("foo");
|
||||
Column bar = table.column("bar");
|
||||
|
||||
Delete delete = builder.from(table).where(foo.isEqualTo(bar)).build();
|
||||
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
delete.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(new From(table), table, new Where(foo.isEqualTo(bar)),
|
||||
foo.isEqualTo(bar), foo, table, bar, table);
|
||||
|
||||
assertThat(delete.toString()).isEqualTo("DELETE FROM mytable WHERE mytable.foo = mytable.bar");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SelectValidator}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DeleteValidatorUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldReportMissingTableForDeleteViaWhere() {
|
||||
|
||||
Column column = SQL.table("table").column("foo");
|
||||
Table bar = SQL.table("bar");
|
||||
|
||||
assertThatThrownBy(() -> {
|
||||
StatementBuilder.delete() //
|
||||
.from(bar) //
|
||||
.where(new SimpleCondition(column, "=", "foo")) //
|
||||
.build();
|
||||
}).isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("Required table [table] by a WHERE predicate not imported by FROM [bar]");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link InsertBuilder}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class InsertBuilderUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldCreateSimpleInsert() {
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column foo = table.column("foo");
|
||||
Column bar = table.column("bar");
|
||||
|
||||
Insert insert = StatementBuilder.insert().into(table).column(foo).column(bar).value(SQL.bindMarker()).build();
|
||||
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
insert.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(insert, new Into(table), table, foo, table, bar, table,
|
||||
new Values(SQL.bindMarker()));
|
||||
|
||||
assertThat(insert.toString()).isEqualTo("INSERT INTO mytable (mytable.foo, mytable.bar) VALUES(?)");
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class SelectBuilderUnitTests {
|
||||
|
||||
Select select = builder.select(foo, bar).from(table).build();
|
||||
|
||||
CapturingSelectVisitor visitor = new CapturingSelectVisitor();
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
select.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(foo, table, bar, table, new From(table), table);
|
||||
@@ -58,7 +58,7 @@ public class SelectBuilderUnitTests {
|
||||
|
||||
Select select = builder.top(10).select(foo).from(table).build();
|
||||
|
||||
CapturingSelectVisitor visitor = new CapturingSelectVisitor();
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
select.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(foo, table, new From(table), table);
|
||||
@@ -78,7 +78,7 @@ public class SelectBuilderUnitTests {
|
||||
|
||||
Select select = builder.select(foo, bar).from(table1, table2).build();
|
||||
|
||||
CapturingSelectVisitor visitor = new CapturingSelectVisitor();
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
select.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(foo, table1, bar, table2, new From(table1, table2), table1, table2);
|
||||
@@ -96,7 +96,7 @@ public class SelectBuilderUnitTests {
|
||||
OrderByField orderByField = OrderByField.from(foo).asc();
|
||||
Select select = builder.select(foo).from(table).orderBy(orderByField).build();
|
||||
|
||||
CapturingSelectVisitor visitor = new CapturingSelectVisitor();
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
select.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(foo, table, new From(table), table, orderByField, foo);
|
||||
@@ -118,7 +118,7 @@ public class SelectBuilderUnitTests {
|
||||
.and(SQL.column("tenant", employee)).equals(SQL.column("tenant", department))
|
||||
.orderBy(OrderByField.from(name).asc()).build();
|
||||
|
||||
CapturingSelectVisitor visitor = new CapturingSelectVisitor();
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
select.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).filteredOn(Join.class::isInstance).hasSize(1);
|
||||
@@ -131,20 +131,4 @@ public class SelectBuilderUnitTests {
|
||||
assertThat(join.getType()).isEqualTo(JoinType.JOIN);
|
||||
}
|
||||
|
||||
static class CapturingSelectVisitor implements Visitor {
|
||||
|
||||
final List<Visitable> enter = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void enter(Visitable segment) {
|
||||
enter.add(segment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leave(Visitable segment) {
|
||||
leave.add(segment);
|
||||
}
|
||||
|
||||
final List<Visitable> leave = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link UpdateBuilder}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class UpdateBuilderUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldCreateSimpleUpdate() {
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column column = table.column("foo");
|
||||
|
||||
Update update = StatementBuilder.update(table).set(column.set(SQL.bindMarker())).build();
|
||||
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
update.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(update, table, Assignments.value(column, SQL.bindMarker()), column,
|
||||
table, SQL.bindMarker());
|
||||
|
||||
assertThat(update.toString()).isEqualTo("UPDATE mytable SET mytable.foo = ?");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldCreateUpdateWIthCondition() {
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column column = table.column("foo");
|
||||
|
||||
Update update = StatementBuilder.update(table).set(column.set(SQL.bindMarker())).where(column.isNull()).build();
|
||||
|
||||
CapturingVisitor visitor = new CapturingVisitor();
|
||||
update.visit(visitor);
|
||||
|
||||
assertThat(visitor.enter).containsSequence(update, table, Assignments.value(column, SQL.bindMarker()), column,
|
||||
table, SQL.bindMarker(), column.isNull());
|
||||
|
||||
assertThat(update.toString()).isEqualTo("UPDATE mytable SET mytable.foo = ? WHERE mytable.foo IS NULL");
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ public class ConditionRendererUnitTests {
|
||||
public void shouldRenderEquals() {
|
||||
|
||||
String sql = SqlRenderer
|
||||
.render(StatementBuilder.select(left).from(table).where(left.isEqualTo(right)).build());
|
||||
.toString(StatementBuilder.select(left).from(table).where(left.isEqualTo(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left = my_table.right");
|
||||
}
|
||||
@@ -47,11 +47,11 @@ public class ConditionRendererUnitTests {
|
||||
public void shouldRenderNotEquals() {
|
||||
|
||||
String sql = SqlRenderer
|
||||
.render(StatementBuilder.select(left).from(table).where(left.isNotEqualTo(right)).build());
|
||||
.toString(StatementBuilder.select(left).from(table).where(left.isNotEqualTo(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left != my_table.right");
|
||||
|
||||
sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.isEqualTo(right).not()).build());
|
||||
sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.isEqualTo(right).not()).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left != my_table.right");
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class ConditionRendererUnitTests {
|
||||
@Test // DATAJDBC-309
|
||||
public void shouldRenderIsLess() {
|
||||
|
||||
String sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.isLess(right)).build());
|
||||
String sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.isLess(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left < my_table.right");
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class ConditionRendererUnitTests {
|
||||
public void shouldRenderIsLessOrEqualTo() {
|
||||
|
||||
String sql = SqlRenderer
|
||||
.render(StatementBuilder.select(left).from(table).where(left.isLessOrEqualTo(right)).build());
|
||||
.toString(StatementBuilder.select(left).from(table).where(left.isLessOrEqualTo(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left <= my_table.right");
|
||||
}
|
||||
@@ -77,7 +77,7 @@ public class ConditionRendererUnitTests {
|
||||
public void shouldRenderIsGreater() {
|
||||
|
||||
String sql = SqlRenderer
|
||||
.render(StatementBuilder.select(left).from(table).where(left.isGreater(right)).build());
|
||||
.toString(StatementBuilder.select(left).from(table).where(left.isGreater(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left > my_table.right");
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class ConditionRendererUnitTests {
|
||||
public void shouldRenderIsGreaterOrEqualTo() {
|
||||
|
||||
String sql = SqlRenderer
|
||||
.render(StatementBuilder.select(left).from(table).where(left.isGreaterOrEqualTo(right)).build());
|
||||
.toString(StatementBuilder.select(left).from(table).where(left.isGreaterOrEqualTo(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left >= my_table.right");
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public class ConditionRendererUnitTests {
|
||||
@Test // DATAJDBC-309
|
||||
public void shouldRenderIn() {
|
||||
|
||||
String sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.in(right)).build());
|
||||
String sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.in(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left IN (my_table.right)");
|
||||
}
|
||||
@@ -102,7 +102,7 @@ public class ConditionRendererUnitTests {
|
||||
@Test // DATAJDBC-309
|
||||
public void shouldRenderLike() {
|
||||
|
||||
String sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.like(right)).build());
|
||||
String sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.like(right)).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left LIKE my_table.right");
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public class ConditionRendererUnitTests {
|
||||
@Test // DATAJDBC-309
|
||||
public void shouldRenderIsNull() {
|
||||
|
||||
String sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.isNull()).build());
|
||||
String sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.isNull()).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left IS NULL");
|
||||
}
|
||||
@@ -118,11 +118,11 @@ public class ConditionRendererUnitTests {
|
||||
@Test // DATAJDBC-309
|
||||
public void shouldRenderIsNotNull() {
|
||||
|
||||
String sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.isNotNull()).build());
|
||||
String sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.isNotNull()).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left IS NOT NULL");
|
||||
|
||||
sql = SqlRenderer.render(StatementBuilder.select(left).from(table).where(left.isNull().not()).build());
|
||||
sql = SqlRenderer.toString(StatementBuilder.select(left).from(table).where(left.isNull().not()).build());
|
||||
|
||||
assertThat(sql).endsWith("WHERE my_table.left IS NOT NULL");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Delete;
|
||||
import org.springframework.data.relational.core.sql.SQL;
|
||||
import org.springframework.data.relational.core.sql.Table;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SqlRenderer}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class DeleteRendererUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderWithoutWhere() {
|
||||
|
||||
Table bar = SQL.table("bar");
|
||||
|
||||
Delete delete = Delete.builder().from(bar).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(delete)).isEqualTo("DELETE FROM bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderWithCondition() {
|
||||
|
||||
Table table = Table.create("bar");
|
||||
|
||||
Delete delete = Delete.builder().from(table).where(table.column("foo").isEqualTo(table.column("baz")))
|
||||
.and(table.column("doe").isNull()).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(delete)).isEqualTo("DELETE FROM bar WHERE bar.foo = bar.baz AND bar.doe IS NULL");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldConsiderTableAlias() {
|
||||
|
||||
Table table = Table.create("bar").as("my_bar");
|
||||
|
||||
Delete delete = Delete.builder().from(table).where(table.column("foo").isEqualTo(table.column("baz"))).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(delete)).isEqualTo("DELETE FROM bar AS my_bar WHERE my_bar.foo = my_bar.baz");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Insert;
|
||||
import org.springframework.data.relational.core.sql.SQL;
|
||||
import org.springframework.data.relational.core.sql.Table;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SqlRenderer}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class InsertRendererUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderInsert() {
|
||||
|
||||
Table bar = SQL.table("bar");
|
||||
|
||||
Insert insert = Insert.builder().into(bar).values(SQL.bindMarker()).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(insert)).isEqualTo("INSERT INTO bar VALUES(?)");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderInsertColumn() {
|
||||
|
||||
Table bar = SQL.table("bar");
|
||||
|
||||
Insert insert = Insert.builder().into(bar).column(bar.column("foo")).values(SQL.bindMarker()).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(insert)).isEqualTo("INSERT INTO bar (bar.foo) VALUES(?)");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderInsertMultipleColumns() {
|
||||
|
||||
Table bar = SQL.table("bar");
|
||||
|
||||
Insert insert = Insert.builder().into(bar).columns(bar.columns("foo", "baz")).value(SQL.bindMarker())
|
||||
.value(SQL.literalOf("foo")).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(insert)).isEqualTo("INSERT INTO bar (bar.foo, bar.baz) VALUES(?, 'foo')");
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Paluch
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class SqlRendererUnitTests {
|
||||
public class SelectRendererUnitTests {
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
public void shouldRenderSingleColumn() {
|
||||
@@ -44,7 +44,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(foo).from(bar).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT bar.foo FROM bar");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT bar.foo FROM bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -54,7 +54,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(table.column("foo").as("my_foo")).from(table).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT my_bar.foo AS my_foo FROM bar AS my_bar");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT my_bar.foo AS my_foo FROM bar AS my_bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -66,7 +66,7 @@ public class SqlRendererUnitTests {
|
||||
Select select = Select.builder().select(table1.column("col1")).select(table2.column("col2")).from(table1)
|
||||
.from(table2).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT table1.col1, table2.col2 FROM table1, table2");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT table1.col1, table2.col2 FROM table1, table2");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -78,7 +78,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().distinct().select(foo, bar).from(table).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT DISTINCT bar.foo, bar.bar FROM bar");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT DISTINCT bar.foo, bar.bar FROM bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -90,7 +90,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(Functions.count(foo), bar).from(table).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT COUNT(bar.foo), bar.bar FROM bar");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT COUNT(bar.foo), bar.bar FROM bar");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -103,7 +103,7 @@ public class SqlRendererUnitTests {
|
||||
.join(department).on(employee.column("department_id")).equals(department.column("id")) //
|
||||
.build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT employee.id, department.name FROM employee "
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT employee.id, department.name FROM employee "
|
||||
+ "JOIN department ON employee.department_id = department.id");
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class SqlRendererUnitTests {
|
||||
.and(employee.column("tenant")).equals(department.column("tenant")) //
|
||||
.build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT employee.id, department.name FROM employee "
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT employee.id, department.name FROM employee "
|
||||
+ "JOIN department ON employee.department_id = department.id " + "AND employee.tenant = department.tenant");
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public class SqlRendererUnitTests {
|
||||
.join(tenant).on(tenant.column("tenant_id")).equals(department.column("tenant")) //
|
||||
.build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT employee.id, department.name FROM employee "
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT employee.id, department.name FROM employee "
|
||||
+ "JOIN department ON employee.department_id = department.id " + "AND employee.tenant = department.tenant "
|
||||
+ "JOIN tenant AS tenant_base ON tenant_base.tenant_id = department.tenant");
|
||||
}
|
||||
@@ -148,7 +148,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(column).from(employee).orderBy(OrderByField.from(column).asc()).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select))
|
||||
assertThat(SqlRenderer.toString(select))
|
||||
.isEqualTo("SELECT emp.name AS emp_name FROM employee AS emp ORDER BY emp_name ASC");
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(bar).from("foo").limitOffset(10, 20).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT foo.bar FROM foo LIMIT 10 OFFSET 20");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT foo.bar FROM foo LIMIT 10 OFFSET 20");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -171,7 +171,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(bar).from(table).where(Conditions.isNull(bar)).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IS NULL");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IS NULL");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -182,7 +182,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(bar).from(table).where(Conditions.isNull(bar).not()).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IS NOT NULL");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IS NOT NULL");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -194,7 +194,7 @@ public class SqlRendererUnitTests {
|
||||
Select select = Select.builder().select(bar).from(table).where(Conditions.isEqual(bar, SQL.bindMarker(":name")))
|
||||
.build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar = :name");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar = :name");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -207,7 +207,7 @@ public class SqlRendererUnitTests {
|
||||
Select select = Select.builder().select(bar).from(table).where(Conditions.isEqual(bar, SQL.bindMarker(":name"))
|
||||
.or(Conditions.isEqual(bar, SQL.bindMarker(":name2"))).and(Conditions.isNull(baz))).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select))
|
||||
assertThat(SqlRenderer.toString(select))
|
||||
.isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar = :name OR foo.bar = :name2 AND foo.baz IS NULL");
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(bar).from(table).where(Conditions.in(bar, SQL.bindMarker(":name"))).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IN (:name)");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IN (:name)");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -231,7 +231,7 @@ public class SqlRendererUnitTests {
|
||||
Select select = Select.builder().select(bar).from(table)
|
||||
.where(Conditions.in(bar, SQL.bindMarker(":name"), SQL.bindMarker(":name2"))).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IN (:name, :name2)");
|
||||
assertThat(SqlRenderer.toString(select)).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IN (:name, :name2)");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-309
|
||||
@@ -247,7 +247,7 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(bar).from(foo).where(Conditions.in(bar, subselect)).build();
|
||||
|
||||
assertThat(SqlRenderer.render(select))
|
||||
assertThat(SqlRenderer.toString(select))
|
||||
.isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar IN (SELECT floo.bah FROM floo)");
|
||||
}
|
||||
|
||||
@@ -260,14 +260,14 @@ public class SqlRendererUnitTests {
|
||||
|
||||
Select select = Select.builder().select(bar).from(foo).where(bar.isEqualTo(baz)).build();
|
||||
|
||||
String upper = SqlRenderer.create(select, new SimpleRenderContext(NamingStrategies.toUpper())).render();
|
||||
String upper = SqlRenderer.create(new SimpleRenderContext(NamingStrategies.toUpper())).render(select);
|
||||
assertThat(upper).isEqualTo("SELECT FOO.BAR FROM FOO WHERE FOO.BAR = FOO.BAZ");
|
||||
|
||||
String lower = SqlRenderer.create(select, new SimpleRenderContext(NamingStrategies.toLower())).render();
|
||||
String lower = SqlRenderer.create(new SimpleRenderContext(NamingStrategies.toLower())).render(select);
|
||||
assertThat(lower).isEqualTo("SELECT foo.bar FROM foo WHERE foo.bar = foo.baz");
|
||||
|
||||
String mapped = SqlRenderer
|
||||
.create(select, new SimpleRenderContext(NamingStrategies.mapWith(StringUtils::uncapitalize))).render();
|
||||
String mapped = SqlRenderer.create(new SimpleRenderContext(NamingStrategies.mapWith(StringUtils::uncapitalize)))
|
||||
.render(select);
|
||||
assertThat(mapped).isEqualTo("SELECT foo.baR FROM foo WHERE foo.baR = foo.baZ");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.relational.core.sql.render;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.relational.core.sql.Column;
|
||||
import org.springframework.data.relational.core.sql.SQL;
|
||||
import org.springframework.data.relational.core.sql.StatementBuilder;
|
||||
import org.springframework.data.relational.core.sql.Table;
|
||||
import org.springframework.data.relational.core.sql.Update;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SqlRenderer}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class UpdateRendererUnitTests {
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderSimpleUpdate() {
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column column = table.column("foo");
|
||||
|
||||
Update update = StatementBuilder.update(table).set(column.set(SQL.bindMarker())).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(update)).isEqualTo("UPDATE mytable SET mytable.foo = ?");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldRenderUpdateWithLiteral() {
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column column = table.column("foo");
|
||||
|
||||
Update update = StatementBuilder.update(table).set(column.set(SQL.literalOf(20))).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(update)).isEqualTo("UPDATE mytable SET mytable.foo = 20");
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-335
|
||||
public void shouldCreateUpdateWIthCondition() {
|
||||
|
||||
Table table = SQL.table("mytable");
|
||||
Column column = table.column("foo");
|
||||
|
||||
Update update = StatementBuilder.update(table).set(column.set(SQL.bindMarker())).where(column.isNull()).build();
|
||||
|
||||
assertThat(SqlRenderer.toString(update)).isEqualTo("UPDATE mytable SET mytable.foo = ? WHERE mytable.foo IS NULL");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user