diff --git a/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java b/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java index bf0bc65a02..242bc9b8b1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/AlterTableImpl.java @@ -55,8 +55,8 @@ import static org.jooq.impl.DSL.field; import static org.jooq.impl.DSL.inline; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.sql; -import static org.jooq.impl.Utils.DataKey.DATA_DROP_CONSTRAINT; import static org.jooq.impl.Utils.toSQLDDLTypeDeclaration; +import static org.jooq.impl.Utils.DataKey.DATA_DROP_CONSTRAINT; import org.jooq.AlterTableAlterStep; import org.jooq.AlterTableDropStep; @@ -245,11 +245,13 @@ class AlterTableImpl extends AbstractQuery implements ctx.start(ALTER_TABLE_TABLE) .keyword("alter table").sql(' ').visit(table) - .end(ALTER_TABLE_TABLE); + .end(ALTER_TABLE_TABLE) + .formatIndentStart() + .formatSeparator(); if (addColumn != null) { ctx.start(ALTER_TABLE_ADD) - .sql(' ').keyword("add").sql(' '); + .keyword("add").sql(' '); @@ -282,8 +284,7 @@ class AlterTableImpl extends AbstractQuery implements else if (addConstraint != null) { ctx.start(ALTER_TABLE_ADD); - ctx.sql(' ') - .keyword("add") + ctx.keyword("add") .sql(' ') .visit(addConstraint); @@ -311,18 +312,18 @@ class AlterTableImpl extends AbstractQuery implements if (alterColumnDefault == null) { // MySQL's CHANGE COLUMN clause has a mandatory RENAMING syntax... - ctx.sql(' ').keyword("change column") + ctx.keyword("change column") .sql(' ').qualify(false).visit(alterColumn).qualify(true); } else { - ctx.sql(' ').keyword("alter column"); + ctx.keyword("alter column"); } break; } default: - ctx.sql(' ').keyword("alter"); + ctx.keyword("alter"); break; } @@ -365,7 +366,7 @@ class AlterTableImpl extends AbstractQuery implements default: - ctx.sql(' ').keyword("set default"); + ctx.keyword("set default"); break; } @@ -391,7 +392,7 @@ class AlterTableImpl extends AbstractQuery implements default: - ctx.sql(' ').keyword("drop"); + ctx.keyword("drop"); break; } @@ -421,14 +422,15 @@ class AlterTableImpl extends AbstractQuery implements ctx.start(ALTER_TABLE_DROP); ctx.data(DATA_DROP_CONSTRAINT, true); - ctx.sql(' ') - .keyword("drop") + ctx.keyword("drop") .sql(' ') .visit(dropConstraint); ctx.data().remove(DATA_DROP_CONSTRAINT); ctx.end(ALTER_TABLE_DROP); } + + ctx.formatIndentEnd(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/ConstraintImpl.java b/jOOQ/src/main/java/org/jooq/impl/ConstraintImpl.java index b1ed501980..9293c1745d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ConstraintImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ConstraintImpl.java @@ -48,8 +48,8 @@ import static org.jooq.impl.ConstraintImpl.Action.SET_DEFAULT; import static org.jooq.impl.ConstraintImpl.Action.SET_NULL; import static org.jooq.impl.DSL.name; import static org.jooq.impl.DSL.table; -import static org.jooq.impl.Utils.DataKey.DATA_DROP_CONSTRAINT; import static org.jooq.impl.Utils.fieldsByName; +import static org.jooq.impl.Utils.DataKey.DATA_DROP_CONSTRAINT; import javax.annotation.Generated; @@ -152,14 +152,15 @@ implements public final void accept(Context ctx) { ctx.keyword("constraint") .sql(' ') - .visit(name); + .visit(name) + .formatIndentStart() + .formatSeparator(); if (ctx.data(DATA_DROP_CONSTRAINT) == null) { boolean qualify = ctx.qualify(); if (unique != null) { - ctx.sql(' ') - .keyword("unique") + ctx.keyword("unique") .sql(" (") .qualify(false) .visit(new QueryPartList>(unique)) @@ -167,8 +168,7 @@ implements .sql(')'); } else if (primaryKey != null) { - ctx.sql(' ') - .keyword("primary key") + ctx.keyword("primary key") .sql(" (") .qualify(false) .visit(new QueryPartList>(primaryKey)) @@ -176,13 +176,13 @@ implements .sql(')'); } else if (foreignKey != null) { - ctx.sql(' ') - .keyword("foreign key") + ctx.keyword("foreign key") .sql(" (") .qualify(false) .visit(new QueryPartList>(foreignKey)) .qualify(qualify) - .sql(") ") + .sql(')') + .formatSeparator() .keyword("references") .sql(' ') .visit(referencesTable) @@ -201,8 +201,7 @@ implements .sql(' ').keyword(onUpdate.sql); } else if (check != null) { - ctx.sql(' ') - .keyword("check") + ctx.keyword("check") .sql(" (") .qualify(false) .visit(check) @@ -210,6 +209,8 @@ implements .sql(')'); } } + + ctx.formatIndentEnd(); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/DDL.java b/jOOQ/src/main/java/org/jooq/impl/DDL.java new file mode 100644 index 0000000000..60817182ac --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/DDL.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com) + * All rights reserved. + * + * 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. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import static org.jooq.impl.DSL.constraint; + +import java.util.ArrayList; +import java.util.List; + +import org.jooq.Constraint; +import org.jooq.DSLContext; +import org.jooq.ForeignKey; +import org.jooq.Queries; +import org.jooq.Query; +import org.jooq.Schema; +import org.jooq.Table; +import org.jooq.UniqueKey; + +/** + * @author Lukas Eder + */ +public class DDL { + + private final DSLContext ctx; + + public DDL(DSLContext ctx) { + this.ctx = ctx; + } + + public Queries queries(Table table) { + List constraints = new ArrayList(); + + for (UniqueKey key : table.getKeys()) + if (key.isPrimary()) + constraints.add(constraint(key.getName()).primaryKey(key.getFieldsArray())); + else + constraints.add(constraint(key.getName()).unique(key.getFieldsArray())); + + for (ForeignKey key : table.getReferences()) + constraints.add(constraint(key.getName()).foreignKey(key.getFieldsArray()).references(key.getKey().getTable(), key.getKey().getFieldsArray())); + + return DSL.queries( + ctx.createTable(table) + .columns(table.fields()) + .constraints(constraints) + ); + } + + public Queries queries(Schema schema) { + List queries = new ArrayList(); + + for (Table table : schema.getTables()) { + List constraints = new ArrayList(); + + for (UniqueKey key : table.getKeys()) + if (key.isPrimary()) + constraints.add(constraint(key.getName()).primaryKey(key.getFieldsArray())); + else + constraints.add(constraint(key.getName()).unique(key.getFieldsArray())); + + queries.add( + ctx.createTable(table) + .columns(table.fields()) + .constraints(constraints) + ); + } + + for (Table table : schema.getTables()) + for (ForeignKey key : table.getReferences()) + queries.add(ctx.alterTable(table).add(constraint(key.getName()).foreignKey(key.getFieldsArray()).references(key.getKey().getTable(), key.getKey().getFieldsArray()))); + + return DSL.queries(queries); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java index 9f753914f3..f3cb626152 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java @@ -95,6 +95,8 @@ class DefaultRenderContext extends AbstractContext implements Ren private int indent; private Deque indentLock; private int printMargin = 80; + private boolean separator; + private boolean newline; // [#1632] Cached values from Settings RenderKeywordStyle cachedRenderKeywordStyle; @@ -168,15 +170,12 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext keyword(String keyword) { - if (RenderKeywordStyle.UPPER == cachedRenderKeywordStyle) { - return sql(keyword.toUpperCase()); - } - else if (RenderKeywordStyle.LOWER == cachedRenderKeywordStyle) { - return sql(keyword.toLowerCase()); - } - else { - return sql(keyword); - } + if (RenderKeywordStyle.UPPER == cachedRenderKeywordStyle) + return sql(keyword.toUpperCase(), true); + else if (RenderKeywordStyle.LOWER == cachedRenderKeywordStyle) + return sql(keyword.toLowerCase(), true); + else + return sql(keyword, true); } @Override @@ -193,6 +192,8 @@ class DefaultRenderContext extends AbstractContext implements Ren s = StringUtils.replace(s, "'", stringLiteralEscapedApos); sql.append(s); + separator = false; + newline = false; return this; } @@ -204,20 +205,26 @@ class DefaultRenderContext extends AbstractContext implements Ren if (c == '\'' && stringLiteral()) sql.append(c); + separator = false; + newline = false; return this; } @Override public final RenderContext sql(int i) { sql.append(i); + separator = false; + newline = false; return this; } @Override public final RenderContext formatNewLine() { if (cachedRenderFormatted) { - sql.append("\n"); - sql.append(indentation()); + sql("\n", true); + sql(indentation(), true); + + newline = true; } return this; @@ -225,11 +232,9 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext formatNewLineAfterPrintMargin() { - if (cachedRenderFormatted && printMargin > 0) { - if (sql.length() - sql.lastIndexOf("\n") > printMargin) { + if (cachedRenderFormatted && printMargin > 0) + if (sql.length() - sql.lastIndexOf("\n") > printMargin) formatNewLine(); - } - } return this; } @@ -251,11 +256,13 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext formatSeparator() { - if (cachedRenderFormatted) { - formatNewLine(); - } - else { - sql.append(" "); + if (!separator && !newline) { + if (cachedRenderFormatted) + formatNewLine(); + else + sql(" ", true); + + separator = true; } return this; @@ -273,26 +280,23 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext formatIndentStart(int i) { - if (cachedRenderFormatted) { + if (cachedRenderFormatted) indent += i; - } return this; } @Override public final RenderContext formatIndentEnd(int i) { - if (cachedRenderFormatted) { + if (cachedRenderFormatted) indent -= i; - } return this; } private final Deque indentLock() { - if (indentLock == null) { + if (indentLock == null) indentLock = new ArrayDeque(); - } return indentLock; } @@ -310,9 +314,8 @@ class DefaultRenderContext extends AbstractContext implements Ren @Override public final RenderContext formatIndentLockEnd() { - if (cachedRenderFormatted) { + if (cachedRenderFormatted) indent = indentLock().pop(); - } return this; } @@ -327,9 +330,8 @@ class DefaultRenderContext extends AbstractContext implements Ren public final RenderContext literal(String literal) { // Literal usually originates from NamedQueryPart.getName(). This could // be null for CustomTable et al. - if (literal == null) { + if (literal == null) return this; - } SQLDialect family = family(); @@ -352,14 +354,12 @@ class DefaultRenderContext extends AbstractContext implements Ren (family == SQLITE && !IDENTIFIER_PATTERN.matcher(literal).matches()); if (!needsQuote) { - if (LOWER == cachedRenderNameStyle) { + if (LOWER == cachedRenderNameStyle) literal = literal.toLowerCase(); - } - else if (UPPER == cachedRenderNameStyle) { + else if (UPPER == cachedRenderNameStyle) literal = literal.toUpperCase(); - } - sql(literal); + sql(literal, true); } else { String[][] quotes = QUOTES.get(family); @@ -373,9 +373,9 @@ class DefaultRenderContext extends AbstractContext implements Ren // effect as the replace call can be avoided in almost all // situations if (literal.indexOf(end) > -1) - sql(StringUtils.replace(literal, quotes[QUOTE_END_DELIMITER][0], quotes[QUOTE_END_DELIMITER_ESCAPED][0])); + sql(StringUtils.replace(literal, quotes[QUOTE_END_DELIMITER][0], quotes[QUOTE_END_DELIMITER_ESCAPED][0]), true); else - sql(literal); + sql(literal, true); sql(end); } diff --git a/jOOQ/src/main/java/org/jooq/impl/QueryPartList.java b/jOOQ/src/main/java/org/jooq/impl/QueryPartList.java index 21077afd30..6dcccd9486 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QueryPartList.java +++ b/jOOQ/src/main/java/org/jooq/impl/QueryPartList.java @@ -106,7 +106,7 @@ class QueryPartList extends AbstractQueryPart implements Li } if (indent) - ctx.formatIndentEnd(); + ctx.formatIndentEnd().formatNewLine(); } }