This is an automated email from the ASF dual-hosted git repository.

doebele pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/empire-db.git


The following commit(s) were added to refs/heads/master by this push:
     new 5de5bfb  EMPIREDB-303 Add support for Unique-Indexes which allow null 
values Implementation provided for SQL Server only.
5de5bfb is described below

commit 5de5bfb2b15822e54342f8b790badf73f866f061
Author: Rainer Döbele <[email protected]>
AuthorDate: Tue Sep 10 14:20:16 2019 +0200

    EMPIREDB-303
    Add support for Unique-Indexes which allow null values
    Implementation provided for SQL Server only.
---
 .../java/org/apache/empire/db/DBDDLGenerator.java  |  5 +--
 .../org/apache/empire/db/DBExpressionIndex.java    | 16 ++++-----
 .../main/java/org/apache/empire/db/DBIndex.java    | 40 ++++++++++++----------
 .../main/java/org/apache/empire/db/DBTable.java    | 22 +++++++++---
 .../src/main/java/org/apache/empire/db/DBView.java |  3 +-
 .../empire/db/sqlserver/MSSqlDDLGenerator.java     | 27 +++++++++++++++
 6 files changed, 78 insertions(+), 35 deletions(-)

diff --git a/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java 
b/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java
index c30d241..51d9b69 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBDDLGenerator.java
@@ -20,6 +20,7 @@ package org.apache.empire.db;
 
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBIndex.DBIndexType;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.MiscellaneousErrorException;
 import org.apache.empire.exceptions.NotImplementedException;
@@ -401,7 +402,7 @@ public abstract class DBDDLGenerator<T extends 
DBDatabaseDriver>
         // Create other Indexes (except primary key)
         for (DBIndex idx : t.getIndexes())
         {
-            if (idx == pk || idx.getType() == DBIndex.PRIMARYKEY)
+            if (idx == pk || idx.getType() == DBIndexType.PRIMARY_KEY)
                 continue;
 
             // Create Index
@@ -420,7 +421,7 @@ public abstract class DBDDLGenerator<T extends 
DBDatabaseDriver>
         StringBuilder sql = new StringBuilder();
 
         // Create Index
-        sql.append((idx.getType() == DBIndex.UNIQUE) ? "CREATE UNIQUE INDEX " 
: "CREATE INDEX ");
+        sql.append((idx.getType().isUnique()) ? "CREATE UNIQUE INDEX " : 
"CREATE INDEX ");
         appendElementName(sql, idx.getName());
         sql.append(" ON ");
         t.addSQL(sql, DBExpr.CTX_FULLNAME);
diff --git 
a/empire-db/src/main/java/org/apache/empire/db/DBExpressionIndex.java 
b/empire-db/src/main/java/org/apache/empire/db/DBExpressionIndex.java
index 81721d4..99870eb 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBExpressionIndex.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBExpressionIndex.java
@@ -30,7 +30,7 @@ public class DBExpressionIndex extends DBIndex
     private final static long serialVersionUID = 1L;
     
     private DBExpr[] columnExpressions;
-
+    
     /**
      * Constructs a DBExpresionIndex
      * 
@@ -38,9 +38,9 @@ public class DBExpressionIndex extends DBIndex
      * @param unique true if the index has only unique values or false 
otherwise
      * @param columnExpressions an array of one or more column expressions of 
the index
      */
-    public DBExpressionIndex(String name, boolean unique, DBExpr... 
columnExpressions)
+    public DBExpressionIndex(String name, DBIndexType type, DBExpr... 
columnExpressions)
     {
-        super(name, (unique ? UNIQUE : STANDARD), null);
+        super(name, type, null);
         // columnExpressions
         if (columnExpressions==null || columnExpressions.length==0)
             throw new InvalidArgumentException("columnExpressions", 
columnExpressions);
@@ -50,15 +50,13 @@ public class DBExpressionIndex extends DBIndex
 
     /**
      * Constructs a DBExpresionIndex
-     * 
-     * @param name the index name
-     * @param unique true if the index has only unique values or false 
otherwise
-     * @param expr an column expressions that defines the key values for the 
index
+     * Overload for convenience
      */
-    public DBExpressionIndex(String name, boolean unique, DBColumnExpr expr)
+    public DBExpressionIndex(String name, boolean unique, DBExpr... 
columnExpressions)
     {
-        this(name, unique, new DBColumnExpr[] { expr });
+        this(name, (unique ? DBIndexType.UNIQUE : DBIndexType.STANDARD), 
columnExpressions);
     }
+
     
     @Override
     public DBDatabase getDatabase()
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBIndex.java 
b/empire-db/src/main/java/org/apache/empire/db/DBIndex.java
index be6a6d9..de8b910 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBIndex.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBIndex.java
@@ -29,24 +29,28 @@ public class DBIndex extends DBObject
 {
     private final static long serialVersionUID = 1L;
   
-    // Index Types
-    /**
-     * SQL Standard index
-     */
-    public static final int STANDARD   = 0;
-    
-    /**
-     * SQL Unique index
-     */
-    public static final int UNIQUE     = 1;
-    
-    /**
-     * SQL Primary key index
-     */
-    public static final int PRIMARYKEY = 2;
+    public enum DBIndexType
+    {
+        STANDARD(false),
+        UNIQUE(true),
+        UNIQUE_ALLOW_NULL(true),
+        PRIMARY_KEY(true);
+        
+        private final boolean unique;
+        
+        DBIndexType(boolean unique)
+        {
+            this.unique = unique;
+        }
+
+        public boolean isUnique()
+        {
+            return unique;
+        }
+    }
 
     private String          name;
-    private int             type;
+    private DBIndexType     type;
     private DBColumn[]      columns;
     private DBTable         table;
 
@@ -57,7 +61,7 @@ public class DBIndex extends DBObject
      * @param type the primary key type (only PRIMARYKEY)
      * @param columns an array of one or more columns of the primary key
      */
-    public DBIndex(String name, int type, DBColumn[] columns)
+    public DBIndex(String name, DBIndexType type, DBColumn[] columns)
     {
         this.name = name;
         this.type = type;
@@ -154,7 +158,7 @@ public class DBIndex extends DBObject
      * 
      * @return the type of this index ({@link #PRIMARYKEY}, {@link #UNIQUE}, 
{@link #STANDARD}) 
      */
-    public int getType()
+    public DBIndexType getType()
     {
         return type;
     }
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBTable.java 
b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
index aab8283..45f5962 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBTable.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBTable.java
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.empire.commons.Options;
 import org.apache.empire.data.DataMode;
 import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBIndex.DBIndexType;
 import org.apache.empire.db.DBRelation.DBCascadeAction;
 import org.apache.empire.db.exceptions.NoPrimaryKeyException;
 import org.apache.empire.db.exceptions.RecordDeleteFailedException;
@@ -430,7 +431,7 @@ public class DBTable extends DBRowSet implements Cloneable
         // Set primary Key now
         if (columns.length>0)
         {   // create primary key
-            primaryKey = new DBIndex(name + "_PK", DBIndex.PRIMARYKEY, 
columns);
+            primaryKey = new DBIndex(name + "_PK", DBIndexType.PRIMARY_KEY, 
columns);
             addIndex(primaryKey);
         }
         else
@@ -472,15 +473,26 @@ public class DBTable extends DBRowSet implements Cloneable
      * 
      * @return the Index object
      */
-    public final DBIndex addIndex(String name, boolean unique, DBColumn... 
columns)
+    public final DBIndex addIndex(String name, DBIndexType type, DBColumn... 
columns)
     {
         if (name==null || columns==null || columns.length==0)
             throw new InvalidArgumentException("name|columns", null);
+        if (type==DBIndexType.PRIMARY_KEY && this.primaryKey!=null)
+            throw new InvalidArgumentException("type", 
DBIndexType.PRIMARY_KEY.name());
         // add Index now
-        DBIndex index = new DBIndex(name, (unique) ? DBIndex.UNIQUE : 
DBIndex.STANDARD, columns);
+        DBIndex index = new DBIndex(name, type, columns);
         addIndex(index);
         return index;
     }
+    
+    /**
+     * Adds an index.
+     * Overload for convenience
+     */
+    public final DBIndex addIndex(String name, boolean unique, DBColumn... 
columns)
+    {
+        return addIndex(name, (unique) ? DBIndexType.UNIQUE : 
DBIndexType.STANDARD, columns);
+    }
 
     /**
      * removes an index.
@@ -572,12 +584,12 @@ public class DBTable extends DBRowSet implements Cloneable
     {
         for (DBIndex idx : getIndexes())
         {
-            if (idx.getType()==DBIndex.PRIMARYKEY)
+            if (idx.getType()==DBIndexType.PRIMARY_KEY)
             {   // Only for new records
                 if (!rec.isNew())
                     continue; // not new
             }
-            else if (idx.getType()==DBIndex.UNIQUE)
+            else if (idx.getType().isUnique())
             {   // check if any of the fields were actually changed
                 if (!rec.isNew() && !rec.wasAnyModified(idx.getColumns()))
                     continue; // not modified
diff --git a/empire-db/src/main/java/org/apache/empire/db/DBView.java 
b/empire-db/src/main/java/org/apache/empire/db/DBView.java
index 76775bf..49f3275 100644
--- a/empire-db/src/main/java/org/apache/empire/db/DBView.java
+++ b/empire-db/src/main/java/org/apache/empire/db/DBView.java
@@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.empire.commons.Options;
 import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBIndex.DBIndexType;
 import org.apache.empire.db.expr.column.DBValueExpr;
 import org.apache.empire.exceptions.InvalidArgumentException;
 import org.apache.empire.exceptions.ItemExistsException;
@@ -219,7 +220,7 @@ public abstract class DBView extends DBRowSet
     protected void setKeyColumns(DBViewColumn... keyColumns)
     { // Set Key Columns
         if (keyColumns != null)
-            primaryKey = new DBIndex(null, DBIndex.PRIMARYKEY, keyColumns);
+            primaryKey = new DBIndex(null, DBIndexType.PRIMARY_KEY, 
keyColumns);
     }
 
     /**
diff --git 
a/empire-db/src/main/java/org/apache/empire/db/sqlserver/MSSqlDDLGenerator.java 
b/empire-db/src/main/java/org/apache/empire/db/sqlserver/MSSqlDDLGenerator.java
index 222a274..7109d59 100644
--- 
a/empire-db/src/main/java/org/apache/empire/db/sqlserver/MSSqlDDLGenerator.java
+++ 
b/empire-db/src/main/java/org/apache/empire/db/sqlserver/MSSqlDDLGenerator.java
@@ -22,9 +22,13 @@ import org.apache.empire.commons.ObjectUtils;
 import org.apache.empire.commons.StringUtils;
 import org.apache.empire.data.Column;
 import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBColumn;
 import org.apache.empire.db.DBDDLGenerator;
 import org.apache.empire.db.DBDatabase;
 import org.apache.empire.db.DBDatabaseDriver.DBSeqTable;
+import org.apache.empire.db.DBExpr;
+import org.apache.empire.db.DBIndex;
+import org.apache.empire.db.DBIndex.DBIndexType;
 import org.apache.empire.db.DBSQLScript;
 import org.apache.empire.db.DBTableColumn;
 
@@ -125,4 +129,27 @@ public class MSSqlDDLGenerator extends 
DBDDLGenerator<DBDatabaseDriverMSSQL>
         super.createDatabase(db, script);
     }
     
+    @Override
+    protected void addCreateIndexStmt(DBIndex index, StringBuilder sql, 
DBSQLScript script)
+    {
+        // Check type
+        if (index.getType()==DBIndexType.UNIQUE_ALLOW_NULL)
+        {   // Add WHERE constraint for ALLOW_NULL
+            boolean first = true;
+            for (DBColumn col : index.getColumns())
+            {
+                // Check whether columns is nullable
+                if (col.isRequired())
+                    continue;
+                // append
+                sql.append((first) ? " WHERE " : " AND ");
+                col.addSQL(sql, DBExpr.CTX_NAME);
+                sql.append(" IS NOT NULL");
+                first = false;
+            }
+        }
+        // done
+        super.addCreateIndexStmt(index, sql, script);
+    }
+    
 }

Reply via email to