Browse Source
SqlGenerator basically got rewritten using the new SQL rendering API. The SQL rendering API got some minor improvements in the process. The whole generation process is now based on paths instead of properties which makes the actual logic of the construction much more obvious. Original pull request: #147.pull/148/head
34 changed files with 1886 additions and 884 deletions
@ -0,0 +1,300 @@
@@ -0,0 +1,300 @@
|
||||
/* |
||||
* 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.jdbc.core; |
||||
|
||||
import java.util.Objects; |
||||
|
||||
import org.springframework.data.mapping.PersistentPropertyPath; |
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
||||
import org.springframework.lang.Nullable; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* A wrapper around a {@link org.springframework.data.mapping.PersistentPropertyPath} for making common operations |
||||
* available used in SQL generation. |
||||
* |
||||
* @author Jens Schauder |
||||
* @since 1.1 |
||||
*/ |
||||
class PersistentPropertyPathExtension { |
||||
|
||||
private final RelationalPersistentEntity<?> entity; |
||||
private final PersistentPropertyPath<RelationalPersistentProperty> path; |
||||
private final RelationalMappingContext context; |
||||
|
||||
PersistentPropertyPathExtension(RelationalMappingContext context, RelationalPersistentEntity<?> entity) { |
||||
|
||||
Assert.notNull(context, "Context must not be null."); |
||||
Assert.notNull(entity, "Entity must not be null."); |
||||
|
||||
this.context = context; |
||||
this.entity = entity; |
||||
this.path = null; |
||||
} |
||||
|
||||
PersistentPropertyPathExtension(RelationalMappingContext context, |
||||
PersistentPropertyPath<RelationalPersistentProperty> path) { |
||||
|
||||
Assert.notNull(context, "Context must not be null."); |
||||
Assert.notNull(path, "Path must not be null."); |
||||
Assert.isTrue(!path.isEmpty(), "Path must not be empty."); |
||||
|
||||
this.context = context; |
||||
this.entity = Objects.requireNonNull(path.getBaseProperty()).getOwner(); |
||||
this.path = path; |
||||
} |
||||
|
||||
/** |
||||
* Returns {@literal true} exactly when the path is non empty and the leaf property an embedded one. |
||||
* |
||||
* @return if the leaf property is embedded. |
||||
*/ |
||||
boolean isEmbedded() { |
||||
return path != null && path.getRequiredLeafProperty().isEmbedded(); |
||||
} |
||||
|
||||
/** |
||||
* Returns the path that has the same beginning but is one segment shorter than this path. |
||||
* |
||||
* @return the parent path. Guaranteed to be not {@literal null}. |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
PersistentPropertyPathExtension getParentPath() { |
||||
|
||||
if (path == null) { |
||||
throw new IllegalStateException("The parent path of a root path is not defined."); |
||||
} |
||||
|
||||
if (path.getLength() == 1) { |
||||
return new PersistentPropertyPathExtension(context, entity); |
||||
} |
||||
|
||||
return new PersistentPropertyPathExtension(context, path.getParentPath()); |
||||
} |
||||
|
||||
/** |
||||
* Returns {@literal true} if there are multiple values for this path, i.e. if the path contains at least one element |
||||
* that is a collection and array or a map. |
||||
* |
||||
* @return {@literal true} if the path contains a multivalued element. |
||||
*/ |
||||
boolean isMultiValued() { |
||||
|
||||
return path != null && //
|
||||
(path.getRequiredLeafProperty().isCollectionLike() //
|
||||
|| path.getRequiredLeafProperty().isQualified() //
|
||||
|| getParentPath().isMultiValued() //
|
||||
); |
||||
} |
||||
|
||||
/** |
||||
* The {@link RelationalPersistentEntity} associated with the leaf of this path. |
||||
* |
||||
* @return Might return {@literal null} when called on a path that does not represent an entity. |
||||
*/ |
||||
@Nullable |
||||
RelationalPersistentEntity<?> getLeafEntity() { |
||||
return path == null ? entity : context.getPersistentEntity(path.getRequiredLeafProperty().getActualType()); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} when this is an empty path or the path references an entity. |
||||
*/ |
||||
boolean isEntity() { |
||||
return path == null || path.getRequiredLeafProperty().isEntity(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} when this is references a {@link java.util.List} or {@link java.util.Map}. |
||||
*/ |
||||
boolean isQualified() { |
||||
return path != null && path.getRequiredLeafProperty().isQualified(); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} when this is references a {@link java.util.Collection} or an array. |
||||
*/ |
||||
boolean isCollectionLike() { |
||||
return path != null && path.getRequiredLeafProperty().isCollectionLike(); |
||||
} |
||||
|
||||
/** |
||||
* The name of the column used to reference the id in the parent table. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
String getReverseColumnName() { |
||||
|
||||
return path.getRequiredLeafProperty().getReverseColumnName(); |
||||
} |
||||
|
||||
/** |
||||
* The alias used in select for the column used to reference the id in the parent table. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
String getReverseColumnNameAlias() { |
||||
|
||||
return prefixWithTableAlias(getReverseColumnName()); |
||||
} |
||||
|
||||
/** |
||||
* The name of the column used to represent this property in the database. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
String getColumnName() { |
||||
|
||||
return assembleColumnName(path.getRequiredLeafProperty().getColumnName()); |
||||
} |
||||
|
||||
/** |
||||
* The alias for the column used to represent this property in the database. |
||||
* |
||||
* @throws IllegalStateException when called on an empty path. |
||||
*/ |
||||
String getColumnAlias() { |
||||
|
||||
return prefixWithTableAlias(getColumnName()); |
||||
} |
||||
|
||||
/** |
||||
* @return {@literal true} if this path represents an entity which has an Id attribute. |
||||
*/ |
||||
boolean hasIdProperty() { |
||||
|
||||
RelationalPersistentEntity<?> leafEntity = getLeafEntity(); |
||||
return leafEntity != null && leafEntity.hasIdProperty(); |
||||
} |
||||
|
||||
PersistentPropertyPathExtension getIdDefiningParentPath() { |
||||
|
||||
PersistentPropertyPathExtension parent = getParentPath(); |
||||
if (parent.path == null) { |
||||
return parent; |
||||
} |
||||
if (parent.isEmbedded()) { |
||||
return getParentPath().getIdDefiningParentPath(); |
||||
} |
||||
return parent; |
||||
} |
||||
|
||||
/** |
||||
* The name of the table this path is tied to or of the longest ancestor path that is actually tied to a table. |
||||
* |
||||
* @return the name of the table. Guaranteed to be not {@literal null}. |
||||
*/ |
||||
String getTableName() { |
||||
return getTableOwningAncestor().getRequiredLeafEntity().getTableName(); |
||||
} |
||||
|
||||
/** |
||||
* The alias used for the table on which this path is based. |
||||
* |
||||
* @return a table alias, {@literal null} if the table owning path is the empty path. |
||||
*/ |
||||
@Nullable |
||||
String getTableAlias() { |
||||
|
||||
PersistentPropertyPathExtension tableOwner = getTableOwningAncestor(); |
||||
if (tableOwner.path == null) { |
||||
return null; |
||||
} |
||||
|
||||
return tableOwner.assembleTableAlias(); |
||||
} |
||||
|
||||
/** |
||||
* The column name of the id column of the ancestor path that represents an actual table. |
||||
*/ |
||||
String getIdColumnName() { |
||||
return getTableOwningAncestor().getRequiredLeafEntity().getIdColumn(); |
||||
} |
||||
|
||||
/** |
||||
* If the table owning ancestor has an id the column name of that id property is returned. Otherwise the reverse |
||||
* column is returned. |
||||
*/ |
||||
String getEffectiveIdColumnName() { |
||||
|
||||
PersistentPropertyPathExtension owner = getTableOwningAncestor(); |
||||
return owner.path == null ? owner.getRequiredLeafEntity().getIdColumn() : owner.getReverseColumnName(); |
||||
} |
||||
|
||||
/** |
||||
* The length of the path. |
||||
*/ |
||||
int getLength() { |
||||
return path == null ? 0 : path.getLength(); |
||||
} |
||||
|
||||
/** |
||||
* Finds and returns the longest path with ich identical or an ancestor to the current path and maps directly to a |
||||
* table. |
||||
* |
||||
* @return a path. Guaranteed to be not {@literal null}. |
||||
*/ |
||||
private PersistentPropertyPathExtension getTableOwningAncestor() { |
||||
|
||||
if (isEntity() && !isEmbedded()) { |
||||
return this; |
||||
} |
||||
return getParentPath().getTableOwningAncestor(); |
||||
} |
||||
|
||||
private String assembleTableAlias() { |
||||
|
||||
RelationalPersistentProperty leafProperty = path.getRequiredLeafProperty(); |
||||
String prefix = isEmbedded() ? leafProperty.getEmbeddedPrefix() : leafProperty.getName(); |
||||
|
||||
if (path.getLength() == 1) { |
||||
Assert.notNull(prefix, "Prefix mus not be null."); |
||||
return prefix; |
||||
} |
||||
|
||||
PersistentPropertyPathExtension parentPath = getParentPath(); |
||||
return parentPath.isEmbedded() ? parentPath.assembleTableAlias() + prefix |
||||
: parentPath.assembleTableAlias() + "_" + prefix; |
||||
} |
||||
|
||||
private String assembleColumnName(String suffix) { |
||||
|
||||
if (path.getLength() <= 1) { |
||||
return suffix; |
||||
} |
||||
PersistentPropertyPath<RelationalPersistentProperty> parentPath = path.getParentPath(); |
||||
RelationalPersistentProperty parentLeaf = parentPath.getRequiredLeafProperty(); |
||||
if (!parentLeaf.isEmbedded()) { |
||||
return suffix; |
||||
} |
||||
String embeddedPrefix = parentLeaf.getEmbeddedPrefix(); |
||||
return getParentPath().assembleColumnName(embeddedPrefix + suffix); |
||||
} |
||||
|
||||
private RelationalPersistentEntity<?> getRequiredLeafEntity() { |
||||
return path == null ? entity : context.getRequiredPersistentEntity(path.getRequiredLeafProperty().getActualType()); |
||||
} |
||||
|
||||
|
||||
private String prefixWithTableAlias(String columnName) { |
||||
|
||||
String tableAlias = getTableAlias(); |
||||
return tableAlias == null ? columnName : tableAlias + "_" + columnName; |
||||
} |
||||
|
||||
} |
||||
@ -1,335 +0,0 @@
@@ -1,335 +0,0 @@
|
||||
/* |
||||
* Copyright 2017-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 |
||||
* |
||||
* https://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.jdbc.core; |
||||
|
||||
import lombok.Builder; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.function.Function; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* Builder for creating Select-statements. Not intended for general purpose, but only for the needs of the |
||||
* {@link JdbcAggregateTemplate}. |
||||
* |
||||
* @author Jens Schauder |
||||
*/ |
||||
class SelectBuilder { |
||||
|
||||
private final List<Column> columns = new ArrayList<>(); |
||||
private final String tableName; |
||||
private final List<Join> joins = new ArrayList<>(); |
||||
private final List<WhereCondition> conditions = new ArrayList<>(); |
||||
|
||||
/** |
||||
* Creates a {@link SelectBuilder} using the given table name. |
||||
* |
||||
* @param tableName the table name. Must not be {@code null}. |
||||
*/ |
||||
SelectBuilder(String tableName) { |
||||
|
||||
this.tableName = tableName; |
||||
} |
||||
|
||||
/** |
||||
* Adds a column to the select list. |
||||
* |
||||
* @param columnSpec a function that specifies the column to add. The passed in {@link Column.ColumnBuilder} allows to |
||||
* specify details like alias and the source table. Must not be {@code null}. |
||||
* @return {@code this}. |
||||
*/ |
||||
SelectBuilder column(Function<Column.ColumnBuilder, Column.ColumnBuilder> columnSpec) { |
||||
|
||||
columns.add(columnSpec.apply(Column.builder()).build()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Adds a where clause to the select |
||||
* |
||||
* @param whereSpec a function specifying the details of the where clause by manipulating the passed in |
||||
* {@link WhereConditionBuilder}. Must not be {@code null}. |
||||
* @return {@code this}. |
||||
*/ |
||||
SelectBuilder where(Function<WhereConditionBuilder, WhereConditionBuilder> whereSpec) { |
||||
|
||||
conditions.add(whereSpec.apply(new WhereConditionBuilder()).build()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Adds a join to the select. |
||||
* |
||||
* @param joinSpec a function specifying the details of the join by manipulating the passed in |
||||
* {@link Join.JoinBuilder}. Must not be {@code null}. |
||||
* @return {@code this}. |
||||
*/ |
||||
SelectBuilder join(Function<Join.JoinBuilder, Join.JoinBuilder> joinSpec) { |
||||
|
||||
joins.add(joinSpec.apply(Join.builder()).build()); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* Builds the actual SQL statement. |
||||
* |
||||
* @return a SQL statement. Guaranteed to be not {@code null}. |
||||
*/ |
||||
String build() { |
||||
|
||||
return selectFrom() + joinClause() + whereClause(); |
||||
} |
||||
|
||||
private String whereClause() { |
||||
|
||||
if (conditions.isEmpty()) { |
||||
return ""; |
||||
} |
||||
|
||||
return conditions.stream() //
|
||||
.map(WhereCondition::toSql) //
|
||||
.collect(Collectors.joining("AND", " WHERE ", "") //
|
||||
); |
||||
} |
||||
|
||||
private String joinClause() { |
||||
return joins.stream().map(j -> joinTable(j) + joinConditions(j)).collect(Collectors.joining(" ")); |
||||
} |
||||
|
||||
private String joinTable(Join j) { |
||||
return String.format("%s JOIN %s AS %s", j.outerJoinModifier(), j.table, j.as); |
||||
} |
||||
|
||||
private String joinConditions(Join j) { |
||||
|
||||
return j.conditions.stream() //
|
||||
.map(w -> String.format("%s %s %s", w.fromExpression, w.operation, w.toExpression)) //
|
||||
.collect(Collectors.joining(" AND ", " ON ", "")); |
||||
} |
||||
|
||||
private String selectFrom() { |
||||
|
||||
return columns.stream() //
|
||||
.map(Column::columnDefinition) //
|
||||
.collect(Collectors.joining(", ", "SELECT ", " FROM " + tableName)); |
||||
} |
||||
|
||||
static class WhereConditionBuilder { |
||||
|
||||
private String fromTable; |
||||
private String fromColumn; |
||||
|
||||
private String operation = "="; |
||||
private String expression; |
||||
|
||||
WhereConditionBuilder() {} |
||||
|
||||
WhereConditionBuilder eq() { |
||||
|
||||
this.operation = "="; |
||||
return this; |
||||
} |
||||
|
||||
public WhereConditionBuilder in() { |
||||
|
||||
this.operation = "in"; |
||||
return this; |
||||
} |
||||
|
||||
WhereConditionBuilder tableAlias(String fromTable) { |
||||
|
||||
this.fromTable = fromTable; |
||||
return this; |
||||
} |
||||
|
||||
WhereConditionBuilder column(String fromColumn) { |
||||
|
||||
this.fromColumn = fromColumn; |
||||
return this; |
||||
} |
||||
|
||||
WhereConditionBuilder variable(String var) { |
||||
|
||||
this.expression = ":" + var; |
||||
return this; |
||||
} |
||||
|
||||
WhereCondition build() { |
||||
return new WhereCondition(fromTable + "." + fromColumn, operation, expression); |
||||
} |
||||
|
||||
} |
||||
|
||||
static class Join { |
||||
|
||||
private final String table; |
||||
private final String as; |
||||
private final Outer outer; |
||||
private final List<WhereCondition> conditions = new ArrayList<>(); |
||||
|
||||
Join(String table, String as, List<WhereCondition> conditions, Outer outer) { |
||||
|
||||
this.table = table; |
||||
this.as = as; |
||||
this.outer = outer; |
||||
this.conditions.addAll(conditions); |
||||
} |
||||
|
||||
static JoinBuilder builder() { |
||||
return new JoinBuilder(); |
||||
} |
||||
|
||||
private String outerJoinModifier() { |
||||
|
||||
switch (outer) { |
||||
case NONE: |
||||
return ""; |
||||
default: |
||||
return String.format(" %s OUTER", outer.name()); |
||||
|
||||
} |
||||
} |
||||
|
||||
public static class JoinBuilder { |
||||
|
||||
private String table; |
||||
private String as; |
||||
private List<WhereCondition> conditions = new ArrayList<>(); |
||||
private Outer outer = Outer.NONE; |
||||
|
||||
JoinBuilder() {} |
||||
|
||||
public Join.JoinBuilder table(String table) { |
||||
|
||||
this.table = table; |
||||
return this; |
||||
} |
||||
|
||||
public Join.JoinBuilder as(String as) { |
||||
|
||||
this.as = as; |
||||
return this; |
||||
} |
||||
|
||||
WhereConditionBuilder where(String column) { |
||||
return new WhereConditionBuilder(this, column); |
||||
} |
||||
|
||||
private JoinBuilder where(WhereCondition condition) { |
||||
|
||||
conditions.add(condition); |
||||
return this; |
||||
} |
||||
|
||||
Join build() { |
||||
return new Join(table, as, conditions, outer); |
||||
} |
||||
|
||||
public String toString() { |
||||
return "org.springframework.data.jdbc.core.SelectBuilder.Join.JoinBuilder(table=" + this.table + ", as=" |
||||
+ this.as + ")"; |
||||
} |
||||
|
||||
JoinBuilder rightOuter() { |
||||
|
||||
outer = Outer.RIGHT; |
||||
return this; |
||||
} |
||||
|
||||
JoinBuilder leftOuter() { |
||||
outer = Outer.LEFT; |
||||
return this; |
||||
} |
||||
|
||||
static class WhereConditionBuilder { |
||||
|
||||
private final JoinBuilder joinBuilder; |
||||
private final String fromColumn; |
||||
|
||||
private String operation = "="; |
||||
|
||||
WhereConditionBuilder(JoinBuilder joinBuilder, String column) { |
||||
|
||||
this.joinBuilder = joinBuilder; |
||||
this.fromColumn = column; |
||||
} |
||||
|
||||
WhereConditionBuilder eq() { |
||||
operation = "="; |
||||
return this; |
||||
} |
||||
|
||||
JoinBuilder column(String table, String column) { |
||||
|
||||
return joinBuilder.where(new WhereCondition( //
|
||||
joinBuilder.as + "." + fromColumn, //
|
||||
operation, //
|
||||
table + "." + column //
|
||||
)); |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
private enum Outer { |
||||
NONE, RIGHT, LEFT |
||||
} |
||||
} |
||||
|
||||
static class WhereCondition { |
||||
|
||||
private final String operation; |
||||
private final String fromExpression; |
||||
private final String toExpression; |
||||
|
||||
WhereCondition(String fromExpression, String operation, String toExpression) { |
||||
|
||||
this.fromExpression = fromExpression; |
||||
this.toExpression = toExpression; |
||||
this.operation = operation; |
||||
} |
||||
|
||||
String toSql() { |
||||
|
||||
if (operation.equals("in")) { |
||||
return String.format("%s %s(%s)", fromExpression, operation, toExpression); |
||||
} |
||||
|
||||
return String.format("%s %s %s", fromExpression, operation, toExpression); |
||||
} |
||||
} |
||||
|
||||
@Builder |
||||
static class Column { |
||||
|
||||
private final String tableAlias; |
||||
private final String column; |
||||
private final String as; |
||||
|
||||
String columnDefinition() { |
||||
StringBuilder b = new StringBuilder(); |
||||
if (tableAlias != null) |
||||
b.append(tableAlias).append('.'); |
||||
b.append(column); |
||||
if (as != null) |
||||
b.append(" AS ").append(as); |
||||
return b.toString(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
/* |
||||
* 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.jdbc.core; |
||||
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.sql.Column; |
||||
import org.springframework.data.relational.core.sql.SQL; |
||||
import org.springframework.data.relational.core.sql.Table; |
||||
|
||||
/** |
||||
* Utility to get from path to SQL DSL elements. |
||||
* |
||||
* @author Jens Schauder |
||||
* @since 1.1 |
||||
*/ |
||||
class SqlContext { |
||||
|
||||
private final RelationalPersistentEntity<?> entity; |
||||
|
||||
SqlContext(RelationalPersistentEntity<?> entity) { |
||||
this.entity = entity; |
||||
} |
||||
|
||||
Column getIdColumn() { |
||||
return getTable().column(entity.getIdColumn()); |
||||
} |
||||
|
||||
Table getTable(PersistentPropertyPathExtension path) { |
||||
|
||||
String tableAlias = path.getTableAlias(); |
||||
Table table = SQL.table(path.getTableName()); |
||||
return tableAlias == null ? table : table.as(tableAlias); |
||||
} |
||||
|
||||
Table getTable() { |
||||
return SQL.table(entity.getTableName()); |
||||
} |
||||
|
||||
Column getColumn(PersistentPropertyPathExtension path) { |
||||
return getTable(path).column(path.getColumnName()).as(path.getColumnAlias()); |
||||
} |
||||
|
||||
Column getReverseColumn(PersistentPropertyPathExtension path) { |
||||
return getTable(path).column(path.getReverseColumnName()).as(path.getReverseColumnNameAlias()); |
||||
} |
||||
} |
||||
@ -0,0 +1,174 @@
@@ -0,0 +1,174 @@
|
||||
/* |
||||
* 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.jdbc.core; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.assertj.core.api.SoftAssertions; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.junit.Test; |
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext; |
||||
import org.springframework.data.mapping.PersistentPropertyPath; |
||||
import org.springframework.data.relational.core.mapping.Embedded; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; |
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; |
||||
|
||||
/** |
||||
* @author Jens Schauder |
||||
*/ |
||||
public class PersistentPropertyPathExtensionUnitTests { |
||||
|
||||
JdbcMappingContext context = new JdbcMappingContext(); |
||||
private RelationalPersistentEntity<?> entity = context.getRequiredPersistentEntity(DummyEntity.class); |
||||
|
||||
@Test |
||||
public void isEmbedded() { |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).isEmbedded()).isFalse(); |
||||
softly.assertThat(extPath("second").isEmbedded()).isFalse(); |
||||
softly.assertThat(extPath("second.third").isEmbedded()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
public void isMultiValued() { |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).isMultiValued()).isFalse(); |
||||
softly.assertThat(extPath("second").isMultiValued()).isFalse(); |
||||
softly.assertThat(extPath("second.third").isMultiValued()).isFalse(); |
||||
softly.assertThat(extPath("secondList.third").isMultiValued()).isTrue(); |
||||
softly.assertThat(extPath("secondList").isMultiValued()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
public void leafEntity() { |
||||
|
||||
RelationalPersistentEntity<?> second = context.getRequiredPersistentEntity(Second.class); |
||||
RelationalPersistentEntity<?> third = context.getRequiredPersistentEntity(Third.class); |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getLeafEntity()).isEqualTo(entity); |
||||
softly.assertThat(extPath("second").getLeafEntity()).isEqualTo(second); |
||||
softly.assertThat(extPath("second.third").getLeafEntity()).isEqualTo(third); |
||||
softly.assertThat(extPath("secondList.third").getLeafEntity()).isEqualTo(third); |
||||
softly.assertThat(extPath("secondList").getLeafEntity()).isEqualTo(second); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
public void isEntity() { |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).isEntity()).isTrue(); |
||||
String path = "second"; |
||||
softly.assertThat(extPath(path).isEntity()).isTrue(); |
||||
softly.assertThat(extPath("second.third").isEntity()).isTrue(); |
||||
softly.assertThat(extPath("second.third.value").isEntity()).isFalse(); |
||||
softly.assertThat(extPath("secondList.third").isEntity()).isTrue(); |
||||
softly.assertThat(extPath("secondList.third.value").isEntity()).isFalse(); |
||||
softly.assertThat(extPath("secondList").isEntity()).isTrue(); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
public void getTableName() { |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getTableName()).isEqualTo("dummy_entity"); |
||||
softly.assertThat(extPath("second").getTableName()).isEqualTo("second"); |
||||
softly.assertThat(extPath("second.third").getTableName()).isEqualTo("second"); |
||||
softly.assertThat(extPath("second.third.value").getTableName()).isEqualTo("second"); |
||||
softly.assertThat(extPath("secondList.third").getTableName()).isEqualTo("second"); |
||||
softly.assertThat(extPath("secondList.third.value").getTableName()).isEqualTo("second"); |
||||
softly.assertThat(extPath("secondList").getTableName()).isEqualTo("second"); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
public void getTableAlias() { |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath(entity).getTableAlias()).isEqualTo(null); |
||||
softly.assertThat(extPath("second").getTableAlias()).isEqualTo("second"); |
||||
softly.assertThat(extPath("second.third").getTableAlias()).isEqualTo("second"); |
||||
softly.assertThat(extPath("second.third.value").getTableAlias()).isEqualTo("second"); |
||||
softly.assertThat(extPath("second.third2").getTableAlias()).isEqualTo("second_third2"); |
||||
softly.assertThat(extPath("second.third2.value").getTableAlias()).isEqualTo("second_third2"); |
||||
softly.assertThat(extPath("secondList.third").getTableAlias()).isEqualTo("secondList"); |
||||
softly.assertThat(extPath("secondList.third.value").getTableAlias()).isEqualTo("secondList"); |
||||
softly.assertThat(extPath("secondList.third2").getTableAlias()).isEqualTo("secondList_third2"); |
||||
softly.assertThat(extPath("secondList.third2.value").getTableAlias()).isEqualTo("secondList_third2"); |
||||
softly.assertThat(extPath("secondList").getTableAlias()).isEqualTo("secondList"); |
||||
softly.assertThat(extPath("second2.third2").getTableAlias()).isEqualTo("secthird2"); |
||||
}); |
||||
} |
||||
|
||||
@Test |
||||
public void getColumnName() { |
||||
|
||||
SoftAssertions.assertSoftly(softly -> { |
||||
|
||||
softly.assertThat(extPath("second.third.value").getColumnName()).isEqualTo("thrdvalue"); |
||||
softly.assertThat(extPath("second.third2.value").getColumnName()).isEqualTo("value"); |
||||
softly.assertThat(extPath("secondList.third.value").getColumnName()).isEqualTo("thrdvalue"); |
||||
softly.assertThat(extPath("secondList.third2.value").getColumnName()).isEqualTo("value"); |
||||
softly.assertThat(extPath("second2.third.value").getColumnName()).isEqualTo("secthrdvalue"); |
||||
softly.assertThat(extPath("second2.third2.value").getColumnName()).isEqualTo("value"); |
||||
}); |
||||
} |
||||
|
||||
@NotNull |
||||
private PersistentPropertyPathExtension extPath(RelationalPersistentEntity<?> entity) { |
||||
return new PersistentPropertyPathExtension(context, entity); |
||||
} |
||||
|
||||
@NotNull |
||||
private PersistentPropertyPathExtension extPath(String path) { |
||||
return new PersistentPropertyPathExtension(context, createSimplePath(path)); |
||||
} |
||||
|
||||
PersistentPropertyPath<RelationalPersistentProperty> createSimplePath(String path) { |
||||
return PropertyPathTestingUtils.toPath(path, DummyEntity.class, context); |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class DummyEntity { |
||||
Second second; |
||||
List<Second> secondList; |
||||
@Embedded("sec") Second second2; |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class Second { |
||||
@Embedded("thrd") Third third; |
||||
Third third2; |
||||
} |
||||
|
||||
@SuppressWarnings("unused") |
||||
static class Third { |
||||
String value; |
||||
} |
||||
|
||||
} |
||||
@ -1,89 +0,0 @@
@@ -1,89 +0,0 @@
|
||||
/* |
||||
* Copyright 2017-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 |
||||
* |
||||
* https://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.jdbc.core; |
||||
|
||||
import static org.assertj.core.api.Assertions.*; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
/** |
||||
* Unit tests for the {@link SelectBuilder}. |
||||
* |
||||
* @author Jens Schauder |
||||
*/ |
||||
public class SelectBuilderUnitTests { |
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void simplestSelect() { |
||||
|
||||
String sql = new SelectBuilder("mytable") //
|
||||
.column(cb -> cb.tableAlias("mytable").column("mycolumn").as("myalias")) //
|
||||
.build(); |
||||
|
||||
assertThat(sql).isEqualTo("SELECT mytable.mycolumn AS myalias FROM mytable"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void columnWithoutTableAlias() { |
||||
|
||||
String sql = new SelectBuilder("mytable") //
|
||||
.column(cb -> cb.column("mycolumn").as("myalias")) //
|
||||
.build(); |
||||
|
||||
assertThat(sql).isEqualTo("SELECT mycolumn AS myalias FROM mytable"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void whereClause() { |
||||
|
||||
String sql = new SelectBuilder("mytable") //
|
||||
.column(cb -> cb.tableAlias("mytable").column("mycolumn").as("myalias")) //
|
||||
.where(cb -> cb.tableAlias("mytable").column("mycolumn").eq().variable("var")).build(); |
||||
|
||||
assertThat(sql).isEqualTo("SELECT mytable.mycolumn AS myalias FROM mytable WHERE mytable.mycolumn = :var"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void multipleColumnsSelect() { |
||||
|
||||
String sql = new SelectBuilder("mytable") //
|
||||
.column(cb -> cb.tableAlias("mytable").column("one").as("oneAlias")) //
|
||||
.column(cb -> cb.tableAlias("mytable").column("two").as("twoAlias")) //
|
||||
.build(); |
||||
|
||||
assertThat(sql).isEqualTo("SELECT mytable.one AS oneAlias, mytable.two AS twoAlias FROM mytable"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void join() { |
||||
String sql = new SelectBuilder("mytable") //
|
||||
.column(cb -> cb.tableAlias("mytable").column("mycolumn").as("myalias")) //
|
||||
.join(jb -> jb.table("other").as("o").where("oid").eq().column("mytable", "id")).build(); |
||||
|
||||
assertThat(sql).isEqualTo("SELECT mytable.mycolumn AS myalias FROM mytable JOIN other AS o ON o.oid = mytable.id"); |
||||
} |
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void outerJoin() { |
||||
String sql = new SelectBuilder("mytable") //
|
||||
.column(cb -> cb.tableAlias("mytable").column("mycolumn").as("myalias")) //
|
||||
.join(jb -> jb.rightOuter().table("other").as("o").where("oid").eq().column("mytable", "id")).build(); |
||||
|
||||
assertThat(sql) |
||||
.isEqualTo("SELECT mytable.mycolumn AS myalias FROM mytable RIGHT OUTER JOIN other AS o ON o.oid = mytable.id"); |
||||
} |
||||
|
||||
} |
||||
@ -1,20 +1,93 @@
@@ -1,20 +1,93 @@
|
||||
CREATE TABLE LEGO_SET ( id1 BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, NAME VARCHAR(30)); |
||||
CREATE TABLE MANUAL ( id2 BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, LEGO_SET BIGINT, ALTERNATIVE BIGINT, CONTENT VARCHAR(2000)); |
||||
CREATE TABLE LEGO_SET |
||||
( |
||||
id1 BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, |
||||
NAME VARCHAR(30) |
||||
); |
||||
CREATE TABLE MANUAL |
||||
( |
||||
id2 BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, |
||||
LEGO_SET BIGINT, |
||||
ALTERNATIVE BIGINT, |
||||
CONTENT VARCHAR(2000) |
||||
); |
||||
|
||||
ALTER TABLE MANUAL ADD FOREIGN KEY (LEGO_SET) |
||||
REFERENCES LEGO_SET(id1); |
||||
ALTER TABLE MANUAL |
||||
ADD FOREIGN KEY (LEGO_SET) |
||||
REFERENCES LEGO_SET (id1); |
||||
|
||||
CREATE TABLE ONE_TO_ONE_PARENT ( id3 BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE ONE_TO_ONE_PARENT |
||||
( |
||||
id3 BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
CREATE TABLE Child_No_Id |
||||
( |
||||
ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, NAME VARCHAR(100)); |
||||
CREATE TABLE ELEMENT_NO_ID ( content VARCHAR(100), LIST_PARENT_KEY BIGINT, LIST_PARENT BIGINT); |
||||
CREATE TABLE LIST_PARENT |
||||
( |
||||
id4 BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, |
||||
NAME VARCHAR(100) |
||||
); |
||||
CREATE TABLE ELEMENT_NO_ID |
||||
( |
||||
content VARCHAR(100), |
||||
LIST_PARENT_KEY BIGINT, |
||||
LIST_PARENT BIGINT |
||||
); |
||||
ALTER TABLE ELEMENT_NO_ID |
||||
ADD FOREIGN KEY (LIST_PARENT) |
||||
REFERENCES LIST_PARENT(id4); |
||||
REFERENCES LIST_PARENT (id4); |
||||
|
||||
CREATE TABLE ARRAY_OWNER |
||||
( |
||||
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, |
||||
DIGITS VARCHAR(20) ARRAY[10] NOT NULL, |
||||
MULTIDIMENSIONAL VARCHAR(20) ARRAY[10] NULL |
||||
); |
||||
|
||||
CREATE TABLE ARRAY_OWNER (ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, DIGITS VARCHAR(20) ARRAY[10] NOT NULL, MULTIDIMENSIONAL VARCHAR(20) ARRAY[10] NULL); |
||||
CREATE TABLE BYTE_ARRAY_OWNER |
||||
( |
||||
ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, |
||||
BINARY_DATA VARBINARY(20) NOT NULL |
||||
); |
||||
|
||||
CREATE TABLE BYTE_ARRAY_OWNER (ID BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY, BINARY_DATA VARBINARY(20) NOT NULL); |
||||
CREATE TABLE CHAIN4 |
||||
( |
||||
FOUR BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 40) PRIMARY KEY, |
||||
FOUR_VALUE VARCHAR(20) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN3 |
||||
( |
||||
THREE BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 30) PRIMARY KEY, |
||||
THREE_VALUE VARCHAR(20), |
||||
CHAIN4 BIGINT, |
||||
FOREIGN KEY (CHAIN4) REFERENCES CHAIN4 (FOUR) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN2 |
||||
( |
||||
TWO BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 20) PRIMARY KEY, |
||||
TWO_VALUE VARCHAR(20), |
||||
CHAIN3 BIGINT, |
||||
FOREIGN KEY (CHAIN3) REFERENCES CHAIN3 (THREE) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN1 |
||||
( |
||||
ONE BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 10) PRIMARY KEY, |
||||
ONE_VALUE VARCHAR(20), |
||||
CHAIN2 BIGINT, |
||||
FOREIGN KEY (CHAIN2) REFERENCES CHAIN2 (TWO) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN0 |
||||
( |
||||
ZERO BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 0) PRIMARY KEY, |
||||
ZERO_VALUE VARCHAR(20), |
||||
CHAIN1 BIGINT, |
||||
FOREIGN KEY (CHAIN1) REFERENCES CHAIN1 (ONE) |
||||
); |
||||
|
||||
@ -1,13 +1,84 @@
@@ -1,13 +1,84 @@
|
||||
CREATE TABLE LEGO_SET ( id1 BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(30)); |
||||
CREATE TABLE MANUAL ( id2 BIGINT AUTO_INCREMENT PRIMARY KEY, LEGO_SET BIGINT, ALTERNATIVE BIGINT, CONTENT VARCHAR(2000)); |
||||
CREATE TABLE LEGO_SET |
||||
( |
||||
id1 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
NAME VARCHAR(30) |
||||
); |
||||
CREATE TABLE MANUAL |
||||
( |
||||
id2 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
LEGO_SET BIGINT, |
||||
ALTERNATIVE BIGINT, |
||||
CONTENT VARCHAR(2000) |
||||
); |
||||
|
||||
ALTER TABLE MANUAL ADD FOREIGN KEY (LEGO_SET) |
||||
REFERENCES LEGO_SET(id1); |
||||
ALTER TABLE MANUAL |
||||
ADD FOREIGN KEY (LEGO_SET) |
||||
REFERENCES LEGO_SET (id1); |
||||
|
||||
CREATE TABLE ONE_TO_ONE_PARENT ( id3 BIGINT AUTO_INCREMENT PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE ONE_TO_ONE_PARENT |
||||
( |
||||
id3 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
CREATE TABLE Child_No_Id |
||||
( |
||||
ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100)); |
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT); |
||||
CREATE TABLE LIST_PARENT |
||||
( |
||||
id4 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
NAME VARCHAR(100) |
||||
); |
||||
CREATE TABLE element_no_id |
||||
( |
||||
content VARCHAR(100), |
||||
LIST_PARENT_key BIGINT, |
||||
LIST_PARENT BIGINT |
||||
); |
||||
|
||||
CREATE TABLE BYTE_ARRAY_OWNER (ID BIGINT AUTO_INCREMENT PRIMARY KEY, BINARY_DATA VARBINARY(20) NOT NULL) |
||||
CREATE TABLE BYTE_ARRAY_OWNER |
||||
( |
||||
ID BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
BINARY_DATA VARBINARY(20) NOT NULL |
||||
); |
||||
|
||||
CREATE TABLE CHAIN4 |
||||
( |
||||
FOUR BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
FOUR_VALUE VARCHAR(20) |
||||
); |
||||
|
||||
|
||||
CREATE TABLE CHAIN3 |
||||
( |
||||
THREE BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
THREE_VALUE VARCHAR(20), |
||||
CHAIN4 BIGINT, |
||||
FOREIGN KEY (CHAIN4) REFERENCES CHAIN4(FOUR) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN2 |
||||
( |
||||
TWO BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
TWO_VALUE VARCHAR(20), |
||||
CHAIN3 BIGINT, |
||||
FOREIGN KEY (CHAIN3) REFERENCES CHAIN3(THREE) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN1 |
||||
( |
||||
ONE BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
ONE_VALUE VARCHAR(20), |
||||
CHAIN2 BIGINT, |
||||
FOREIGN KEY (CHAIN2) REFERENCES CHAIN2(TWO) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN0 |
||||
( |
||||
ZERO BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
ZERO_VALUE VARCHAR(20), |
||||
CHAIN1 BIGINT, |
||||
FOREIGN KEY (CHAIN1) REFERENCES CHAIN1(ONE) |
||||
); |
||||
|
||||
@ -1,18 +1,93 @@
@@ -1,18 +1,93 @@
|
||||
DROP TABLE IF EXISTS MANUAL; |
||||
DROP TABLE IF EXISTS LEGO_SET; |
||||
CREATE TABLE LEGO_SET ( id1 BIGINT IDENTITY PRIMARY KEY, NAME VARCHAR(30)); |
||||
CREATE TABLE MANUAL ( id2 BIGINT IDENTITY PRIMARY KEY, LEGO_SET BIGINT, ALTERNATIVE BIGINT, CONTENT VARCHAR(2000)); |
||||
ALTER TABLE MANUAL ADD FOREIGN KEY (LEGO_SET) REFERENCES LEGO_SET(id1); |
||||
CREATE TABLE LEGO_SET |
||||
( |
||||
id1 BIGINT IDENTITY PRIMARY KEY, |
||||
NAME VARCHAR(30) |
||||
); |
||||
CREATE TABLE MANUAL |
||||
( |
||||
id2 BIGINT IDENTITY PRIMARY KEY, |
||||
LEGO_SET BIGINT, |
||||
ALTERNATIVE BIGINT, |
||||
CONTENT VARCHAR(2000) |
||||
); |
||||
ALTER TABLE MANUAL |
||||
ADD FOREIGN KEY (LEGO_SET) REFERENCES LEGO_SET (id1); |
||||
|
||||
DROP TABLE IF EXISTS Child_No_Id; |
||||
DROP TABLE IF EXISTS ONE_TO_ONE_PARENT; |
||||
CREATE TABLE ONE_TO_ONE_PARENT ( id3 BIGINT IDENTITY PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT BIGINT PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE ONE_TO_ONE_PARENT |
||||
( |
||||
id3 BIGINT IDENTITY PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
CREATE TABLE Child_No_Id |
||||
( |
||||
ONE_TO_ONE_PARENT BIGINT PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS element_no_id; |
||||
DROP TABLE IF EXISTS LIST_PARENT; |
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT IDENTITY PRIMARY KEY, NAME VARCHAR(100)); |
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT); |
||||
CREATE TABLE LIST_PARENT |
||||
( |
||||
id4 BIGINT IDENTITY PRIMARY KEY, |
||||
NAME VARCHAR(100) |
||||
); |
||||
CREATE TABLE element_no_id |
||||
( |
||||
content VARCHAR(100), |
||||
LIST_PARENT_key BIGINT, |
||||
LIST_PARENT BIGINT |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS BYTE_ARRAY_OWNER; |
||||
CREATE TABLE BYTE_ARRAY_OWNER (ID BIGINT IDENTITY PRIMARY KEY, BINARY_DATA VARBINARY(20) NOT NULL) |
||||
CREATE TABLE BYTE_ARRAY_OWNER |
||||
( |
||||
ID BIGINT IDENTITY PRIMARY KEY, |
||||
BINARY_DATA VARBINARY(20) NOT NULL |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS CHAIN4; |
||||
CREATE TABLE CHAIN4 |
||||
( |
||||
FOUR BIGINT IDENTITY PRIMARY KEY, |
||||
FOUR_VALUE VARCHAR(20) |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS CHAIN3; |
||||
CREATE TABLE CHAIN3 |
||||
( |
||||
THREE BIGINT IDENTITY PRIMARY KEY, |
||||
THREE_VALUE VARCHAR(20), |
||||
CHAIN4 BIGINT, |
||||
FOREIGN KEY (CHAIN4) REFERENCES CHAIN4 (FOUR) |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS CHAIN2; |
||||
CREATE TABLE CHAIN2 |
||||
( |
||||
TWO BIGINT IDENTITY PRIMARY KEY, |
||||
TWO_VALUE VARCHAR(20), |
||||
CHAIN3 BIGINT, |
||||
FOREIGN KEY (CHAIN3) REFERENCES CHAIN3 (THREE) |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS CHAIN1; |
||||
CREATE TABLE CHAIN1 |
||||
( |
||||
ONE BIGINT IDENTITY PRIMARY KEY, |
||||
ONE_VALUE VARCHAR(20), |
||||
CHAIN2 BIGINT, |
||||
FOREIGN KEY (CHAIN2) REFERENCES CHAIN2 (TWO) |
||||
); |
||||
|
||||
DROP TABLE IF EXISTS CHAIN0; |
||||
CREATE TABLE CHAIN0 |
||||
( |
||||
ZERO BIGINT IDENTITY PRIMARY KEY, |
||||
ZERO_VALUE VARCHAR(20), |
||||
CHAIN1 BIGINT, |
||||
FOREIGN KEY (CHAIN1) REFERENCES CHAIN1 (ONE) |
||||
); |
||||
@ -1,13 +1,84 @@
@@ -1,13 +1,84 @@
|
||||
CREATE TABLE LEGO_SET ( id1 BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(30)); |
||||
CREATE TABLE MANUAL ( id2 BIGINT AUTO_INCREMENT PRIMARY KEY, LEGO_SET BIGINT, ALTERNATIVE BIGINT, CONTENT VARCHAR(2000)); |
||||
CREATE TABLE LEGO_SET |
||||
( |
||||
id1 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
NAME VARCHAR(30) |
||||
); |
||||
CREATE TABLE MANUAL |
||||
( |
||||
id2 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
LEGO_SET BIGINT, |
||||
ALTERNATIVE BIGINT, |
||||
CONTENT VARCHAR(2000) |
||||
); |
||||
|
||||
ALTER TABLE MANUAL ADD FOREIGN KEY (LEGO_SET) |
||||
REFERENCES LEGO_SET(id1); |
||||
ALTER TABLE MANUAL |
||||
ADD FOREIGN KEY (LEGO_SET) |
||||
REFERENCES LEGO_SET (id1); |
||||
|
||||
CREATE TABLE ONE_TO_ONE_PARENT ( id3 BIGINT AUTO_INCREMENT PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE Child_No_Id (ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, content VARCHAR(30)); |
||||
CREATE TABLE ONE_TO_ONE_PARENT |
||||
( |
||||
id3 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
CREATE TABLE Child_No_Id |
||||
( |
||||
ONE_TO_ONE_PARENT INTEGER PRIMARY KEY, |
||||
content VARCHAR(30) |
||||
); |
||||
|
||||
CREATE TABLE LIST_PARENT ( id4 BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100)); |
||||
CREATE TABLE element_no_id ( content VARCHAR(100), LIST_PARENT_key BIGINT, LIST_PARENT BIGINT); |
||||
CREATE TABLE LIST_PARENT |
||||
( |
||||
id4 BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
NAME VARCHAR(100) |
||||
); |
||||
CREATE TABLE element_no_id |
||||
( |
||||
content VARCHAR(100), |
||||
LIST_PARENT_key BIGINT, |
||||
LIST_PARENT BIGINT |
||||
); |
||||
|
||||
CREATE TABLE BYTE_ARRAY_OWNER (ID BIGINT AUTO_INCREMENT PRIMARY KEY, BINARY_DATA VARBINARY(20) NOT NULL) |
||||
CREATE TABLE BYTE_ARRAY_OWNER |
||||
( |
||||
ID BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
BINARY_DATA VARBINARY(20) NOT NULL |
||||
); |
||||
|
||||
CREATE TABLE CHAIN4 |
||||
( |
||||
FOUR BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
FOUR_VALUE VARCHAR(20) |
||||
); |
||||
|
||||
|
||||
CREATE TABLE CHAIN3 |
||||
( |
||||
THREE BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
THREE_VALUE VARCHAR(20), |
||||
CHAIN4 BIGINT, |
||||
FOREIGN KEY (CHAIN4) REFERENCES CHAIN4(FOUR) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN2 |
||||
( |
||||
TWO BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
TWO_VALUE VARCHAR(20), |
||||
CHAIN3 BIGINT, |
||||
FOREIGN KEY (CHAIN3) REFERENCES CHAIN3(THREE) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN1 |
||||
( |
||||
ONE BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
ONE_VALUE VARCHAR(20), |
||||
CHAIN2 BIGINT, |
||||
FOREIGN KEY (CHAIN2) REFERENCES CHAIN2(TWO) |
||||
); |
||||
|
||||
CREATE TABLE CHAIN0 |
||||
( |
||||
ZERO BIGINT AUTO_INCREMENT PRIMARY KEY, |
||||
ZERO_VALUE VARCHAR(20), |
||||
CHAIN1 BIGINT, |
||||
FOREIGN KEY (CHAIN1) REFERENCES CHAIN1(ONE) |
||||
); |
||||
Loading…
Reference in new issue