提交 b311beca authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #627 from plus33/master

Fix for "Change not-null / null -constraint to existing column" (MySql/ORACLE - SQL style)
...@@ -21,6 +21,8 @@ Change Log ...@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <ul>
<li>Fix bug in MySQL/ORACLE-syntax silently corrupting the modified column in cases of setting the 'NULL'- or 'NOT NULL'-constraint. E.g. alter table T modify C NULL;
</li>
<li>Issue #570: MySQL compatibility for ALTER TABLE .. DROP INDEX <li>Issue #570: MySQL compatibility for ALTER TABLE .. DROP INDEX
</li> </li>
<li>Issue #537: Include the COLUMN name in message "Numeric value out of range" <li>Issue #537: Include the COLUMN name in message "Numeric value out of range"
......
...@@ -166,6 +166,7 @@ To become a donor, use PayPal (at the very bottom of the main web page). ...@@ -166,6 +166,7 @@ To become a donor, use PayPal (at the very bottom of the main web page).
</li><li>Cristan Meijer, Netherlands </li><li>Cristan Meijer, Netherlands
</li><li>Adam McMahon, USA </li><li>Adam McMahon, USA
</li><li>F&aacute;bio Gomes Lisboa Gomes, Brasil </li><li>F&aacute;bio Gomes Lisboa Gomes, Brasil
</li><li><a href="http://tao.works">Sam Blume, Switzerland</a>
</li></ul> </li></ul>
<!-- [close] { --></div></td></tr></table><!-- } --><!-- analytics --></body></html> <!-- [close] { --></div></td></tr></table><!-- } --><!-- analytics --></body></html>
......
...@@ -344,7 +344,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -344,7 +344,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Allow to scan index backwards starting with a value (to better support ORDER BY DESC). </li><li>Allow to scan index backwards starting with a value (to better support ORDER BY DESC).
</li><li>Java Service Wrapper: try http://yajsw.sourceforge.net/ </li><li>Java Service Wrapper: try http://yajsw.sourceforge.net/
</li><li>Batch parameter for INSERT, UPDATE, and DELETE, and commit after each batch. See also MySQL DELETE. </li><li>Batch parameter for INSERT, UPDATE, and DELETE, and commit after each batch. See also MySQL DELETE.
</li><li>MySQL compatibility: support ALTER TABLE .. MODIFY COLUMN.
</li><li>Use a lazy and auto-close input stream (open resource when reading, close on eof). </li><li>Use a lazy and auto-close input stream (open resource when reading, close on eof).
</li><li>Connection pool: 'reset session' command (delete temp tables, rollback, auto-commit true). </li><li>Connection pool: 'reset session' command (delete temp tables, rollback, auto-commit true).
</li><li>Improve SQL documentation, see http://www.w3schools.com/sql/ </li><li>Improve SQL documentation, see http://www.w3schools.com/sql/
......
...@@ -5869,7 +5869,23 @@ public class Parser { ...@@ -5869,7 +5869,23 @@ public class Parser {
// MySQL compatibility // MySQL compatibility
readIf("COLUMN"); readIf("COLUMN");
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists); if ((isToken("NOT") || isToken("NULL"))) {
AlterTableAlterColumn command = new AlterTableAlterColumn(
session, schema);
command.setTableName(tableName);
command.setIfTableExists(ifTableExists);
Column column = columnIfTableExists(schema, tableName, columnName, ifTableExists);
command.setOldColumn(column);
if (readIf("NOT")) {
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_NOT_NULL);
} else {
read("NULL");
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_NULL);
}
return command;
} else {
return parseAlterTableAlterColumnType(schema, tableName, columnName, ifTableExists);
}
} else if (readIf("ALTER")) { } else if (readIf("ALTER")) {
readIf("COLUMN"); readIf("COLUMN");
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
......
...@@ -51,6 +51,7 @@ public class TestAlter extends TestBase { ...@@ -51,6 +51,7 @@ public class TestAlter extends TestBase {
testAlterTableAddMultipleColumnsBefore(); testAlterTableAddMultipleColumnsBefore();
testAlterTableAddMultipleColumnsAfter(); testAlterTableAddMultipleColumnsAfter();
testAlterTableModifyColumn(); testAlterTableModifyColumn();
testAlterTableModifyColumnSetNull();
conn.close(); conn.close();
deleteDb(getTestName()); deleteDb(getTestName());
} }
...@@ -283,4 +284,27 @@ public class TestAlter extends TestBase { ...@@ -283,4 +284,27 @@ public class TestAlter extends TestBase {
stat.execute("insert into t values('Hello')"); stat.execute("insert into t values('Hello')");
stat.execute("drop table t"); stat.execute("drop table t");
} }
/**
* Test for fix "Change not-null / null -constraint to existing column"
* (MySql/ORACLE - SQL style) that failed silently corrupting the changed
* column.<br/>
* Before the change (added after v1.4.196) following was observed:
* <pre>
* alter table T modify C int null; -- Worked as expected
* alter table T modify C null; -- Silently corrupted column C
* </pre>
*/
private void testAlterTableModifyColumnSetNull() throws SQLException {
// This worked in v1.4.196
stat.execute("create table T (C varchar not null)");
stat.execute("alter table T modify C int null");
stat.execute("insert into T values(null)");
stat.execute("drop table T");
// This failed in v1.4.196
stat.execute("create table T (C int not null)");
stat.execute("alter table T modify C null"); // Silently corrupted column C
stat.execute("insert into T values(null)"); // <- ERROR: NULL not allowed
stat.execute("drop table T");
}
} }
...@@ -1305,10 +1305,6 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1305,10 +1305,6 @@ public class TestFunctions extends TestBase implements AggregateFunction {
} }
private void testToDate() throws ParseException { private void testToDate() throws ParseException {
if (Locale.getDefault() != Locale.ENGLISH) {
return;
}
final int month = Calendar.getInstance().get(Calendar.MONTH); final int month = Calendar.getInstance().get(Calendar.MONTH);
Date date = null; Date date = null;
...@@ -1418,23 +1414,25 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1418,23 +1414,25 @@ public class TestFunctions extends TestBase implements AggregateFunction {
date = new SimpleDateFormat("yyyy-MM-dd").parse("2013-01-29"); date = new SimpleDateFormat("yyyy-MM-dd").parse("2013-01-29");
assertEquals(date, ToDateParser.toDate("113029", "J")); assertEquals(date, ToDateParser.toDate("113029", "J"));
date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss") if (Locale.getDefault() == Locale.ENGLISH) {
date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.parse("9999-12-31T23:59:59"); .parse("9999-12-31T23:59:59");
assertEquals(date, ToDateParser.toDate("31-DEC-9999 23:59:59", assertEquals(date, ToDateParser.toDate("31-DEC-9999 23:59:59",
"DD-MON-YYYY HH24:MI:SS")); "DD-MON-YYYY HH24:MI:SS"));
assertEquals(date, ToDateParser.toDate("31-DEC-9999 23:59:59", assertEquals(date, ToDateParser.toDate("31-DEC-9999 23:59:59",
"DD-MON-RRRR HH24:MI:SS")); "DD-MON-RRRR HH24:MI:SS"));
SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd"); SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");
assertEquals(ymd.parse("0001-03-01"), ToDateParser.toDate("1-MAR-0001", "DD-MON-RRRR")); assertEquals(ymd.parse("0001-03-01"), ToDateParser.toDate("1-MAR-0001", "DD-MON-RRRR"));
assertEquals(ymd.parse("9999-03-01"), ToDateParser.toDate("1-MAR-9999", "DD-MON-RRRR")); assertEquals(ymd.parse("9999-03-01"), ToDateParser.toDate("1-MAR-9999", "DD-MON-RRRR"));
assertEquals(ymd.parse("2000-03-01"), ToDateParser.toDate("1-MAR-000", "DD-MON-RRRR")); assertEquals(ymd.parse("2000-03-01"), ToDateParser.toDate("1-MAR-000", "DD-MON-RRRR"));
assertEquals(ymd.parse("1999-03-01"), ToDateParser.toDate("1-MAR-099", "DD-MON-RRRR")); assertEquals(ymd.parse("1999-03-01"), ToDateParser.toDate("1-MAR-099", "DD-MON-RRRR"));
assertEquals(ymd.parse("0100-03-01"), ToDateParser.toDate("1-MAR-100", "DD-MON-RRRR")); assertEquals(ymd.parse("0100-03-01"), ToDateParser.toDate("1-MAR-100", "DD-MON-RRRR"));
assertEquals(ymd.parse("2000-03-01"), ToDateParser.toDate("1-MAR-00", "DD-MON-RRRR")); assertEquals(ymd.parse("2000-03-01"), ToDateParser.toDate("1-MAR-00", "DD-MON-RRRR"));
assertEquals(ymd.parse("2049-03-01"), ToDateParser.toDate("1-MAR-49", "DD-MON-RRRR")); assertEquals(ymd.parse("2049-03-01"), ToDateParser.toDate("1-MAR-49", "DD-MON-RRRR"));
assertEquals(ymd.parse("1950-03-01"), ToDateParser.toDate("1-MAR-50", "DD-MON-RRRR")); assertEquals(ymd.parse("1950-03-01"), ToDateParser.toDate("1-MAR-50", "DD-MON-RRRR"));
assertEquals(ymd.parse("1999-03-01"), ToDateParser.toDate("1-MAR-99", "DD-MON-RRRR")); assertEquals(ymd.parse("1999-03-01"), ToDateParser.toDate("1-MAR-99", "DD-MON-RRRR"));
}
} }
private static void setMonth(Date date, int month) { private static void setMonth(Date date, int month) {
...@@ -1732,13 +1730,26 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1732,13 +1730,26 @@ public class TestFunctions extends TestBase implements AggregateFunction {
"SELECT TO_CHAR(12345, '$999') FROM DUAL"); "SELECT TO_CHAR(12345, '$999') FROM DUAL");
assertResult("######", stat, assertResult("######", stat,
"SELECT TO_CHAR(12345, '$9999') FROM DUAL"); "SELECT TO_CHAR(12345, '$9999') FROM DUAL");
assertResult(" " + cs + "12345", stat,
"SELECT TO_CHAR(12345, '$99999999') FROM DUAL");
assertResult(" " + cs + "12,345.35", stat,
"SELECT TO_CHAR(12345.345, '$99,999,999.99') FROM DUAL");
String expected = String.format("%,d", 12345); String expected = String.format("%,d", 12345);
assertResult(" " + cs + expected, stat, if (Locale.getDefault() == Locale.ENGLISH) {
assertResult(String.format("%5s12345", cs), stat,
"SELECT TO_CHAR(12345, '$99999999') FROM DUAL");
assertResult(String.format("%6s12,345.35", cs), stat,
"SELECT TO_CHAR(12345.345, '$99,999,999.99') FROM DUAL");
assertResult(String.format("%5s%s", cs, expected), stat,
"SELECT TO_CHAR(12345.345, '$99g999g999') FROM DUAL"); "SELECT TO_CHAR(12345.345, '$99g999g999') FROM DUAL");
assertResult(" " + cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'L999.99') FROM DUAL");
assertResult(" -" + cs + "123.45", stat,
"SELECT TO_CHAR(-123.45, 'L999.99') FROM DUAL");
assertResult(cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'FML999.99') FROM DUAL");
assertResult(" " + cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'U999.99') FROM DUAL");
assertResult(" " + cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'u999.99') FROM DUAL");
}
assertResult(" 12,345.35", stat, assertResult(" 12,345.35", stat,
"SELECT TO_CHAR(12345.345, '99,999,999.99') FROM DUAL"); "SELECT TO_CHAR(12345.345, '99,999,999.99') FROM DUAL");
assertResult("12,345.35", stat, assertResult("12,345.35", stat,
...@@ -1827,16 +1838,6 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -1827,16 +1838,6 @@ public class TestFunctions extends TestBase implements AggregateFunction {
"SELECT TO_CHAR(123.45, 'C999g999') FROM DUAL"); "SELECT TO_CHAR(123.45, 'C999g999') FROM DUAL");
assertResult(cc + "123.45", stat, assertResult(cc + "123.45", stat,
"SELECT TO_CHAR(123.45, 'FMC999,999.99') FROM DUAL"); "SELECT TO_CHAR(123.45, 'FMC999,999.99') FROM DUAL");
assertResult(" " + cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'L999.99') FROM DUAL");
assertResult(" -" + cs + "123.45", stat,
"SELECT TO_CHAR(-123.45, 'L999.99') FROM DUAL");
assertResult(cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'FML999.99') FROM DUAL");
assertResult(" " + cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'U999.99') FROM DUAL");
assertResult(" " + cs + "123.45", stat,
"SELECT TO_CHAR(123.45, 'u999.99') FROM DUAL");
expected = String.format("%.2f", 0.33f).substring(1); expected = String.format("%.2f", 0.33f).substring(1);
assertResult(" " + expected, stat, assertResult(" " + expected, stat,
"SELECT TO_CHAR(0.326, '99D99') FROM DUAL"); "SELECT TO_CHAR(0.326, '99D99') FROM DUAL");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论