### Eclipse Workspace Patch 1.0
#P h2
Index: src/main/org/h2/res/_messages_en.prop
===================================================================
--- src/main/org/h2/res/_messages_en.prop	(revision 4033)
+++ src/main/org/h2/res/_messages_en.prop	(working copy)
@@ -19,6 +19,7 @@
 40001=Deadlock detected. The current transaction was rolled back. Details: {0}
 42000=Syntax error in SQL statement {0}
 42001=Syntax error in SQL statement {0}; expected {1}
+42123=same columns already indexed on {0}
 42S01=Table {0} already exists
 42S02=Table {0} not found
 42S11=Index {0} already exists
Index: src/main/org/h2/command/ddl/CreateIndex.java
===================================================================
--- src/main/org/h2/command/ddl/CreateIndex.java	(revision 3910)
+++ src/main/org/h2/command/ddl/CreateIndex.java	(working copy)
@@ -1,8 +1,7 @@
 /*
- * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
- * Version 1.0, and under the Eclipse Public License, Version 1.0
- * (http://h2database.com/html/license.html).
- * Initial Developer: H2 Group
+ * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
+ * 1.0, and under the Eclipse Public License, Version 1.0
+ * (http://h2database.com/html/license.html). Initial Developer: H2 Group
  */
 package org.h2.command.ddl;
 
@@ -12,15 +11,16 @@
 import org.h2.engine.Database;
 import org.h2.engine.Right;
 import org.h2.engine.Session;
+import org.h2.index.Index;
 import org.h2.index.IndexType;
+import org.h2.index.PageDataIndex;
 import org.h2.message.DbException;
 import org.h2.schema.Schema;
 import org.h2.table.IndexColumn;
 import org.h2.table.Table;
 
 /**
- * This class represents the statement
- * CREATE INDEX
+ * This class represents the statement CREATE INDEX
  */
 public class CreateIndex extends SchemaCommand {
 
@@ -77,6 +77,7 @@
             }
             throw DbException.get(ErrorCode.INDEX_ALREADY_EXISTS_1, indexName);
         }
+
         IndexType indexType;
         if (primaryKey) {
             if (table.findPrimaryKey() != null) {
@@ -88,11 +89,57 @@
         } else {
             indexType = IndexType.createNonUnique(persistent, hash);
         }
+        if (!db.isStarting() && db.getMode().createIndexCheckStrictly) {
+            if (table.getIndexes().size() > 1) {
+                for (Index checkTarget : table.getIndexes()) {
+                    if (!(checkTarget instanceof PageDataIndex)) {
+                        checkDefinition(indexType, checkTarget);
+                    }
+                }
+            }
+        }
         IndexColumn.mapColumns(indexColumns, table);
         table.addIndex(session, indexName, id, indexColumns, indexType, create, comment);
         return 0;
     }
 
+    protected void checkDefinition(IndexType creatingType, Index existing) {
+        IndexColumn[] creatingColumns = this.indexColumns;
+        IndexColumn[] existingColumns = existing.getIndexColumns();
+        if (existingColumns == null || creatingColumns == null) {
+            return;
+        }
+        if (existingColumns.length != creatingColumns.length) {
+            return;
+        }
+        for (int i = 0; i < creatingColumns.length; i++) {
+            IndexColumn creatingColumn = creatingColumns[i];
+            IndexColumn existingColumn = existingColumns[i];
+            if (!columnEquals(creatingColumn, existingColumn)) {
+                return;
+            }
+        }
+        IndexType existingType = existing.getIndexType();
+        if (session.getDatabase().getMode().allowOverrideNonUniqueIndex
+                && (creatingType.isUnique() && !existingType.isUnique())) {
+            return;
+        }
+        throw DbException.get(ErrorCode.COLUMNS_ALREADY_INDEXED_1);
+    }
+
+    protected boolean columnEquals(IndexColumn a, IndexColumn b) {
+        String aName = a.column != null ? a.column.getName() : a.columnName;
+        String bName = b.column != null ? b.column.getName() : b.columnName;
+        if (aName.equals(bName)) {
+            if (session.getDatabase().getMode().allowOverloadDifferentSortType) {
+                return a.sortType == b.sortType;
+            } else {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public void setPrimaryKey(boolean b) {
         this.primaryKey = b;
     }
Index: src/main/org/h2/constant/ErrorCode.java
===================================================================
--- src/main/org/h2/constant/ErrorCode.java	(revision 3788)
+++ src/main/org/h2/constant/ErrorCode.java	(working copy)
@@ -342,6 +342,8 @@
      */
     public static final int COLUMN_NOT_FOUND_1 = 42122;
 
+    public static final int COLUMNS_ALREADY_INDEXED_1 = 42123;
+
     // 0A: feature not supported
 
     // HZ: remote database access
Index: src/test/org/h2/test/db/TestCompatibility.java
===================================================================
--- src/test/org/h2/test/db/TestCompatibility.java	(revision 4033)
+++ src/test/org/h2/test/db/TestCompatibility.java	(working copy)
@@ -1,8 +1,7 @@
 /*
- * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
- * Version 1.0, and under the Eclipse Public License, Version 1.0
- * (http://h2database.com/html/license.html).
- * Initial Developer: H2 Group
+ * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, Version
+ * 1.0, and under the Eclipse Public License, Version 1.0
+ * (http://h2database.com/html/license.html). Initial Developer: H2 Group
  */
 package org.h2.test.db;
 
@@ -48,7 +47,9 @@
         testDB2();
         testDerby();
         testPlusSignAsConcatOperator();
-
+        testCreateIndexCheckStrictlyOracle();
+        testCreateIndexCheckStrictlyDB2();
+        testCreateIndexCheckStrictlyDerby();
         conn.close();
         deleteDb("compatibility");
     }
@@ -65,10 +66,9 @@
         Connection c = getConnection("compatibility;DATABASE_TO_UPPER=FALSE");
         Statement stat = c.createStatement();
         stat.execute("create table test(id int primary key, name varchar) as select 1, 'hello'");
-        assertThrows(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, stat).
-            execute("create table test(id int primary key, name varchar)");
-        assertThrows(ErrorCode.DUPLICATE_COLUMN_NAME_1, stat).
-            execute("alter table test add column Name varchar");
+        assertThrows(ErrorCode.TABLE_OR_VIEW_ALREADY_EXISTS_1, stat).execute(
+                "create table test(id int primary key, name varchar)");
+        assertThrows(ErrorCode.DUPLICATE_COLUMN_NAME_1, stat).execute("alter table test add column Name varchar");
         ResultSet rs;
 
         DatabaseMetaData meta = c.getMetaData();
@@ -109,8 +109,7 @@
         }
         Statement stat = conn.createStatement();
         stat.execute("create table test(id int primary key) as select 1");
-        assertThrows(ErrorCode.USER_DATA_TYPE_ALREADY_EXISTS_1, stat).
-                execute("create domain int as varchar");
+        assertThrows(ErrorCode.USER_DATA_TYPE_ALREADY_EXISTS_1, stat).execute("create domain int as varchar");
         conn.close();
         conn = getConnection("compatibility");
         stat = conn.createStatement();
@@ -165,16 +164,177 @@
         stat.execute("create table t2(c1 int, c2 int)");
         stat.execute("create unique index i2 on t2(c1, c2)");
         stat.execute("insert into t2 values (null, 1)");
-        assertThrows(ErrorCode.DUPLICATE_KEY_1, stat).
-                execute("insert into t2 values (null, 1)");
+        assertThrows(ErrorCode.DUPLICATE_KEY_1, stat).execute("insert into t2 values (null, 1)");
         stat.execute("insert into t2 values (null, null)");
         stat.execute("insert into t2 values (null, null)");
         stat.execute("insert into t2 values (1, null)");
-        assertThrows(ErrorCode.DUPLICATE_KEY_1, stat).
-                execute("insert into t2 values (1, null)");
+        assertThrows(ErrorCode.DUPLICATE_KEY_1, stat).execute("insert into t2 values (1, null)");
         stat.execute("DROP TABLE T2");
     }
 
+    private void testCreateIndexCheckStrictlyOracle() throws SQLException {
+        Statement stat = conn.createStatement();
+        stat.execute("SET MODE ORACLE");
+        stat.execute("drop table if exists test");
+        stat.execute("create table test(id int not null primary key, id2 int)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE1 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE2_1 on test(id asc)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE2_2 on test(id asc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE3_1 on test(id)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create unique index CASE3_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create unique index CASE4_1 on test(id)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE4_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create unique index CASE44_1 on test(id)");
+        stat.execute("create unique index CASE44_2 on test(id desc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE5_1 on test(id)");
+        stat.execute("create index CASE5_2 on test(id desc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE6_1 on test(id desc)");
+        stat.execute("create index CASE6_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE7_1 on test(id,id2)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE7_2 on test(id,id2)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE8_1 on test(id asc,id2 desc)");
+        stat.execute("create index CASE8_2 on test(id desc,id2 asc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE9_1 on test(id,id2)");
+        stat.execute("create index CASE9_2 on test(id2,id)");
+        stat.execute("DROP TABLE TEST");
+    }
+
+    private void testCreateIndexCheckStrictlyDB2() throws SQLException {
+        Statement stat = conn.createStatement();
+        stat.execute("SET MODE DB2");
+        stat.execute("drop table if exists test");
+        stat.execute("create table test(id int not null primary key, id2 int)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE1 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE2_1 on test(id asc)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE2_2 on test(id asc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE3_1 on test(id)");
+        stat.execute("create unique index CASE3_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create unique index CASE4_1 on test(id)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE4_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create unique index CASE44_1 on test(id)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create unique index CASE44_2 on test(id desc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE5_1 on test(id)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE5_2 on test(id desc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE6_1 on test(id desc)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE6_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE7_1 on test(id,id2)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE7_2 on test(id,id2)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE8_1 on test(id asc,id2 desc)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE8_2 on test(id desc,id2 asc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE9_1 on test(id,id2)");
+        stat.execute("create index CASE9_2 on test(id2,id)");
+        stat.execute("DROP TABLE TEST");
+    }
+
+
+    private void testCreateIndexCheckStrictlyDerby() throws SQLException {
+        Statement stat = conn.createStatement();
+        stat.execute("SET MODE Derby");
+        stat.execute("drop table if exists test");
+        stat.execute("create table test(id int not null primary key, id2 int)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE1 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE2_1 on test(id asc)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE2_2 on test(id asc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE3_1 on test(id)");
+        stat.execute("create unique index CASE3_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create unique index CASE4_1 on test(id)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE4_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create unique index CASE44_1 on test(id)");
+        stat.execute("create unique index CASE44_2 on test(id desc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE5_1 on test(id)");
+        stat.execute("create index CASE5_2 on test(id desc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int)");
+        stat.execute("create index CASE6_1 on test(id desc)");
+        stat.execute("create index CASE6_2 on test(id)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE7_1 on test(id,id2)");
+        assertThrows(ErrorCode.COLUMNS_ALREADY_INDEXED_1, stat).execute("create index CASE7_2 on test(id,id2)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE8_1 on test(id asc,id2 desc)");
+        stat.execute("create index CASE8_2 on test(id desc,id2 asc)");
+        stat.execute("DROP TABLE TEST");
+
+        stat.execute("create table test(id int, id2 int, id3 int)");
+        stat.execute("create index CASE9_1 on test(id,id2)");
+        stat.execute("create index CASE9_2 on test(id2,id)");
+        stat.execute("DROP TABLE TEST");
+    }
+
     private void testHsqlDb() throws SQLException {
         Statement stat = conn.createStatement();
         stat.execute("DROP TABLE TEST IF EXISTS; CREATE TABLE TEST(ID INT PRIMARY KEY); ");
@@ -195,6 +355,7 @@
     }
 
     private void testMySQL() throws SQLException {
+        System.getProperties().list(System.out);
         Statement stat = conn.createStatement();
         stat.execute("SELECT 1");
         stat.execute("DROP TABLE IF EXISTS TEST");
@@ -259,7 +420,8 @@
         prep.executeQuery();
         prep.close();
 
-        prep = conn.prepareStatement("SELECT full_name FROM test WHERE (SUBSTRING(name, 1, 1) + SUBSTRING(surname, 2, 3)) = ?");
+        prep = conn
+                .prepareStatement("SELECT full_name FROM test WHERE (SUBSTRING(name, 1, 1) + SUBSTRING(surname, 2, 3)) = ?");
         prep.setString(1, "Joe");
         ResultSet res = prep.executeQuery();
         assertTrue("Result cannot be empty", res.next());
@@ -276,12 +438,12 @@
         assertEquals("1", res.getString(1));
         conn.close();
         conn = getConnection("compatibility;MODE=MySQL");
-        assertThrows(ErrorCode.SCHEMA_NOT_FOUND_1, conn.createStatement()).
-                executeQuery("SELECT 1 FROM sysibm.sysdummy1");
+        assertThrows(ErrorCode.SCHEMA_NOT_FOUND_1, conn.createStatement()).executeQuery(
+                "SELECT 1 FROM sysibm.sysdummy1");
         conn.close();
         conn = getConnection("compatibility;MODE=DB2");
         Statement stmt = conn.createStatement();
-        stmt.execute("drop table test");
+        stmt.execute("drop table if exists test");
         stmt.execute("create table test(id varchar)");
         stmt.execute("insert into test values ('3'),('1'),('2')");
         res = stmt.executeQuery("select id from test order by id fetch next 2 rows only");
@@ -300,8 +462,8 @@
         assertEquals("1", res.getString(1));
         conn.close();
         conn = getConnection("compatibility;MODE=PostgreSQL");
-        assertThrows(ErrorCode.SCHEMA_NOT_FOUND_1, conn.createStatement()).
-                executeQuery("SELECT 1 FROM sysibm.sysdummy1");
+        assertThrows(ErrorCode.SCHEMA_NOT_FOUND_1, conn.createStatement()).executeQuery(
+                "SELECT 1 FROM sysibm.sysdummy1");
         conn.close();
         conn = getConnection("compatibility");
     }
Index: src/main/org/h2/engine/Mode.java
===================================================================
--- src/main/org/h2/engine/Mode.java	(revision 4033)
+++ src/main/org/h2/engine/Mode.java	(working copy)
@@ -57,6 +57,15 @@
     public boolean indexDefinitionInCreateTable;
 
     /**
+     * When creating index, check already exists indexes that indexed columns.
+     */
+    public boolean createIndexCheckStrictly;
+    
+    public boolean allowOverrideNonUniqueIndex;
+   
+    public boolean allowOverloadDifferentSortType;
+    
+    /**
      * Meta data calls return identifiers in lower case.
      */
     public boolean lowerCaseIdentifiers;
@@ -125,6 +134,8 @@
         mode.aliasColumnName = true;
         mode.supportOffsetFetch = true;
         mode.sysDummy1 = true;
+        mode.createIndexCheckStrictly = true;
+        mode.allowOverrideNonUniqueIndex = true;
         add(mode);
 
         mode = new Mode("Derby");
@@ -132,6 +143,9 @@
         mode.uniqueIndexSingleNull = true;
         mode.supportOffsetFetch = true;
         mode.sysDummy1 = true;
+        mode.createIndexCheckStrictly = true;
+        mode.allowOverloadDifferentSortType = true;
+        mode.allowOverrideNonUniqueIndex = true;
         add(mode);
 
         mode = new Mode("HSQLDB");
@@ -159,6 +173,8 @@
         mode = new Mode("Oracle");
         mode.aliasColumnName = true;
         mode.uniqueIndexSingleNullExceptAllColumnsAreNull = true;
+        mode.createIndexCheckStrictly = true;
+        mode.allowOverloadDifferentSortType = true;
         add(mode);
 
         mode = new Mode("PostgreSQL");
