Unverified 提交 6f846985 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1264 from katzyn/ddl

Preserve domain name in columns and add CASCADE | RESTRICT to DROP DOMAIN
......@@ -884,9 +884,11 @@ DROP CONSTANT ONE
"
"Commands (DDL)","DROP DOMAIN","
DROP DOMAIN [ IF EXISTS ] domainName
DROP DOMAIN [ IF EXISTS ] domainName [ RESTRICT | CASCADE ]
","
Drops a data type (domain).
The command will fail if it is referenced by a column (the default).
Column descriptors are replaced with original definition of specified domain if the CASCADE clause is used.
This command commits an open transaction in this connection.
","
DROP DOMAIN EMAIL
......
......@@ -649,7 +649,7 @@ public class Parser {
if (readIf("(")) {
ArrayList<Column> list = Utils.newSmallArrayList();
for (int i = 0;; i++) {
Column column = parseColumnForTable("C" + i, true);
Column column = parseColumnForTable("C" + i, true, false);
list.add(column);
if (!readIfMore(true)) {
break;
......@@ -1789,11 +1789,7 @@ public class Parser {
command.setDeleteFiles(true);
}
return command;
} else if (readIf("DOMAIN")) {
return parseDropUserDataType();
} else if (readIf("TYPE")) {
return parseDropUserDataType();
} else if (readIf("DATATYPE")) {
} else if (readIf("DOMAIN") || readIf("TYPE") || readIf("DATATYPE")) {
return parseDropUserDataType();
} else if (readIf("AGGREGATE")) {
return parseDropAggregate();
......@@ -1815,6 +1811,11 @@ public class Parser {
command.setTypeName(readUniqueIdentifier());
ifExists = readIfExists(ifExists);
command.setIfExists(ifExists);
if (readIf("CASCADE")) {
command.setDropAction(ConstraintActionType.CASCADE);
} else if (readIf("RESTRICT")) {
command.setDropAction(ConstraintActionType.RESTRICT);
}
return command;
}
......@@ -2804,14 +2805,14 @@ public class Parser {
case Function.CAST: {
function.setParameter(0, readExpression());
read("AS");
Column type = parseColumnWithType(null);
Column type = parseColumnWithType(null, false);
function.setDataType(type);
read(")");
break;
}
case Function.CONVERT: {
if (database.getMode().swapConvertFunctionParameters) {
Column type = parseColumnWithType(null);
Column type = parseColumnWithType(null, false);
function.setDataType(type);
read(",");
function.setParameter(0, readExpression());
......@@ -2819,7 +2820,7 @@ public class Parser {
} else {
function.setParameter(0, readExpression());
read(",");
Column type = parseColumnWithType(null);
Column type = parseColumnWithType(null, false);
function.setDataType(type);
read(")");
}
......@@ -2926,7 +2927,7 @@ public class Parser {
ArrayList<Column> columns = Utils.newSmallArrayList();
do {
String columnName = readAliasIdentifier();
Column column = parseColumnWithType(columnName);
Column column = parseColumnWithType(columnName, false);
columns.add(column);
read("=");
function.setParameter(i, readExpression());
......@@ -3368,7 +3369,7 @@ public class Parser {
Expression[] args = { r };
r = new JavaFunction(f, args);
} else {
Column col = parseColumnWithType(null);
Column col = parseColumnWithType(null, false);
Function function = Function.getFunction(database, "CAST");
function.setDataType(col);
function.setParameter(0, r);
......@@ -4212,7 +4213,7 @@ public class Parser {
}
private Column parseColumnForTable(String columnName,
boolean defaultNullable) {
boolean defaultNullable, boolean forTable) {
Column column;
boolean isIdentity = readIf("IDENTITY");
if (isIdentity || readIf("BIGSERIAL")) {
......@@ -4238,7 +4239,7 @@ public class Parser {
column.setPrimaryKey(true);
}
} else {
column = parseColumnWithType(columnName);
column = parseColumnWithType(columnName, forTable);
}
if (readIf("INVISIBLE")) {
column.setVisible(false);
......@@ -4346,7 +4347,7 @@ public class Parser {
return null;
}
private Column parseColumnWithType(String columnName) {
private Column parseColumnWithType(String columnName, boolean forTable) {
String original = currentToken;
boolean regular = false;
int originalScale = -1;
......@@ -4414,7 +4415,7 @@ public class Parser {
templateColumn = userDataType.getColumn();
dataType = DataType.getDataType(templateColumn.getType());
comment = templateColumn.getComment();
original = templateColumn.getOriginalSQL();
original = forTable ? userDataType.getSQL() : templateColumn.getOriginalSQL();
precision = templateColumn.getPrecision();
displaySize = templateColumn.getDisplaySize();
scale = templateColumn.getScale();
......@@ -4584,6 +4585,9 @@ public class Parser {
}
column.setComment(comment);
column.setOriginalSQL(original);
if (forTable) {
column.setUserDataType(userDataType);
}
return column;
}
......@@ -4610,11 +4614,7 @@ public class Parser {
return parseCreateSchema();
} else if (readIf("CONSTANT")) {
return parseCreateConstant();
} else if (readIf("DOMAIN")) {
return parseCreateUserDataType();
} else if (readIf("TYPE")) {
return parseCreateUserDataType();
} else if (readIf("DATATYPE")) {
} else if (readIf("DOMAIN") || readIf("TYPE") || readIf("DATATYPE")) {
return parseCreateUserDataType();
} else if (readIf("AGGREGATE")) {
return parseCreateAggregate(force);
......@@ -5030,7 +5030,7 @@ public class Parser {
CreateUserDataType command = new CreateUserDataType(session);
command.setTypeName(readUniqueIdentifier());
read("AS");
Column col = parseColumnForTable("VALUE", true);
Column col = parseColumnForTable("VALUE", true, false);
if (readIf("CHECK")) {
Expression expr = readExpression();
col.addCheckConstraint(session, expr);
......@@ -6155,7 +6155,7 @@ public class Parser {
boolean nullable = column == null ? true : column.isNullable();
// new column type ignored. RENAME and MODIFY are
// a single command in MySQL but two different commands in H2.
parseColumnForTable(newColumnName, nullable);
parseColumnForTable(newColumnName, nullable, true);
AlterTableRenameColumn command = new AlterTableRenameColumn(session, schema);
command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
......@@ -6336,7 +6336,7 @@ public class Parser {
String tableName, String columnName, boolean ifTableExists) {
Column oldColumn = columnIfTableExists(schema, tableName, columnName, ifTableExists);
Column newColumn = parseColumnForTable(columnName,
oldColumn == null ? true : oldColumn.isNullable());
oldColumn == null ? true : oldColumn.isNullable(), true);
AlterTableAlterColumn command = new AlterTableAlterColumn(session,
schema);
command.setTableName(tableName);
......@@ -6705,7 +6705,7 @@ public class Parser {
command.addConstraintCommand(c);
} else {
String columnName = readColumnIdentifier();
Column column = parseColumnForTable(columnName, true);
Column column = parseColumnForTable(columnName, true, true);
if (column.isAutoIncrement() && column.isPrimaryKey()) {
column.setPrimaryKey(false);
IndexColumn[] cols = { new IndexColumn() };
......
......@@ -7,10 +7,13 @@ package org.h2.command.ddl;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface;
import org.h2.constraint.ConstraintActionType;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.UserDataType;
import org.h2.message.DbException;
import org.h2.table.Column;
import org.h2.table.Table;
/**
* This class represents the statement
......@@ -20,15 +23,22 @@ public class DropUserDataType extends DefineCommand {
private String typeName;
private boolean ifExists;
private ConstraintActionType dropAction;
public DropUserDataType(Session session) {
super(session);
dropAction = session.getDatabase().getSettings().dropRestrict ?
ConstraintActionType.RESTRICT : ConstraintActionType.CASCADE;
}
public void setIfExists(boolean ifExists) {
this.ifExists = ifExists;
}
public void setDropAction(ConstraintActionType dropAction) {
this.dropAction = dropAction;
}
@Override
public int update() {
session.getUser().checkAdmin();
......@@ -40,6 +50,23 @@ public class DropUserDataType extends DefineCommand {
throw DbException.get(ErrorCode.USER_DATA_TYPE_NOT_FOUND_1, typeName);
}
} else {
for (Table t : db.getAllTablesAndViews(false)) {
boolean modified = false;
for (Column c : t.getColumns()) {
UserDataType udt = c.getUserDataType();
if (udt != null && udt.getName().equals(typeName)) {
if (dropAction == ConstraintActionType.RESTRICT) {
throw DbException.get(ErrorCode.CANNOT_DROP_2, typeName, t.getCreateSQL());
}
c.setOriginalSQL(type.getColumn().getOriginalSQL());
c.setUserDataType(null);
modified = true;
}
}
if (modified) {
db.updateMeta(session, t);
}
}
db.removeDatabaseObject(session, type);
}
return 0;
......
......@@ -99,8 +99,8 @@ public class DbSettings extends SettingsBase {
/**
* Database setting <code>DROP_RESTRICT</code> (default: true).<br />
* Whether the default action for DROP TABLE, DROP VIEW, and DROP SCHEMA
* is RESTRICT.
* Whether the default action for DROP TABLE, DROP VIEW, DROP SCHEMA, and
* DROP DOMAIN is RESTRICT.
*/
public final boolean dropRestrict = get("DROP_RESTRICT", true);
......
......@@ -12,6 +12,7 @@ import org.h2.command.Parser;
import org.h2.engine.Constants;
import org.h2.engine.Mode;
import org.h2.engine.Session;
import org.h2.engine.UserDataType;
import org.h2.expression.ConditionAndOr;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor;
......@@ -87,6 +88,7 @@ public class Column {
private String comment;
private boolean primaryKey;
private boolean visible = true;
private UserDataType userDataType;
public Column(String name, int type) {
this(name, type, -1, -1, -1, null);
......@@ -314,6 +316,14 @@ public class Column {
visible = b;
}
public UserDataType getUserDataType() {
return userDataType;
}
public void setUserDataType(UserDataType userDataType) {
this.userDataType = userDataType;
}
/**
* Validate the value, convert it if required, and update the sequence value
* if required. If the value is null, the default value (NULL if no default
......@@ -566,6 +576,8 @@ public class Column {
}
if (!nullable) {
buff.append(" NOT NULL");
} else if (userDataType != null && !userDataType.getColumn().isNullable()) {
buff.append(" NULL");
}
if (convertNullToDefault) {
buff.append(" NULL_TO_DEFAULT");
......
......@@ -124,7 +124,7 @@ public class TestScript extends TestDb {
}
for (String s : new String[] { "alterTableAdd", "alterTableDropColumn",
"createAlias", "createSynonym", "createView", "createTable", "createTrigger",
"dropIndex", "dropSchema", "truncateTable" }) {
"dropDomain", "dropIndex", "dropSchema", "truncateTable" }) {
testScript("ddl/" + s + ".sql");
}
for (String s : new String[] { "error_reporting", "insertIgnore",
......
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE DOMAIN E AS ENUM('A', 'B');
> ok
CREATE DOMAIN E_NN AS ENUM('A', 'B') NOT NULL;
> ok
CREATE TABLE TEST(I INT PRIMARY KEY, E1 E, E2 E NOT NULL, E3 E_NN, E4 E_NN NULL);
> ok
INSERT INTO TEST VALUES (1, 'A', 'B', 'A', 'B');
> update count: 1
SELECT COLUMN_NAME, NULLABLE, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TEST' ORDER BY ORDINAL_POSITION;
> COLUMN_NAME NULLABLE COLUMN_TYPE
> ----------- -------- -------------
> I 0 INT NOT NULL
> E1 1 E
> E2 0 E NOT NULL
> E3 0 E_NN NOT NULL
> E4 1 E_NN NULL
> rows (ordered): 5
DROP DOMAIN E RESTRICT;
> exception CANNOT_DROP_2
DROP DOMAIN E CASCADE;
> ok
DROP DOMAIN E_NN CASCADE;
> ok
SELECT COLUMN_NAME, NULLABLE, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TEST' ORDER BY ORDINAL_POSITION;
> COLUMN_NAME NULLABLE COLUMN_TYPE
> ----------- -------- ----------------------
> I 0 INT NOT NULL
> E1 1 ENUM('A','B')
> E2 0 ENUM('A','B') NOT NULL
> E3 0 ENUM('A','B') NOT NULL
> E4 1 ENUM('A','B')
> rows (ordered): 5
DROP TABLE TEST;
> ok
......@@ -840,10 +840,13 @@ script nodata nopasswords nosettings;
> -----------------------------------------------
> -- 0 +/- SELECT COUNT(*) FROM PUBLIC.TEST;
> CREATE DOMAIN INT AS VARCHAR;
> CREATE MEMORY TABLE PUBLIC.TEST( ID VARCHAR );
> CREATE MEMORY TABLE PUBLIC.TEST( ID INT );
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN;
> rows: 4
SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TEST';
>> 12
drop table test;
> ok
......@@ -2674,7 +2677,7 @@ select DOMAIN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, PRECISION, SCALE, TY
script nodata nopasswords nosettings;
> SCRIPT
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
> -- 1 +/- SELECT COUNT(*) FROM PUBLIC.ADDRESS;
> -- 1 +/- SELECT COUNT(*) FROM PUBLIC.TEST;
> ALTER TABLE PUBLIC.ADDRESS ADD CONSTRAINT PUBLIC.CONSTRAINT_E PRIMARY KEY(ID);
......@@ -2685,8 +2688,8 @@ script nodata nopasswords nosettings;
> CREATE DOMAIN STRING2 AS VARCHAR NOT NULL;
> CREATE DOMAIN STRING3 AS VARCHAR DEFAULT '<empty>';
> CREATE DOMAIN STRING_X AS VARCHAR DEFAULT '<empty>';
> CREATE MEMORY TABLE PUBLIC.ADDRESS( ID INT NOT NULL, NAME VARCHAR(200) CHECK (POSITION('@', NAME) > 1), NAME2 VARCHAR(200) DEFAULT '@gmail.com' CHECK ((POSITION('@', NAME2) > 1) AND (POSITION('gmail', NAME2) > 1)) );
> CREATE MEMORY TABLE PUBLIC.TEST( A VARCHAR(255) DEFAULT '' NOT NULL, B VARCHAR, C VARCHAR NOT NULL, D VARCHAR DEFAULT '<empty>' );
> CREATE MEMORY TABLE PUBLIC.ADDRESS( ID INT NOT NULL, NAME EMAIL CHECK (POSITION('@', NAME) > 1), NAME2 GMAIL DEFAULT '@gmail.com' CHECK ((POSITION('@', NAME2) > 1) AND (POSITION('gmail', NAME2) > 1)) );
> CREATE MEMORY TABLE PUBLIC.TEST( A STRING DEFAULT '' NOT NULL, B STRING1, C STRING2 NOT NULL, D STRING3 DEFAULT '<empty>' );
> CREATE USER IF NOT EXISTS SA PASSWORD '' ADMIN;
> rows: 13
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论