Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve some MySQL compatibility issues #1944

Merged
merged 3 commits into from May 23, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -21,6 +21,12 @@ <h1>Change Log</h1>

<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #1942: MySQL Mode: convertInsertNullToZero should be turned off by default?
</li>
<li>Issue #1940: MySQL Mode: Modify column from NOT NULL to NULL syntax
</li>
<li>PR #1941: Extract OFFSET / FETCH handling from Select and SelectUnion to Query
</li>
<li>Issue #1938: Regression with CREATE OR REPLACE VIEW. Causes "Duplicate column name" exception.
</li>
<li>PR #1937: Get rid of FunctionCursorResultSet
@@ -903,11 +903,7 @@ <h3>MySQL Compatibility Mode</h3>
When case-insensitive identifiers are needed append <code>;CASE_INSENSITIVE_IDENTIFIERS=TRUE</code> to URL.
Do not change value of DATABASE_TO_LOWER after creation of database.
</p>
<ul><li>When inserting data, if a column is defined to be <code>NOT NULL</code>
and <code>NULL</code> is inserted,
then a 0 (or empty string, or the current timestamp for timestamp columns) value is used.
Usually, this operation is not allowed and an exception is thrown.
</li><li>Creating indexes in the <code>CREATE TABLE</code> statement is allowed using
<ul><li>Creating indexes in the <code>CREATE TABLE</code> statement is allowed using
<code>INDEX(..)</code> or <code>KEY(..)</code>.
Example: <code>create table test(id int primary key, name varchar(255), key idx_name(name));</code>
</li><li>When converting a floating point number to an integer, the fractional
@@ -7593,7 +7593,8 @@ private Prepared parseAlterTable() {
}
break;
case NO_NULL_CONSTRAINT_FOUND:
command = parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists);
command = parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists,
database.getMode().getEnum() != ModeEnum.MySQL);
break;
default:
throw DbException.get(ErrorCode.UNKNOWN_MODE_1,
@@ -7704,7 +7705,7 @@ private Prepared parseAlterTable() {
command.setSelectivity(readExpression());
return command;
} else {
return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists);
return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists, true);
}
} else if (database.getMode().getEnum() == ModeEnum.MySQL && readIf("AUTO_INCREMENT")) {
readIf(EQUAL);
@@ -7758,10 +7759,10 @@ private Prepared commandIfTableExists(Schema schema, String tableName,
}

private AlterTableAlterColumn parseAlterTableAlterColumnType(Schema schema,
String tableName, String columnName, boolean ifTableExists) {
String tableName, String columnName, boolean ifTableExists, boolean preserveNotNull) {
Column oldColumn = columnIfTableExists(schema, tableName, columnName, ifTableExists);
Column newColumn = parseColumnForTable(columnName,
oldColumn == null ? true : oldColumn.isNullable(), true);
!preserveNotNull || oldColumn == null || oldColumn.isNullable(), true);
if (readIf(CHECK)) {
Expression expr = readExpression();
newColumn.addCheckConstraint(session, expr);
@@ -60,14 +60,6 @@
*/
public boolean aliasColumnName;

/**
* When inserting data, if a column is defined to be NOT NULL and NULL is
* inserted, then a 0 (or empty string, or the current timestamp for
* timestamp columns) value is used. Usually, this operation is not allowed
* and an exception is thrown.
*/
public boolean convertInsertNullToZero;

/**
* When converting the scale of decimal data, the number is only converted
* if the new scale is smaller than the current scale. Usually, the scale is
@@ -299,7 +291,6 @@
add(mode);

mode = new Mode(ModeEnum.MySQL);
mode.convertInsertNullToZero = true;
mode.indexDefinitionInCreateTable = true;
mode.lowerCaseIdentifiers = true;
// Next one is for MariaDB
@@ -29,11 +29,8 @@
import org.h2.value.DataType;
import org.h2.value.TypeInfo;
import org.h2.value.Value;
import org.h2.value.ValueInt;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueString;
import org.h2.value.ValueTime;
import org.h2.value.ValueUuid;

/**
@@ -398,25 +395,7 @@ public Value validateConvertUpdateSequence(Session session, Value value) {
}
}
if (value == ValueNull.INSTANCE && !nullable) {
if (mode.convertInsertNullToZero) {
int t = type.getValueType();
DataType dt = DataType.getDataType(t);
if (dt.decimal) {
value = ValueInt.get(0).convertTo(t);
} else if (dt.type == Value.TIMESTAMP) {
value = session.getCurrentCommandStart().convertTo(Value.TIMESTAMP);
} else if (dt.type == Value.TIMESTAMP_TZ) {
value = session.getCurrentCommandStart();
} else if (dt.type == Value.TIME) {
value = ValueTime.fromNanos(0);
} else if (dt.type == Value.DATE) {
value = session.getCurrentCommandStart().convertTo(Value.DATE);
} else {
value = ValueString.get("").convertTo(t);
}
} else {
throw DbException.get(ErrorCode.NULL_NOT_ALLOWED, name);
}
throw DbException.get(ErrorCode.NULL_NOT_ALLOWED, name);
}
}
if (checkConstraint != null) {
@@ -121,3 +121,50 @@ SET MODE Regular;

DROP TABLE TEST;
> ok

-- Compatibility syntax

CREATE MEMORY TABLE TEST(V INT NOT NULL);
> ok

ALTER TABLE TEST MODIFY COLUMN V BIGINT;
> ok

SCRIPT NODATA NOPASSWORDS NOSETTINGS TABLE TEST;
> SCRIPT
> -----------------------------------------------------------
> -- 0 +/- SELECT COUNT(*) FROM PUBLIC.TEST;
> CREATE MEMORY TABLE "PUBLIC"."TEST"( "V" BIGINT NOT NULL );
> CREATE USER IF NOT EXISTS "SA" PASSWORD '' ADMIN;
> rows: 3

SET MODE MySQL;
> ok

ALTER TABLE TEST MODIFY COLUMN V INT;
> ok

SCRIPT NODATA NOPASSWORDS NOSETTINGS TABLE TEST;
> SCRIPT
> -------------------------------------------------
> -- 0 +/- SELECT COUNT(*) FROM PUBLIC.TEST;
> CREATE MEMORY TABLE "PUBLIC"."TEST"( "V" INT );
> CREATE USER IF NOT EXISTS "SA" PASSWORD '' ADMIN;
> rows: 3

ALTER TABLE TEST MODIFY COLUMN V BIGINT NOT NULL;
> ok

SCRIPT NODATA NOPASSWORDS NOSETTINGS TABLE TEST;
> SCRIPT
> -----------------------------------------------------------
> -- 0 +/- SELECT COUNT(*) FROM PUBLIC.TEST;
> CREATE MEMORY TABLE "PUBLIC"."TEST"( "V" BIGINT NOT NULL );
> CREATE USER IF NOT EXISTS "SA" PASSWORD '' ADMIN;
> rows: 3

SET MODE Regular;
> ok

DROP TABLE TEST;
> ok
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.