You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@empire-db.apache.org by fr...@apache.org on 2009/02/08 15:11:25 UTC

svn commit: r742097 - in /incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db: derby/ h2/ postgresql/

Author: francisdb
Date: Sun Feb  8 14:11:24 2009
New Revision: 742097

URL: http://svn.apache.org/viewvc?rev=742097&view=rev
Log:
three new database drivers
not 100% tested but they all run the demo app (except for the reverse function not being available on some drivers)

Added:
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/DBDatabaseDriverDerby.java
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/package.html
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/DBDatabaseDriverH2.java
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/package.html
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/DBDatabaseDriverPostgreSQL.java
    incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/package.html

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/DBDatabaseDriverDerby.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/DBDatabaseDriverDerby.java?rev=742097&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/DBDatabaseDriverDerby.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/DBDatabaseDriverDerby.java Sun Feb  8 14:11:24 2009
@@ -0,0 +1,733 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.db.derby;
+
+import java.sql.Connection;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBCmdType;
+import org.apache.empire.db.DBColumn;
+import org.apache.empire.db.DBCommand;
+import org.apache.empire.db.DBCommandExpr;
+import org.apache.empire.db.DBDatabase;
+import org.apache.empire.db.DBDatabaseDriver;
+import org.apache.empire.db.DBDriverFeature;
+import org.apache.empire.db.DBExpr;
+import org.apache.empire.db.DBIndex;
+import org.apache.empire.db.DBObject;
+import org.apache.empire.db.DBRelation;
+import org.apache.empire.db.DBSQLScript;
+import org.apache.empire.db.DBTable;
+import org.apache.empire.db.DBTableColumn;
+import org.apache.empire.db.DBView;
+import org.apache.empire.db.oracle.DBDatabaseDriverOracle.BooleanType;
+
+
+/**
+ * This class provides support for the Derby database system.
+ * 
+ *
+ */
+public class DBDatabaseDriverDerby extends DBDatabaseDriver
+{
+	
+	private BooleanType booleanType = BooleanType.NUMBER;
+    /**
+     * Defines the Derby command type.
+     */ 
+    public static class DBCommandDerby extends DBCommand
+    {
+        public DBCommandDerby(DBDatabase db)
+        {
+            super(db);
+        }
+    }
+    
+    // Properties
+    private String databaseName = null;
+    // Sequence treatment
+    // When set to 'false' (default) Derby's autoincrement feature is used.
+    private boolean useSequenceTable = false;
+    private String sequenceTableName = "Sequences";
+    
+    /**
+     * Constructor for the Derby database driver.<br>
+     */
+    public DBDatabaseDriverDerby()
+    {
+        // Default Constructor
+    }
+
+    /**
+     * returns the name for the database / schema
+     * @return the database / schema name
+     */
+    public String getDatabaseName()
+    {
+        return databaseName;
+    }
+
+    /**
+     * Sets the name for the database / schema<br>
+     * This names is required for creating a database.<br>
+     * When a name is set, the driver will automatically execute 'USE dbname' when the database is opened.
+     * @param databaseName the name of the database
+     */
+    public void setDatabaseName(String databaseName)
+    {
+        this.databaseName = databaseName;
+    }
+
+    /**
+     * returns whether a sequence table is used for record identiy management.<br>
+     * Default is false. In this case the AutoIncrement feature of Derby is used.
+     * @return true if a sequence table is used instead of identity columns.
+     */
+    public boolean isUseSequenceTable()
+    {
+        return useSequenceTable;
+    }
+
+    /**
+     * If set to true a special table is used for sequence number generation.<br>
+     * Otherwise the AutoIncrement feature of Derby is used identiy fields. 
+     * @param useSequenceTable true to use a sequence table or false otherwise.
+     */
+    public void setUseSequenceTable(boolean useSequenceTable)
+    {
+        this.useSequenceTable = useSequenceTable;
+    }
+
+    /**
+     * returns the name of the sequence table
+     * @return the name of the table used for sequence number generation
+     */
+    public String getSequenceTableName()
+    {
+        return sequenceTableName;
+    }
+
+    /**
+     * Sets the name of the sequence table.
+     * Only applicable if useSequenceTable is set to true.
+     * @param sequenceTableName the name of the table used for sequence number generation
+     */
+    public void setSequenceTableName(String sequenceTableName)
+    {
+        this.sequenceTableName = sequenceTableName;
+    }
+
+    /**
+     * Creates a new Derby command object.
+     * 
+     * @return the new DBCommandDerby object
+     */
+    @Override
+    public DBCommand createCommand(DBDatabase db)
+    {
+        if (db == null)
+            return null;
+        // create command object
+        return new DBCommandDerby(db);
+    }
+
+    /**
+     * Returns whether or not a particular feature is supported by this driver
+     * @param type type of requrested feature. @see DBDriverFeature
+     * @return true if the features is supported or false otherwise
+     */
+    @Override
+    public boolean isSupported(DBDriverFeature type)
+    {
+        switch (type)
+        {   // return support info 
+            case CREATE_SCHEMA: return true;
+            case SEQUENCES:     return useSequenceTable;    
+        }
+        return false;
+    }
+    
+    /**
+     * Gets an sql phrase template for this database system.<br>
+     * @see DBDatabaseDriver#getSQLPhrase(int)
+     * @return the phrase template
+     */
+    @Override
+    public String getSQLPhrase(int phrase)
+    {
+        switch (phrase)
+        {
+            // sql-phrases
+            case SQL_NULL_VALUE:              return "null";
+            case SQL_PARAMETER:               return " ? ";
+            case SQL_RENAME_TABLE:            return " ";
+            case SQL_RENAME_COLUMN:           return " AS ";
+            case SQL_DATABASE_LINK:           return "@";
+            case SQL_QUOTES_OPEN:             return "\"";
+            case SQL_QUOTES_CLOSE:            return "\"";
+            case SQL_CONCAT_EXPR:             return "? || {0}";
+            // data types
+            case SQL_BOOLEAN_TRUE:            return "1";
+            case SQL_BOOLEAN_FALSE:           return "0";
+            case SQL_CURRENT_DATE:            return "CURRENT_DATE()";
+            case SQL_DATE_PATTERN:            return "yyyy-MM-dd";
+            case SQL_DATE_TEMPLATE:           return "'{0}'";
+            case SQL_CURRENT_DATETIME:        return "NOW()";
+            case SQL_DATETIME_PATTERN:        return "yyyy-MM-dd HH:mm:ss";
+            case SQL_DATETIME_TEMPLATE:       return "'{0}'";
+            // functions
+            case SQL_FUNC_COALESCE:           return "coalesce(?, {0})";
+            case SQL_FUNC_SUBSTRING:          return "substr(?, {0})";
+            case SQL_FUNC_SUBSTRINGEX:        return "substr(?, {0}, {1})";
+            case SQL_FUNC_REPLACE:            return "replace(?, {0}, {1})";
+            case SQL_FUNC_REVERSE:            return "reverse_not_available_in_derby(?)"; 
+            case SQL_FUNC_STRINDEX:           return "locate({0}, ?)"; 
+            case SQL_FUNC_STRINDEXFROM:       return "locate({0}, ?, {1})"; 
+            case SQL_FUNC_LENGTH:             return "length(?)";
+            case SQL_FUNC_UPPER:              return "upper(?)";
+            case SQL_FUNC_LOWER:              return "lower(?)";
+            case SQL_FUNC_TRIM:               return "trim(?)";
+            case SQL_FUNC_LTRIM:              return "ltrim(?)";
+            case SQL_FUNC_RTRIM:              return "rtrim(?)";
+            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            // Numeric
+            case SQL_FUNC_ABS:                return "abs(?)";
+            case SQL_FUNC_ROUND:              return "round(?,{0})";
+            case SQL_FUNC_TRUNC:              return "truncate(?,{0})";
+            case SQL_FUNC_CEILING:            return "ceiling(?)";
+            case SQL_FUNC_FLOOR:              return "floor(?)";
+            // Date
+            case SQL_FUNC_DAY:                return "day(?)";
+            case SQL_FUNC_MONTH:              return "month(?)";
+            case SQL_FUNC_YEAR:               return "year(?)";
+            // Aggregation
+            case SQL_FUNC_SUM:                return "sum(?)";
+            case SQL_FUNC_MAX:                return "max(?)";
+            case SQL_FUNC_MIN:                return "min(?)";
+            case SQL_FUNC_AVG:                return "avg(?)";
+            // Others
+            case SQL_FUNC_DECODE:             return "case ? {0} end";
+            case SQL_FUNC_DECODE_SEP:         return " ";
+            case SQL_FUNC_DECODE_PART:        return "when {0} then {1}";
+            case SQL_FUNC_DECODE_ELSE:        return "else {0}";
+            // Not defined
+            default:
+                log.error("SQL phrase " + String.valueOf(phrase) + " is not defined!");
+                return "?";
+        }
+    }
+
+    /**
+     * @see DBDatabaseDriver#getConvertPhrase(DataType, DataType, Object)
+     */
+    @Override
+    public String getConvertPhrase(DataType destType, DataType srcType, Object format)
+    {
+        switch(destType)
+        {
+           case BOOL:      return "CAST(? AS UNSIGNED)";
+           case INTEGER:   return "CAST(? AS SIGNED)";
+           case DECIMAL:   return "CAST(? AS DECIMAL)";
+           case DOUBLE:    return "CAST(? AS DECIMAL)";
+           case DATE:      return "CAST(? AS DATE)";
+           case DATETIME:  return "CAST(? AS DATETIME)";
+           // Convert to text
+           case TEXT:
+                return "CAST(? AS CHAR)";
+           case BLOB:
+                return "CAST(? AS BLOB)";
+           // Unknown Type                                       
+           default:
+                log.error("getConvertPhrase: unknown type (" + String.valueOf(destType));
+                return "?";
+        }
+    }
+    
+    /**
+     * @see DBDatabaseDriver#getNextSequenceValue(DBDatabase, String, int, Connection)
+     */
+    @Override
+    public Object getNextSequenceValue(DBDatabase db, String seqName, int minValue, Connection conn)
+    {   //Use Oracle Sequences
+        if (useSequenceTable)
+        {   // Use a sequence Table to generate Sequences
+            DBTable t = db.getTable(sequenceTableName);
+            return ((DBSeqTable)t).getNextValue(seqName, minValue, conn);
+        }
+        else
+        {   // Post Detection
+            return null;
+        }
+    }
+
+    /**
+     * @see DBDatabaseDriver#getDDLScript(DBCmdType, DBObject, DBSQLScript)  
+     */
+    @Override
+    public boolean getDDLScript(DBCmdType type, DBObject dbo, DBSQLScript script)
+    {
+        // The Object's database must be attached to this driver
+        if (dbo==null || dbo.getDatabase().getDriver()!=this)
+            return error(Errors.InvalidArg, dbo, "dbo");
+        // Check Type of object
+        if (dbo instanceof DBDatabase)
+        { // Database
+            switch (type)
+            {
+                case CREATE:
+                    return createDatabase((DBDatabase) dbo, script, true);
+                case DROP:
+                    return dropObject(((DBDatabase) dbo).getSchema(), "DATABASE", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLScript."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBTable)
+        { // Table
+            switch (type)
+            {
+                case CREATE:
+                    return createTable((DBTable) dbo, script);
+                case DROP:
+                    return dropObject(((DBTable) dbo).getName(), "TABLE", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBView)
+        { // View
+            switch (type)
+            {
+                case CREATE:
+                    return createView((DBView) dbo, script);
+                case DROP:
+                    return dropObject(((DBView) dbo).getName(), "VIEW", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBRelation)
+        { // Relation
+            switch (type)
+            {
+                case CREATE:
+                    return createRelation((DBRelation) dbo, script);
+                case DROP:
+                    return dropObject(((DBRelation) dbo).getName(), "CONSTRAINT", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBTableColumn)
+        { // Table Column
+            return alterTable((DBTableColumn) dbo, type, script);
+        } 
+        else
+        { // an invalid argument has been supplied
+            return error(Errors.InvalidArg, dbo, "dbo");
+        }
+    }
+
+    /**
+     * Overridden. Returns a timestamp that is used for record updates created by the database server.
+     * 
+     * @return the current date and time of the database server.
+     */
+    @Override
+    public java.sql.Timestamp getUpdateTimestamp(Connection conn)
+    {
+        // Default implementation
+        GregorianCalendar cal = new GregorianCalendar();
+        return new java.sql.Timestamp(cal.getTimeInMillis());
+    }
+
+    /*
+     * return the sql for creating a Database
+     */
+    private boolean createDatabase(DBDatabase db, DBSQLScript script, boolean createSchema)
+    {
+//        // User Master to create Database
+//        if (createSchema)
+//        {   // check database Name
+//            if (StringUtils.isValid(databaseName)==false)
+//                return error(Errors.InvalidProperty, "databaseName");
+//            // Create Database
+//            script.addStmt("CREATE DATABASE " + databaseName + " CHARACTER SET " + characterSet);
+//            script.addStmt("USE " + databaseName);
+//            // appendDDLStmt(db, "SET DATEFORMAT ymd", buf);
+//            // Sequence Table
+//            if (useSequenceTable && db.getTable(sequenceTableName)==null)
+//                new DBSeqTable(sequenceTableName, db);
+//        }
+        // Create all Tables
+        Iterator<DBTable> tables = db.getTables().iterator();
+        while (tables.hasNext())
+        {
+            if (!createTable(tables.next(), script))
+                return false;
+        }
+        // Create Relations
+        Iterator<DBRelation> relations = db.getRelations().iterator();
+        while (relations.hasNext())
+        {
+            if (!createRelation(relations.next(), script))
+                return false;
+        }
+        // Create Views
+        Iterator<DBView> views = db.getViews().iterator();
+        while (views.hasNext())
+        {
+            if (!createView(views.next(), script))
+                return false;
+        }
+        // Done
+        return true;
+    }
+    
+    /**
+     * Returns true if the table has been created successfully.
+     * 
+     * @return true if the table has been created successfully
+     */
+    private boolean createTable(DBTable t, DBSQLScript script)
+    {
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating table ");
+        sql.append(t.getName());
+        sql.append(" --\r\n");
+        sql.append("CREATE TABLE ");
+        t.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" (");
+        boolean addSeparator = false;
+        Iterator<DBColumn> columns = t.getColumns().iterator();
+        while (columns.hasNext())
+        {
+            DBTableColumn c = (DBTableColumn) columns.next();
+            sql.append((addSeparator) ? ",\r\n   " : "\r\n   ");
+            if (appendColumnDesc(c, sql)==false)
+                continue; // Ignore and continue;
+            addSeparator = true;
+        }
+        // Primary Key
+        DBIndex pk = t.getPrimaryKey();
+        if (pk != null)
+        { // add the primary key
+            sql.append(", PRIMARY KEY (");
+            addSeparator = false;
+            // columns
+            DBColumn[] keyColumns = pk.getColumns();
+            for (int i = 0; i < keyColumns.length; i++)
+            {
+                sql.append((addSeparator) ? ", " : "");
+                keyColumns[i].addSQL(sql, DBExpr.CTX_NAME);
+                addSeparator = true;
+            }
+            sql.append(")");
+        }
+        sql.append(")");
+        // Comment?
+        String comment = t.getComment();
+        if (StringUtils.isValid(comment))
+        {   // Add the table comment
+            sql.append(" COMMENT = '");
+            sql.append(comment);
+            sql.append("'");
+        }
+        // Create the table
+        if (script.addStmt(sql) == false)
+            return false;
+        // Create other Indizes (except primary key)
+        Iterator<DBIndex> indexes = t.getIndexes().iterator();
+        while (indexes.hasNext())
+        {
+            DBIndex idx = indexes.next();
+            if (idx == pk || idx.getType() == DBIndex.PRIMARYKEY)
+                continue;
+
+            // Cretae Index
+            sql.setLength(0);
+            sql.append((idx.getType() == DBIndex.UNIQUE) ? "CREATE UNIQUE INDEX " : "CREATE INDEX ");
+            appendElementName(sql, idx.getName());
+            sql.append(" ON ");
+            t.addSQL(sql, DBExpr.CTX_FULLNAME);
+            sql.append(" (");
+            addSeparator = false;
+
+            // columns
+            DBColumn[] idxColumns = idx.getColumns();
+            for (int i = 0; i < idxColumns.length; i++)
+            {
+                sql.append((addSeparator) ? ", " : "");
+                idxColumns[i].addSQL(sql, DBExpr.CTX_NAME);
+                addSeparator = true;
+            }
+            sql.append(")");
+            // Create Index
+            if (script.addStmt(sql) == false)
+                return false;
+        }
+        // done
+        return success();
+    }
+    
+    /**
+     * Appends a table column defintion to a ddl statement
+     * @param c the column which description to append
+     * @param sql the sql builder object
+     * @return true if the column was successfully appended or false otherwise
+     */
+    private boolean appendColumnDesc(DBTableColumn c, StringBuilder sql)
+    {
+        // Append name
+        c.addSQL(sql, DBExpr.CTX_NAME);
+        sql.append(" ");
+        switch (c.getDataType())
+        {
+            case INTEGER:
+            { // Integer type
+                sql.append("INT");
+                int size = (int)c.getSize();
+                if (size>0)
+                {   // Set Integer length
+                    sql.append("(");
+                    sql.append(String.valueOf(size));
+                    sql.append(")");
+                }
+                break;
+            }    
+            case AUTOINC:
+            { // Auto increment
+                sql.append("INT");
+                if (useSequenceTable==false)
+                    sql.append(" GENERATED ALWAYS AS IDENTITY");
+                break;
+            }    
+            case TEXT:
+            { // Check fixed or variable length
+                int size = Math.abs((int) c.getSize());
+                if (size == 0)
+                    size = 100;
+                sql.append("VARCHAR(");
+                sql.append(String.valueOf(size));
+                sql.append(")");
+            }
+                break;
+            case CHAR:
+            { // Check fixed or variable length
+                int size = Math.abs((int) c.getSize());
+                if (size == 0)
+                    size = 1;
+                sql.append("CHAR(");
+                sql.append(String.valueOf(size));
+                sql.append(")");
+            }
+                break;
+            case DATE:
+                sql.append("DATE");
+                break;
+            case DATETIME:
+                sql.append("TIMESTAMP");
+                break;
+            case BOOL:
+            	if ( booleanType==BooleanType.CHAR )
+                    sql.append("CHAR(1)");
+                else sql.append("SMALLINT");
+                break;
+            case DOUBLE:
+                sql.append("DOUBLE");
+                break;
+            case DECIMAL:
+            { // Decimal
+                sql.append("DECIMAL(");
+                int prec = (int) c.getSize();
+                int scale = (int) ((c.getSize() - prec) * 10 + 0.5);
+                // sql.append((prec+scale).ToString());sql.append(",");
+                sql.append(String.valueOf(prec));
+                sql.append(",");
+                sql.append(String.valueOf(scale));
+                sql.append(")");
+            }
+                break;
+            case CLOB:
+                sql.append("LONGTEXT");
+                break;
+            case BLOB:
+                sql.append("BLOB");
+                if (c.getSize() > 0)
+                    sql.append(" (" + String.valueOf((long) c.getSize()) + ") ");
+                break;
+            case UNKNOWN:
+                 log.error("Cannot append column of Data-Type 'UNKNOWN'");
+                 return false;
+        }
+        // Default Value
+        if (isDDLColumnDefaults() && c.getDataType()!=DataType.AUTOINC && c.getDefaultValue()!=null)
+        {   sql.append(" DEFAULT ");
+            sql.append(getValueString(c.getDefaultValue(), c.getDataType()));
+        }
+        // Nullable
+        if (c.isRequired())
+            sql.append(" NOT NULL");
+        // Done
+        return true;
+    }
+
+    /**
+     * Returns true if the relation has been created successfully.
+     * 
+     * @return true if the relation has been created successfully
+     */
+    private boolean createRelation(DBRelation r, DBSQLScript script)
+    {
+        DBTable sourceTable = (DBTable) r.getReferences()[0].getSourceColumn().getRowSet();
+        DBTable targetTable = (DBTable) r.getReferences()[0].getTargetColumn().getRowSet();
+
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating foreign key constraint ");
+        sql.append(r.getName());
+        sql.append(" --\r\n");
+        sql.append("ALTER TABLE ");
+        sourceTable.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" ADD CONSTRAINT ");
+        appendElementName(sql, r.getName());
+        sql.append(" FOREIGN KEY (");
+        // Source Names
+        boolean addSeparator = false;
+        DBRelation.DBReference[] refs = r.getReferences();
+        for (int i = 0; i < refs.length; i++)
+        {
+            sql.append((addSeparator) ? ", " : "");
+            refs[i].getSourceColumn().addSQL(sql, DBExpr.CTX_NAME);
+            addSeparator = true;
+        }
+        // References
+        sql.append(") REFERENCES ");
+        targetTable.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" (");
+        // Target Names
+        addSeparator = false;
+        for (int i = 0; i < refs.length; i++)
+        {
+            sql.append((addSeparator) ? ", " : "");
+            refs[i].getTargetColumn().addSQL(sql, DBExpr.CTX_NAME);
+            addSeparator = true;
+        }
+        // done
+        sql.append(")");
+        if (script.addStmt(sql) == false)
+            return false;
+        // done
+        return success();
+    }
+
+    /**
+     * Creates an alter table dll statement for adding, modifiying or droping a column.
+     * @param col the column which to add, modify or drop
+     * @param type the type of operation to perform
+     * @param buf buffer to which to append the sql statement to
+     * @return true if the statement was successfully appended to the buffer
+     */
+    private boolean alterTable(DBTableColumn col, DBCmdType type, DBSQLScript script)
+    {
+        StringBuilder sql = new StringBuilder();
+        sql.append("ALTER TABLE ");
+        col.getRowSet().addSQL(sql, DBExpr.CTX_FULLNAME);
+        switch(type)
+        {
+            case CREATE:
+                sql.append(" ADD ");
+                appendColumnDesc(col, sql);
+                break;
+            case ALTER:
+                sql.append(" MODIFY ");
+                appendColumnDesc(col, sql);
+                break;
+            case DROP:
+                sql.append(" DROP COLUMN ");
+                sql.append(col.getName());
+                break;
+        }
+        // done
+        return script.addStmt(sql);
+    }
+
+    /**
+     * Returns true if the view has been created successfully.
+     * 
+     * @return true if the view has been created successfully
+     */
+    private boolean createView(DBView v, DBSQLScript script)
+    {
+        // Create the Command
+        DBCommandExpr cmd = v.createCommand();
+        if (cmd==null)
+        {   // Check whether Error information is available
+            log.error("No command has been supplied for view " + v.getName());
+            if (v.hasError())
+                return error(v);
+            // No error information available: Use Errors.NotImplemented
+            return error(Errors.NotImplemented, v.getName() + ".createCommand");
+        }
+        // Make sure there is no OrderBy
+        cmd.clearOrderBy();
+
+        // Build String
+        StringBuilder sql = new StringBuilder();
+        sql.append( "CREATE VIEW ");
+        v.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append( " (" );
+        boolean addSeparator = false;
+        for(DBColumn c : v.getColumns())
+        {
+            if (addSeparator)
+                sql.append(", ");
+            // Add Column name
+            c.addSQL(sql, DBExpr.CTX_NAME);
+            // next
+            addSeparator = true;
+        }
+        sql.append(")\r\nAS\r\n");
+        cmd.addSQL( sql, DBExpr.CTX_DEFAULT);
+        // done
+        return script.addStmt(sql.toString());
+    }
+    
+    /**
+     * Returns true if the object has been dropped successfully.
+     * 
+     * @return true if the object has been dropped successfully
+     */
+    private boolean dropObject(String name, String objType, DBSQLScript script)
+    {
+        if (name == null || name.length() == 0)
+            return error(Errors.InvalidArg, name, "name");
+        // Create Drop Statement
+        StringBuilder sql = new StringBuilder();
+        sql.append("DROP ");
+        sql.append(objType);
+        sql.append(" ");
+        appendElementName(sql, name);
+        return script.addStmt(sql);
+    }
+
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/package.html
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/package.html?rev=742097&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/package.html (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/derby/package.html Sun Feb  8 14:11:24 2009
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ --> 
+<html>
+<head>
+</head>
+<body>
+
+This package contains classes necessary to support the Apache Derby database system.
+
+</body></html>
\ No newline at end of file

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/DBDatabaseDriverH2.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/DBDatabaseDriverH2.java?rev=742097&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/DBDatabaseDriverH2.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/DBDatabaseDriverH2.java Sun Feb  8 14:11:24 2009
@@ -0,0 +1,728 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.db.h2;
+
+import java.sql.Connection;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBCmdType;
+import org.apache.empire.db.DBColumn;
+import org.apache.empire.db.DBCommand;
+import org.apache.empire.db.DBCommandExpr;
+import org.apache.empire.db.DBDatabase;
+import org.apache.empire.db.DBDatabaseDriver;
+import org.apache.empire.db.DBDriverFeature;
+import org.apache.empire.db.DBExpr;
+import org.apache.empire.db.DBIndex;
+import org.apache.empire.db.DBObject;
+import org.apache.empire.db.DBRelation;
+import org.apache.empire.db.DBSQLScript;
+import org.apache.empire.db.DBTable;
+import org.apache.empire.db.DBTableColumn;
+import org.apache.empire.db.DBView;
+
+
+/**
+ * This class provides support for the H2 database system.
+ * 
+ *
+ */
+public class DBDatabaseDriverH2 extends DBDatabaseDriver
+{
+    /**
+     * Defines the H2 command type.
+     */ 
+    public static class DBCommandH2 extends DBCommand
+    {
+        public DBCommandH2(DBDatabase db)
+        {
+            super(db);
+        }
+    }
+    
+    // Properties
+    private String databaseName = null;
+    // Sequence treatment
+    // When set to 'false' (default) H2's autoincrement feature is used.
+    private boolean useSequenceTable = false;
+    private String sequenceTableName = "Sequences";
+    
+    /**
+     * Constructor for the H2 database driver.<br>
+     */
+    public DBDatabaseDriverH2()
+    {
+        // Default Constructor
+    }
+
+    /**
+     * returns the name for the database / schema
+     * @return the database / schema name
+     */
+    public String getDatabaseName()
+    {
+        return databaseName;
+    }
+
+    /**
+     * Sets the name for the database / schema<br>
+     * This names is required for creating a database.<br>
+     * When a name is set, the driver will automatically execute 'USE dbname' when the database is opened.
+     * @param databaseName the name of the database
+     */
+    public void setDatabaseName(String databaseName)
+    {
+        this.databaseName = databaseName;
+    }
+
+    /**
+     * returns whether a sequence table is used for record identiy management.<br>
+     * Default is false. In this case the AutoIncrement feature of H2 is used.
+     * @return true if a sequence table is used instead of identity columns.
+     */
+    public boolean isUseSequenceTable()
+    {
+        return useSequenceTable;
+    }
+
+    /**
+     * If set to true a special table is used for sequence number generation.<br>
+     * Otherwise the AutoIncrement feature of H2 is used identiy fields. 
+     * @param useSequenceTable true to use a sequence table or false otherwise.
+     */
+    public void setUseSequenceTable(boolean useSequenceTable)
+    {
+        this.useSequenceTable = useSequenceTable;
+    }
+
+    /**
+     * returns the name of the sequence table
+     * @return the name of the table used for sequence number generation
+     */
+    public String getSequenceTableName()
+    {
+        return sequenceTableName;
+    }
+
+    /**
+     * Sets the name of the sequence table.
+     * Only applicable if useSequenceTable is set to true.
+     * @param sequenceTableName the name of the table used for sequence number generation
+     */
+    public void setSequenceTableName(String sequenceTableName)
+    {
+        this.sequenceTableName = sequenceTableName;
+    }
+
+    /**
+     * Creates a new H2 command object.
+     * 
+     * @return the new DBCommandDerby object
+     */
+    @Override
+    public DBCommand createCommand(DBDatabase db)
+    {
+        if (db == null)
+            return null;
+        // create command object
+        return new DBCommandH2(db);
+    }
+
+    /**
+     * Returns whether or not a particular feature is supported by this driver
+     * @param type type of requrested feature. @see DBDriverFeature
+     * @return true if the features is supported or false otherwise
+     */
+    @Override
+    public boolean isSupported(DBDriverFeature type)
+    {
+        switch (type)
+        {   // return support info 
+            case CREATE_SCHEMA: return true;
+            case SEQUENCES:     return useSequenceTable;    
+        }
+        return false;
+    }
+    
+    /**
+     * Gets an sql phrase template for this database system.<br>
+     * @see DBDatabaseDriver#getSQLPhrase(int)
+     * @return the phrase template
+     */
+    @Override
+    public String getSQLPhrase(int phrase)
+    {
+        switch (phrase)
+        {
+            // sql-phrases
+            case SQL_NULL_VALUE:              return "null";
+            case SQL_PARAMETER:               return " ? ";
+            case SQL_RENAME_TABLE:            return " ";
+            case SQL_RENAME_COLUMN:           return " AS ";
+            case SQL_DATABASE_LINK:           return "@";
+            case SQL_QUOTES_OPEN:             return "\"";
+            case SQL_QUOTES_CLOSE:            return "\"";
+            case SQL_CONCAT_EXPR:             return "concat(?, {0})";
+            // data types
+            case SQL_BOOLEAN_TRUE:            return "1";
+            case SQL_BOOLEAN_FALSE:           return "0";
+            case SQL_CURRENT_DATE:            return "CURRENT_DATE()";
+            case SQL_DATE_PATTERN:            return "yyyy-MM-dd";
+            case SQL_DATE_TEMPLATE:           return "'{0}'";
+            case SQL_CURRENT_DATETIME:        return "NOW()";
+            case SQL_DATETIME_PATTERN:        return "yyyy-MM-dd HH:mm:ss";
+            case SQL_DATETIME_TEMPLATE:       return "'{0}'";
+            // functions
+            case SQL_FUNC_COALESCE:           return "coalesce(?, {0})";
+            case SQL_FUNC_SUBSTRING:          return "substring(?, {0})";
+            case SQL_FUNC_SUBSTRINGEX:        return "substring(?, {0}, {1})";
+            case SQL_FUNC_REPLACE:            return "replace(?, {0}, {1})";
+            case SQL_FUNC_REVERSE:            return "reverse_not_available_in_h2(?)"; 
+            case SQL_FUNC_STRINDEX:           return "instr(?, {0})"; 
+            case SQL_FUNC_STRINDEXFROM:       return "locate({0}, ?, {1})"; 
+            case SQL_FUNC_LENGTH:             return "length(?)";
+            case SQL_FUNC_UPPER:              return "upper(?)";
+            case SQL_FUNC_LOWER:              return "lcase(?)";
+            case SQL_FUNC_TRIM:               return "trim(?)";
+            case SQL_FUNC_LTRIM:              return "ltrim(?)";
+            case SQL_FUNC_RTRIM:              return "rtrim(?)";
+            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            // Numeric
+            case SQL_FUNC_ABS:                return "abs(?)";
+            case SQL_FUNC_ROUND:              return "round(?,{0})";
+            case SQL_FUNC_TRUNC:              return "truncate(?,{0})";
+            case SQL_FUNC_CEILING:            return "ceiling(?)";
+            case SQL_FUNC_FLOOR:              return "floor(?)";
+            // Date
+            case SQL_FUNC_DAY:                return "day(?)";
+            case SQL_FUNC_MONTH:              return "month(?)";
+            case SQL_FUNC_YEAR:               return "year(?)";
+            // Aggregation
+            case SQL_FUNC_SUM:                return "sum(?)";
+            case SQL_FUNC_MAX:                return "max(?)";
+            case SQL_FUNC_MIN:                return "min(?)";
+            case SQL_FUNC_AVG:                return "avg(?)";
+            // Others
+            case SQL_FUNC_DECODE:             return "case ? {0} end";
+            case SQL_FUNC_DECODE_SEP:         return " ";
+            case SQL_FUNC_DECODE_PART:        return "when {0} then {1}";
+            case SQL_FUNC_DECODE_ELSE:        return "else {0}";
+            // Not defined
+            default:
+                log.error("SQL phrase " + String.valueOf(phrase) + " is not defined!");
+                return "?";
+        }
+    }
+
+    /**
+     * @see DBDatabaseDriver#getConvertPhrase(DataType, DataType, Object)
+     */
+    @Override
+    public String getConvertPhrase(DataType destType, DataType srcType, Object format)
+    {
+        switch(destType)
+        {
+           case BOOL:      return "CAST(? AS UNSIGNED)";
+           case INTEGER:   return "CAST(? AS SIGNED)";
+           case DECIMAL:   return "CAST(? AS DECIMAL)";
+           case DOUBLE:    return "CAST(? AS DECIMAL)";
+           case DATE:      return "CAST(? AS DATE)";
+           case DATETIME:  return "CAST(? AS DATETIME)";
+           // Convert to text
+           case TEXT:
+                return "CAST(? AS CHAR)";
+           case BLOB:
+                return "CAST(? AS BLOB)";
+           // Unknown Type                                       
+           default:
+                log.error("getConvertPhrase: unknown type (" + String.valueOf(destType));
+                return "?";
+        }
+    }
+    
+    /**
+     * @see DBDatabaseDriver#getNextSequenceValue(DBDatabase, String, int, Connection)
+     */
+    @Override
+    public Object getNextSequenceValue(DBDatabase db, String seqName, int minValue, Connection conn)
+    {   //Use Oracle Sequences
+        if (useSequenceTable)
+        {   // Use a sequence Table to generate Sequences
+            DBTable t = db.getTable(sequenceTableName);
+            return ((DBSeqTable)t).getNextValue(seqName, minValue, conn);
+        }
+        else
+        {   // Post Detection
+            return null;
+        }
+    }
+
+    /**
+     * @see DBDatabaseDriver#getDDLScript(DBCmdType, DBObject, DBSQLScript)  
+     */
+    @Override
+    public boolean getDDLScript(DBCmdType type, DBObject dbo, DBSQLScript script)
+    {
+        // The Object's database must be attached to this driver
+        if (dbo==null || dbo.getDatabase().getDriver()!=this)
+            return error(Errors.InvalidArg, dbo, "dbo");
+        // Check Type of object
+        if (dbo instanceof DBDatabase)
+        { // Database
+            switch (type)
+            {
+                case CREATE:
+                    return createDatabase((DBDatabase) dbo, script, true);
+                case DROP:
+                    return dropObject(((DBDatabase) dbo).getSchema(), "DATABASE", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLScript."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBTable)
+        { // Table
+            switch (type)
+            {
+                case CREATE:
+                    return createTable((DBTable) dbo, script);
+                case DROP:
+                    return dropObject(((DBTable) dbo).getName(), "TABLE", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBView)
+        { // View
+            switch (type)
+            {
+                case CREATE:
+                    return createView((DBView) dbo, script);
+                case DROP:
+                    return dropObject(((DBView) dbo).getName(), "VIEW", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBRelation)
+        { // Relation
+            switch (type)
+            {
+                case CREATE:
+                    return createRelation((DBRelation) dbo, script);
+                case DROP:
+                    return dropObject(((DBRelation) dbo).getName(), "CONSTRAINT", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBTableColumn)
+        { // Table Column
+            return alterTable((DBTableColumn) dbo, type, script);
+        } 
+        else
+        { // an invalid argument has been supplied
+            return error(Errors.InvalidArg, dbo, "dbo");
+        }
+    }
+
+    /**
+     * Overridden. Returns a timestamp that is used for record updates created by the database server.
+     * 
+     * @return the current date and time of the database server.
+     */
+    @Override
+    public java.sql.Timestamp getUpdateTimestamp(Connection conn)
+    {
+        // Default implementation
+        GregorianCalendar cal = new GregorianCalendar();
+        return new java.sql.Timestamp(cal.getTimeInMillis());
+    }
+
+    /*
+     * return the sql for creating a Database
+     */
+    private boolean createDatabase(DBDatabase db, DBSQLScript script, boolean createSchema)
+    {
+//        // User Master to create Database
+//        if (createSchema)
+//        {   // check database Name
+//            if (StringUtils.isValid(databaseName)==false)
+//                return error(Errors.InvalidProperty, "databaseName");
+//            // Create Database
+//            script.addStmt("CREATE DATABASE " + databaseName + " CHARACTER SET " + characterSet);
+//            script.addStmt("USE " + databaseName);
+//            // appendDDLStmt(db, "SET DATEFORMAT ymd", buf);
+//            // Sequence Table
+//            if (useSequenceTable && db.getTable(sequenceTableName)==null)
+//                new DBSeqTable(sequenceTableName, db);
+//        }
+        // Create all Tables
+        Iterator<DBTable> tables = db.getTables().iterator();
+        while (tables.hasNext())
+        {
+            if (!createTable(tables.next(), script))
+                return false;
+        }
+        // Create Relations
+        Iterator<DBRelation> relations = db.getRelations().iterator();
+        while (relations.hasNext())
+        {
+            if (!createRelation(relations.next(), script))
+                return false;
+        }
+        // Create Views
+        Iterator<DBView> views = db.getViews().iterator();
+        while (views.hasNext())
+        {
+            if (!createView(views.next(), script))
+                return false;
+        }
+        // Done
+        return true;
+    }
+    
+    /**
+     * Returns true if the table has been created successfully.
+     * 
+     * @return true if the table has been created successfully
+     */
+    private boolean createTable(DBTable t, DBSQLScript script)
+    {
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating table ");
+        sql.append(t.getName());
+        sql.append(" --\r\n");
+        sql.append("CREATE TABLE ");
+        t.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" (");
+        boolean addSeparator = false;
+        Iterator<DBColumn> columns = t.getColumns().iterator();
+        while (columns.hasNext())
+        {
+            DBTableColumn c = (DBTableColumn) columns.next();
+            sql.append((addSeparator) ? ",\r\n   " : "\r\n   ");
+            if (appendColumnDesc(c, sql)==false)
+                continue; // Ignore and continue;
+            addSeparator = true;
+        }
+        // Primary Key
+        DBIndex pk = t.getPrimaryKey();
+        if (pk != null)
+        { // add the primary key
+            sql.append(", PRIMARY KEY (");
+            addSeparator = false;
+            // columns
+            DBColumn[] keyColumns = pk.getColumns();
+            for (int i = 0; i < keyColumns.length; i++)
+            {
+                sql.append((addSeparator) ? ", " : "");
+                keyColumns[i].addSQL(sql, DBExpr.CTX_NAME);
+                addSeparator = true;
+            }
+            sql.append(")");
+        }
+        sql.append(")");
+        // Comment?
+        String comment = t.getComment();
+        if (StringUtils.isValid(comment))
+        {   // Add the table comment
+            sql.append(" COMMENT = '");
+            sql.append(comment);
+            sql.append("'");
+        }
+        // Create the table
+        if (script.addStmt(sql) == false)
+            return false;
+        // Create other Indizes (except primary key)
+        Iterator<DBIndex> indexes = t.getIndexes().iterator();
+        while (indexes.hasNext())
+        {
+            DBIndex idx = indexes.next();
+            if (idx == pk || idx.getType() == DBIndex.PRIMARYKEY)
+                continue;
+
+            // Cretae Index
+            sql.setLength(0);
+            sql.append((idx.getType() == DBIndex.UNIQUE) ? "CREATE UNIQUE INDEX " : "CREATE INDEX ");
+            appendElementName(sql, idx.getName());
+            sql.append(" ON ");
+            t.addSQL(sql, DBExpr.CTX_FULLNAME);
+            sql.append(" (");
+            addSeparator = false;
+
+            // columns
+            DBColumn[] idxColumns = idx.getColumns();
+            for (int i = 0; i < idxColumns.length; i++)
+            {
+                sql.append((addSeparator) ? ", " : "");
+                idxColumns[i].addSQL(sql, DBExpr.CTX_NAME);
+                addSeparator = true;
+            }
+            sql.append(")");
+            // Create Index
+            if (script.addStmt(sql) == false)
+                return false;
+        }
+        // done
+        return success();
+    }
+    
+    /**
+     * Appends a table column defintion to a ddl statement
+     * @param c the column which description to append
+     * @param sql the sql builder object
+     * @return true if the column was successfully appended or false otherwise
+     */
+    private boolean appendColumnDesc(DBTableColumn c, StringBuilder sql)
+    {
+        // Append name
+        c.addSQL(sql, DBExpr.CTX_NAME);
+        sql.append(" ");
+        switch (c.getDataType())
+        {
+            case INTEGER:
+            { // Integer type
+                sql.append("INT");
+                int size = (int)c.getSize();
+                if (size>0)
+                {   // Set Integer length
+                    sql.append("(");
+                    sql.append(String.valueOf(size));
+                    sql.append(")");
+                }
+                break;
+            }    
+            case AUTOINC:
+            { // Auto increment
+                sql.append("INT");
+                if (useSequenceTable==false)
+                    sql.append(" AUTO_INCREMENT");
+                break;
+            }    
+            case TEXT:
+            { // Check fixed or variable length
+                int size = Math.abs((int) c.getSize());
+                if (size == 0)
+                    size = 100;
+                sql.append("VARCHAR(");
+                sql.append(String.valueOf(size));
+                sql.append(")");
+            }
+                break;
+            case CHAR:
+            { // Check fixed or variable length
+                int size = Math.abs((int) c.getSize());
+                if (size == 0)
+                    size = 1;
+                sql.append("CHAR(");
+                sql.append(String.valueOf(size));
+                sql.append(")");
+            }
+                break;
+            case DATE:
+                sql.append("DATE");
+                break;
+            case DATETIME:
+                sql.append("DATETIME");
+                break;
+            case BOOL:
+                sql.append("BIT");
+                break;
+            case DOUBLE:
+                sql.append("DOUBLE");
+                break;
+            case DECIMAL:
+            { // Decimal
+                sql.append("DECIMAL(");
+                int prec = (int) c.getSize();
+                int scale = (int) ((c.getSize() - prec) * 10 + 0.5);
+                // sql.append((prec+scale).ToString());sql.append(",");
+                sql.append(String.valueOf(prec));
+                sql.append(",");
+                sql.append(String.valueOf(scale));
+                sql.append(")");
+            }
+                break;
+            case CLOB:
+                sql.append("LONGTEXT");
+                break;
+            case BLOB:
+                sql.append("BLOB");
+                if (c.getSize() > 0)
+                    sql.append(" (" + String.valueOf((long) c.getSize()) + ") ");
+                break;
+            case UNKNOWN:
+                 log.error("Cannot append column of Data-Type 'UNKNOWN'");
+                 return false;
+        }
+        // Default Value
+        if (isDDLColumnDefaults() && c.getDataType()!=DataType.AUTOINC && c.getDefaultValue()!=null)
+        {   sql.append(" DEFAULT ");
+            sql.append(getValueString(c.getDefaultValue(), c.getDataType()));
+        }
+        // Nullable
+        if (c.isRequired())
+            sql.append(" NOT NULL");
+        // Done
+        return true;
+    }
+
+    /**
+     * Returns true if the relation has been created successfully.
+     * 
+     * @return true if the relation has been created successfully
+     */
+    private boolean createRelation(DBRelation r, DBSQLScript script)
+    {
+        DBTable sourceTable = (DBTable) r.getReferences()[0].getSourceColumn().getRowSet();
+        DBTable targetTable = (DBTable) r.getReferences()[0].getTargetColumn().getRowSet();
+
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating foreign key constraint ");
+        sql.append(r.getName());
+        sql.append(" --\r\n");
+        sql.append("ALTER TABLE ");
+        sourceTable.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" ADD CONSTRAINT ");
+        appendElementName(sql, r.getName());
+        sql.append(" FOREIGN KEY (");
+        // Source Names
+        boolean addSeparator = false;
+        DBRelation.DBReference[] refs = r.getReferences();
+        for (int i = 0; i < refs.length; i++)
+        {
+            sql.append((addSeparator) ? ", " : "");
+            refs[i].getSourceColumn().addSQL(sql, DBExpr.CTX_NAME);
+            addSeparator = true;
+        }
+        // References
+        sql.append(") REFERENCES ");
+        targetTable.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" (");
+        // Target Names
+        addSeparator = false;
+        for (int i = 0; i < refs.length; i++)
+        {
+            sql.append((addSeparator) ? ", " : "");
+            refs[i].getTargetColumn().addSQL(sql, DBExpr.CTX_NAME);
+            addSeparator = true;
+        }
+        // done
+        sql.append(")");
+        if (script.addStmt(sql) == false)
+            return false;
+        // done
+        return success();
+    }
+
+    /**
+     * Creates an alter table dll statement for adding, modifiying or droping a column.
+     * @param col the column which to add, modify or drop
+     * @param type the type of operation to perform
+     * @param buf buffer to which to append the sql statement to
+     * @return true if the statement was successfully appended to the buffer
+     */
+    private boolean alterTable(DBTableColumn col, DBCmdType type, DBSQLScript script)
+    {
+        StringBuilder sql = new StringBuilder();
+        sql.append("ALTER TABLE ");
+        col.getRowSet().addSQL(sql, DBExpr.CTX_FULLNAME);
+        switch(type)
+        {
+            case CREATE:
+                sql.append(" ADD ");
+                appendColumnDesc(col, sql);
+                break;
+            case ALTER:
+                sql.append(" MODIFY ");
+                appendColumnDesc(col, sql);
+                break;
+            case DROP:
+                sql.append(" DROP COLUMN ");
+                sql.append(col.getName());
+                break;
+        }
+        // done
+        return script.addStmt(sql);
+    }
+
+    /**
+     * Returns true if the view has been created successfully.
+     * 
+     * @return true if the view has been created successfully
+     */
+    private boolean createView(DBView v, DBSQLScript script)
+    {
+        // Create the Command
+        DBCommandExpr cmd = v.createCommand();
+        if (cmd==null)
+        {   // Check whether Error information is available
+            log.error("No command has been supplied for view " + v.getName());
+            if (v.hasError())
+                return error(v);
+            // No error information available: Use Errors.NotImplemented
+            return error(Errors.NotImplemented, v.getName() + ".createCommand");
+        }
+        // Make sure there is no OrderBy
+        cmd.clearOrderBy();
+
+        // Build String
+        StringBuilder sql = new StringBuilder();
+        sql.append( "CREATE VIEW ");
+        v.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append( " (" );
+        boolean addSeparator = false;
+        for(DBColumn c : v.getColumns())
+        {
+            if (addSeparator)
+                sql.append(", ");
+            // Add Column name
+            c.addSQL(sql, DBExpr.CTX_NAME);
+            // next
+            addSeparator = true;
+        }
+        sql.append(")\r\nAS\r\n");
+        cmd.addSQL( sql, DBExpr.CTX_DEFAULT);
+        // done
+        return script.addStmt(sql.toString());
+    }
+    
+    /**
+     * Returns true if the object has been dropped successfully.
+     * 
+     * @return true if the object has been dropped successfully
+     */
+    private boolean dropObject(String name, String objType, DBSQLScript script)
+    {
+        if (name == null || name.length() == 0)
+            return error(Errors.InvalidArg, name, "name");
+        // Create Drop Statement
+        StringBuilder sql = new StringBuilder();
+        sql.append("DROP ");
+        sql.append(objType);
+        sql.append(" ");
+        appendElementName(sql, name);
+        return script.addStmt(sql);
+    }
+
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/package.html
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/package.html?rev=742097&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/package.html (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/h2/package.html Sun Feb  8 14:11:24 2009
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ --> 
+<html>
+<head>
+</head>
+<body>
+
+This package contains classes necessary to support the H2 database system.
+
+</body></html>
\ No newline at end of file

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/DBDatabaseDriverPostgreSQL.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/DBDatabaseDriverPostgreSQL.java?rev=742097&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/DBDatabaseDriverPostgreSQL.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/DBDatabaseDriverPostgreSQL.java Sun Feb  8 14:11:24 2009
@@ -0,0 +1,768 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.empire.db.postgresql;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.DataType;
+import org.apache.empire.db.DBCmdType;
+import org.apache.empire.db.DBColumn;
+import org.apache.empire.db.DBCommand;
+import org.apache.empire.db.DBCommandExpr;
+import org.apache.empire.db.DBDatabase;
+import org.apache.empire.db.DBDatabaseDriver;
+import org.apache.empire.db.DBDriverFeature;
+import org.apache.empire.db.DBExpr;
+import org.apache.empire.db.DBIndex;
+import org.apache.empire.db.DBObject;
+import org.apache.empire.db.DBRelation;
+import org.apache.empire.db.DBSQLScript;
+import org.apache.empire.db.DBTable;
+import org.apache.empire.db.DBTableColumn;
+import org.apache.empire.db.DBView;
+import org.apache.empire.db.DBDatabaseDriver.DBSetGenKeys;
+
+
+/**
+ * This class provides support for the PostgreSQL database system.
+ * 
+ *
+ */
+public class DBDatabaseDriverPostgreSQL extends DBDatabaseDriver
+{
+    /**
+     * Defines the PostgreSQL command type.
+     */ 
+    public static class DBCommandPostreSQL extends DBCommand
+    {
+        public DBCommandPostreSQL(DBDatabase db)
+        {
+            super(db);
+        }
+    }
+    
+    // Properties
+    private String databaseName = null;
+    
+    /**
+     * Constructor for the PostgreSQL database driver.<br>
+     */
+    public DBDatabaseDriverPostgreSQL()
+    {
+        // Default Constructor
+    }
+
+    /**
+     * returns the name for the database / schema
+     * @return the database / schema name
+     */
+    public String getDatabaseName()
+    {
+        return databaseName;
+    }
+
+    /**
+     * Sets the name for the database / schema<br>
+     * This names is required for creating a database.<br>
+     * When a name is set, the driver will automatically execute 'USE dbname' when the database is opened.
+     * @param databaseName the name of the database
+     */
+    public void setDatabaseName(String databaseName)
+    {
+        this.databaseName = databaseName;
+    }
+
+    /**
+     * Creates a new PostgreSQL command object.
+     * 
+     * @return the new DBCommandPostgreSQL object
+     */
+    @Override
+    public DBCommand createCommand(DBDatabase db)
+    {
+        if (db == null)
+            return null;
+        // create command object
+        return new DBCommandPostreSQL(db);
+    }
+
+    /**
+     * Returns whether or not a particular feature is supported by this driver
+     * @param type type of requrested feature. @see DBDriverFeature
+     * @return true if the features is supported or false otherwise
+     */
+    @Override
+    public boolean isSupported(DBDriverFeature type)
+    {
+        switch (type)
+        {   // return support info 
+            case CREATE_SCHEMA: return true;
+            case SEQUENCES:     return true;    
+        }
+        return false;
+    }
+    
+    /**
+     * Gets an sql phrase template for this database system.<br>
+     * @see DBDatabaseDriver#getSQLPhrase(int)
+     * @return the phrase template
+     */
+    @Override
+    public String getSQLPhrase(int phrase)
+    {
+        switch (phrase)
+        {
+            // sql-phrases
+            case SQL_NULL_VALUE:              return "null";
+            case SQL_PARAMETER:               return " ? ";
+            case SQL_RENAME_TABLE:            return " ";
+            case SQL_RENAME_COLUMN:           return " AS ";
+            case SQL_DATABASE_LINK:           return "@";
+            case SQL_QUOTES_OPEN:             return "\"";
+            case SQL_QUOTES_CLOSE:            return "\"";
+            case SQL_CONCAT_EXPR:             return "? || {0}";
+            // data types
+            case SQL_BOOLEAN_TRUE:            return "TRUE";
+            case SQL_BOOLEAN_FALSE:           return "FALSE";
+            case SQL_CURRENT_DATE:            return "CURRENT_DATE()";
+            case SQL_DATE_PATTERN:            return "yyyy-MM-dd";
+            case SQL_DATE_TEMPLATE:           return "'{0}'";
+            case SQL_CURRENT_DATETIME:        return "NOW()";
+            case SQL_DATETIME_PATTERN:        return "yyyy-MM-dd HH:mm:ss";
+            case SQL_DATETIME_TEMPLATE:       return "'{0}'";
+            // functions
+            case SQL_FUNC_COALESCE:           return "coalesce(?, {0})";
+            case SQL_FUNC_SUBSTRING:          return "substring(?, {0})";
+            case SQL_FUNC_SUBSTRINGEX:        return "substring(?, {0}, {1})";
+            case SQL_FUNC_REPLACE:            return "replace(?, {0}, {1})";
+            case SQL_FUNC_REVERSE:            return "reverse_not_available_in_pgsql(?)";//"reverse(?)";
+            case SQL_FUNC_STRINDEX:           return "strpos(?, {0})"; 
+            case SQL_FUNC_STRINDEXFROM:       return "strindexfrom_not_available_in_pgsql({0}, ?, {1})";//"locate({0}, ?, {1})"; 
+            case SQL_FUNC_LENGTH:             return "length(?)";
+            case SQL_FUNC_UPPER:              return "upper(?)";
+            case SQL_FUNC_LOWER:              return "lcase(?)";
+            case SQL_FUNC_TRIM:               return "trim(?)";
+            case SQL_FUNC_LTRIM:              return "ltrim(?)";
+            case SQL_FUNC_RTRIM:              return "rtrim(?)";
+            case SQL_FUNC_ESCAPE:             return "? escape '{0}'";
+            // Numeric
+            case SQL_FUNC_ABS:                return "abs(?)";
+            case SQL_FUNC_ROUND:              return "round(?,{0})";
+            case SQL_FUNC_TRUNC:              return "truncate(?,{0})";
+            case SQL_FUNC_CEILING:            return "ceiling(?)";
+            case SQL_FUNC_FLOOR:              return "floor(?)";
+            // Date
+            case SQL_FUNC_DAY:                return "day(?)";
+            case SQL_FUNC_MONTH:              return "month(?)";
+            case SQL_FUNC_YEAR:               return "year(?)";
+            // Aggregation
+            case SQL_FUNC_SUM:                return "sum(?)";
+            case SQL_FUNC_MAX:                return "max(?)";
+            case SQL_FUNC_MIN:                return "min(?)";
+            case SQL_FUNC_AVG:                return "avg(?)";
+            // Others
+            case SQL_FUNC_DECODE:             return "case ? {0} end";
+            case SQL_FUNC_DECODE_SEP:         return " ";
+            case SQL_FUNC_DECODE_PART:        return "when {0} then {1}";
+            case SQL_FUNC_DECODE_ELSE:        return "else {0}";
+            // Not defined
+            default:
+                log.error("SQL phrase " + String.valueOf(phrase) + " is not defined!");
+                return "?";
+        }
+    }
+
+    /**
+     * @see DBDatabaseDriver#getConvertPhrase(DataType, DataType, Object)
+     */
+    @Override
+    public String getConvertPhrase(DataType destType, DataType srcType, Object format)
+    {
+        switch(destType)
+        {
+           case BOOL:      return "CAST(? AS UNSIGNED)";
+           case INTEGER:   return "CAST(? AS SIGNED)";
+           case DECIMAL:   return "CAST(? AS DECIMAL)";
+           case DOUBLE:    return "CAST(? AS DECIMAL)";
+           case DATE:      return "CAST(? AS DATE)";
+           case DATETIME:  return "CAST(? AS DATETIME)";
+           // Convert to text
+           case TEXT:
+                return "CAST(? AS CHAR)";
+           case BLOB:
+                return "CAST(? AS BLOB)";
+           // Unknown Type                                       
+           default:
+                log.error("getConvertPhrase: unknown type (" + String.valueOf(destType));
+                return "?";
+        }
+    }
+
+    
+    /**
+     * @see DBDatabaseDriver#getNextSequenceValue(DBDatabase, String, int, Connection)
+     */
+    @Override
+    public Object getNextSequenceValue(DBDatabase db, String seqName, int minValue, Connection conn)
+    { // Use Oracle Sequences
+        StringBuilder sql = new StringBuilder(80);
+        sql.append("SELECT nextval('");
+        db.appendQualifiedName(sql, seqName, detectQuoteName(seqName));
+        sql.append("')");
+        Object val = db.querySingleValue(sql.toString(), conn);
+        if (val == null)
+        { // Error!
+            log.error("getNextSequenceValue: Invalid sequence value for sequence " + seqName);
+        }
+        // Done
+        return val;
+    }
+    
+    @Override
+    public int executeSQL(String sqlCmd, Object[] sqlParams, Connection conn, DBSetGenKeys genKeys)
+    throws SQLException
+{   // Execute the Statement
+    Statement stmt = null;
+    try
+    {
+        int count = 0;
+        if (sqlParams!=null)
+        {   // Use a prepared statement
+            PreparedStatement pstmt = conn.prepareStatement(sqlCmd);
+            prepareStatement(pstmt, sqlParams);
+            count = pstmt.executeUpdate(); 
+        }
+        else
+        {   // Execute a simple statement
+            stmt = conn.createStatement();
+            count = stmt.executeUpdate(sqlCmd);
+        }
+        
+        // Retrieve any auto-generated keys
+        if (genKeys!=null)
+        {   // Return Keys
+            ResultSet rs = stmt.getGeneratedKeys();
+            try {
+                while(rs.next())
+                    genKeys.set(rs.getObject(1));
+            } finally {
+                rs.close();
+            }
+        }
+        return count;
+    } finally
+    { // Close
+        close(stmt);
+    }
+}
+    
+    
+    
+
+    /**
+     * @see DBDatabaseDriver#getDDLScript(DBCmdType, DBObject, DBSQLScript)  
+     */
+    @Override
+    public boolean getDDLScript(DBCmdType type, DBObject dbo, DBSQLScript script)
+    {
+        // The Object's database must be attached to this driver
+        if (dbo==null || dbo.getDatabase().getDriver()!=this)
+            return error(Errors.InvalidArg, dbo, "dbo");
+        // Check Type of object
+        if (dbo instanceof DBDatabase)
+        { // Database
+            switch (type)
+            {
+                case CREATE:
+                    return createDatabase((DBDatabase) dbo, script);
+                case DROP:
+                    return dropObject(((DBDatabase) dbo).getSchema(), "DATABASE", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLScript."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBTable)
+        { // Table
+            switch (type)
+            {
+                case CREATE:
+                    return createTable((DBTable) dbo, script);
+                case DROP:
+                    return dropObject(((DBTable) dbo).getName(), "TABLE", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBView)
+        { // View
+            switch (type)
+            {
+                case CREATE:
+                    return createView((DBView) dbo, script);
+                case DROP:
+                    return dropObject(((DBView) dbo).getName(), "VIEW", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBRelation)
+        { // Relation
+            switch (type)
+            {
+                case CREATE:
+                    return createRelation((DBRelation) dbo, script);
+                case DROP:
+                    return dropObject(((DBRelation) dbo).getName(), "CONSTRAINT", script);
+                default:
+                    return error(Errors.NotImplemented, "getDDLCommand."+dbo.getClass().getName()+"."+String.valueOf(type));
+            }
+        } 
+        else if (dbo instanceof DBTableColumn)
+        { // Table Column
+            return alterTable((DBTableColumn) dbo, type, script);
+        } 
+        else
+        { // an invalid argument has been supplied
+            return error(Errors.InvalidArg, dbo, "dbo");
+        }
+    }
+
+    /**
+     * Overridden. Returns a timestamp that is used for record updates created by the database server.
+     * 
+     * @return the current date and time of the database server.
+     */
+    @Override
+    public java.sql.Timestamp getUpdateTimestamp(Connection conn)
+    {
+        // Default implementation
+        GregorianCalendar cal = new GregorianCalendar();
+        return new java.sql.Timestamp(cal.getTimeInMillis());
+    }
+
+    /*
+     * return the sql for creating a Database
+     */
+    private boolean createDatabase(DBDatabase db, DBSQLScript script)
+    {    	
+        // Create all Sequences
+        Iterator<DBTable> seqtabs = db.getTables().iterator();
+        while (seqtabs.hasNext())
+        {
+            DBTable table = seqtabs.next();
+            Iterator<DBColumn> cols = table.getColumns().iterator();
+            while (cols.hasNext())
+            {
+                DBTableColumn c = (DBTableColumn) cols.next();
+                if (c.getDataType() == DataType.AUTOINC)
+                {
+                    createSequence(db, c, script);
+                }
+            }
+        }
+    	
+        // Create all Tables
+        Iterator<DBTable> tables = db.getTables().iterator();
+        while (tables.hasNext())
+        {
+            if (!createTable(tables.next(), script))
+                return false;
+        }
+        // Create Relations
+        Iterator<DBRelation> relations = db.getRelations().iterator();
+        while (relations.hasNext())
+        {
+            if (!createRelation(relations.next(), script))
+                return false;
+        }
+        // Create Views
+        Iterator<DBView> views = db.getViews().iterator();
+        while (views.hasNext())
+        {
+            if (!createView(views.next(), script))
+                return false;
+        }
+        // Done
+        return true;
+    }
+    
+    private String createSequenceName(DBTableColumn c){
+    	 Object defValue = c.getDefaultValue();
+         return (defValue != null) ? defValue.toString() : c.toString();
+    }
+    
+    /**
+     * Returns true if the sequence has been created successfully.
+     * 
+     * @return true if the sequence has been created successfully
+     */
+    private boolean createSequence(DBDatabase db, DBTableColumn c, DBSQLScript script)
+    {
+    	String seqName = createSequenceName(c);
+        // createSQL
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating sequence for column ");
+        sql.append(c.getFullName());
+        sql.append(" --\r\n");
+        sql.append("CREATE SEQUENCE ");
+        db.appendQualifiedName(sql, seqName, detectQuoteName(seqName));
+        
+//        create sequence foo_id_seq;
+//        select setval('foo_id_seq', (select max(id) from foo));
+
+        
+        sql.append(" INCREMENT BY 1 START WITH 1 MINVALUE 0");
+        // executeDLL
+        return script.addStmt(sql);
+    }
+    
+    /**
+     * Returns true if the table has been created successfully.
+     * 
+     * @return true if the table has been created successfully
+     */
+    private boolean createTable(DBTable t, DBSQLScript script)
+    {
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating table ");
+        sql.append(t.getName());
+        sql.append(" --\r\n");
+        sql.append("CREATE TABLE ");
+        t.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" (");
+        boolean addSeparator = false;
+        Iterator<DBColumn> columns = t.getColumns().iterator();
+        while (columns.hasNext())
+        {
+            DBTableColumn c = (DBTableColumn) columns.next();
+            sql.append((addSeparator) ? ",\r\n   " : "\r\n   ");
+            if (appendColumnDesc(c, sql)==false)
+                continue; // Ignore and continue;
+            addSeparator = true;
+        }
+        // Primary Key
+        DBIndex pk = t.getPrimaryKey();
+        if (pk != null)
+        { // add the primary key
+            sql.append(", PRIMARY KEY (");
+            addSeparator = false;
+            // columns
+            DBColumn[] keyColumns = pk.getColumns();
+            for (int i = 0; i < keyColumns.length; i++)
+            {
+                sql.append((addSeparator) ? ", " : "");
+                keyColumns[i].addSQL(sql, DBExpr.CTX_NAME);
+                addSeparator = true;
+            }
+            sql.append(")");
+        }
+        sql.append(")");
+        // Comment?
+        String comment = t.getComment();
+        if (StringUtils.isValid(comment))
+        {   // Add the table comment
+            sql.append(" COMMENT = '");
+            sql.append(comment);
+            sql.append("'");
+        }
+        // Create the table
+        if (script.addStmt(sql) == false)
+            return false;
+        // Create other Indizes (except primary key)
+        Iterator<DBIndex> indexes = t.getIndexes().iterator();
+        while (indexes.hasNext())
+        {
+            DBIndex idx = indexes.next();
+            if (idx == pk || idx.getType() == DBIndex.PRIMARYKEY)
+                continue;
+
+            // Cretae Index
+            sql.setLength(0);
+            sql.append((idx.getType() == DBIndex.UNIQUE) ? "CREATE UNIQUE INDEX " : "CREATE INDEX ");
+            appendElementName(sql, idx.getName());
+            sql.append(" ON ");
+            t.addSQL(sql, DBExpr.CTX_FULLNAME);
+            sql.append(" (");
+            addSeparator = false;
+
+            // columns
+            DBColumn[] idxColumns = idx.getColumns();
+            for (int i = 0; i < idxColumns.length; i++)
+            {
+                sql.append((addSeparator) ? ", " : "");
+                idxColumns[i].addSQL(sql, DBExpr.CTX_NAME);
+                addSeparator = true;
+            }
+            sql.append(")");
+            // Create Index
+            if (script.addStmt(sql) == false)
+                return false;
+        }
+        // done
+        return success();
+    }
+    
+    /**
+     * Appends a table column defintion to a ddl statement
+     * @param c the column which description to append
+     * @param sql the sql builder object
+     * @return true if the column was successfully appended or false otherwise
+     */
+    private boolean appendColumnDesc(DBTableColumn c, StringBuilder sql)
+    {
+        // Append name
+        c.addSQL(sql, DBExpr.CTX_NAME);
+        sql.append(" ");
+        switch (c.getDataType())
+        {
+            case INTEGER:
+            { // Integer type
+                sql.append("INT");
+                int size = (int)c.getSize();
+                if (size>0)
+                {   // Set Integer length
+                    sql.append("(");
+                    sql.append(String.valueOf(size));
+                    sql.append(")");
+                }
+                break;
+            }    
+            case AUTOINC:
+            { // Auto increment
+                sql.append("INT");
+                
+                //String seqName = createSequenceName(c);                
+                //sql.append(" DEFAULT nextval('"+seqName+"')");
+                break;
+            }    
+            case TEXT:
+            { // Check fixed or variable length
+                int size = Math.abs((int) c.getSize());
+                if (size == 0)
+                    size = 100;
+                sql.append("VARCHAR(");
+                sql.append(String.valueOf(size));
+                sql.append(")");
+            }
+                break;
+            case CHAR:
+            { // Check fixed or variable length
+                int size = Math.abs((int) c.getSize());
+                if (size == 0)
+                    size = 1;
+                sql.append("CHAR(");
+                sql.append(String.valueOf(size));
+                sql.append(")");
+            }
+                break;
+            case DATE:
+                sql.append("DATE");
+                break;
+            case DATETIME:
+                sql.append("TIMESTAMP");
+                break;
+            case BOOL:
+                sql.append("BOOLEAN");
+                break;
+            case DOUBLE:
+                sql.append("DOUBLE");
+                break;
+            case DECIMAL:
+            { // Decimal
+                sql.append("DECIMAL(");
+                int prec = (int) c.getSize();
+                int scale = (int) ((c.getSize() - prec) * 10 + 0.5);
+                // sql.append((prec+scale).ToString());sql.append(",");
+                sql.append(String.valueOf(prec));
+                sql.append(",");
+                sql.append(String.valueOf(scale));
+                sql.append(")");
+            }
+                break;
+            case CLOB:
+                sql.append("LONGTEXT");
+                break;
+            case BLOB:
+                sql.append("BLOB");
+                if (c.getSize() > 0)
+                    sql.append(" (" + String.valueOf((long) c.getSize()) + ") ");
+                break;
+            case UNKNOWN:
+                 log.error("Cannot append column of Data-Type 'UNKNOWN'");
+                 return false;
+        }
+        // Default Value
+        if (isDDLColumnDefaults() && c.getDataType()!=DataType.AUTOINC && c.getDefaultValue()!=null)
+        {   sql.append(" DEFAULT ");
+            sql.append(getValueString(c.getDefaultValue(), c.getDataType()));
+        }
+        // Nullable
+        if (c.isRequired())
+            sql.append(" NOT NULL");
+        // Done
+        return true;
+    }
+
+    /**
+     * Returns true if the relation has been created successfully.
+     * 
+     * @return true if the relation has been created successfully
+     */
+    private boolean createRelation(DBRelation r, DBSQLScript script)
+    {
+        DBTable sourceTable = (DBTable) r.getReferences()[0].getSourceColumn().getRowSet();
+        DBTable targetTable = (DBTable) r.getReferences()[0].getTargetColumn().getRowSet();
+
+        StringBuilder sql = new StringBuilder();
+        sql.append("-- creating foreign key constraint ");
+        sql.append(r.getName());
+        sql.append(" --\r\n");
+        sql.append("ALTER TABLE ");
+        sourceTable.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" ADD CONSTRAINT ");
+        appendElementName(sql, r.getName());
+        sql.append(" FOREIGN KEY (");
+        // Source Names
+        boolean addSeparator = false;
+        DBRelation.DBReference[] refs = r.getReferences();
+        for (int i = 0; i < refs.length; i++)
+        {
+            sql.append((addSeparator) ? ", " : "");
+            refs[i].getSourceColumn().addSQL(sql, DBExpr.CTX_NAME);
+            addSeparator = true;
+        }
+        // References
+        sql.append(") REFERENCES ");
+        targetTable.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append(" (");
+        // Target Names
+        addSeparator = false;
+        for (int i = 0; i < refs.length; i++)
+        {
+            sql.append((addSeparator) ? ", " : "");
+            refs[i].getTargetColumn().addSQL(sql, DBExpr.CTX_NAME);
+            addSeparator = true;
+        }
+        // done
+        sql.append(")");
+        if (script.addStmt(sql) == false)
+            return false;
+        // done
+        return success();
+    }
+
+    /**
+     * Creates an alter table dll statement for adding, modifiying or droping a column.
+     * @param col the column which to add, modify or drop
+     * @param type the type of operation to perform
+     * @param buf buffer to which to append the sql statement to
+     * @return true if the statement was successfully appended to the buffer
+     */
+    private boolean alterTable(DBTableColumn col, DBCmdType type, DBSQLScript script)
+    {
+        StringBuilder sql = new StringBuilder();
+        sql.append("ALTER TABLE ");
+        col.getRowSet().addSQL(sql, DBExpr.CTX_FULLNAME);
+        switch(type)
+        {
+            case CREATE:
+                sql.append(" ADD ");
+                appendColumnDesc(col, sql);
+                break;
+            case ALTER:
+                sql.append(" MODIFY ");
+                appendColumnDesc(col, sql);
+                break;
+            case DROP:
+                sql.append(" DROP COLUMN ");
+                sql.append(col.getName());
+                break;
+        }
+        // done
+        return script.addStmt(sql);
+    }
+
+    /**
+     * Returns true if the view has been created successfully.
+     * 
+     * @return true if the view has been created successfully
+     */
+    private boolean createView(DBView v, DBSQLScript script)
+    {
+        // Create the Command
+        DBCommandExpr cmd = v.createCommand();
+        if (cmd==null)
+        {   // Check whether Error information is available
+            log.error("No command has been supplied for view " + v.getName());
+            if (v.hasError())
+                return error(v);
+            // No error information available: Use Errors.NotImplemented
+            return error(Errors.NotImplemented, v.getName() + ".createCommand");
+        }
+        // Make sure there is no OrderBy
+        cmd.clearOrderBy();
+
+        // Build String
+        StringBuilder sql = new StringBuilder();
+        sql.append( "CREATE VIEW ");
+        v.addSQL(sql, DBExpr.CTX_FULLNAME);
+        sql.append( " (" );
+        boolean addSeparator = false;
+        for(DBColumn c : v.getColumns())
+        {
+            if (addSeparator)
+                sql.append(", ");
+            // Add Column name
+            c.addSQL(sql, DBExpr.CTX_NAME);
+            // next
+            addSeparator = true;
+        }
+        sql.append(")\r\nAS\r\n");
+        cmd.addSQL( sql, DBExpr.CTX_DEFAULT);
+        // done
+        return script.addStmt(sql.toString());
+    }
+    
+    /**
+     * Returns true if the object has been dropped successfully.
+     * 
+     * @return true if the object has been dropped successfully
+     */
+    private boolean dropObject(String name, String objType, DBSQLScript script)
+    {
+        if (name == null || name.length() == 0)
+            return error(Errors.InvalidArg, name, "name");
+        // Create Drop Statement
+        StringBuilder sql = new StringBuilder();
+        sql.append("DROP ");
+        sql.append(objType);
+        sql.append(" ");
+        appendElementName(sql, name);
+        return script.addStmt(sql);
+    }
+
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/package.html
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/package.html?rev=742097&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/package.html (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/postgresql/package.html Sun Feb  8 14:11:24 2009
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<!-- 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ --> 
+<html>
+<head>
+</head>
+<body>
+
+This package contains classes necessary to support the PostgreSQL database system.
+
+</body></html>
\ No newline at end of file