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 do...@apache.org on 2008/08/06 10:47:43 UTC

svn commit: r683173 [4/10] - in /incubator/empire-db/trunk/core/Empire-db: ./ .settings/ bin/ lib/ src/ src/META-INF/ src/org/ src/org/apache/ src/org/apache/empire/ src/org/apache/empire/commons/ src/org/apache/empire/data/ src/org/apache/empire/data/...

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBCommandExpr.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBCommandExpr.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBCommandExpr.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBCommandExpr.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,531 @@
+/*
+ * ESTEAM Software GmbH
+ */
+package org.apache.empire.db;
+
+// java
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.Options;
+import org.apache.empire.data.DataType;
+import org.w3c.dom.Element;
+
+
+/**
+ * This abstract class handles the creation of the SQL-Commands.
+ * There are inner classes to construct different SQL-Commands.
+ * <P>
+ * 
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de</A>
+ */
+public abstract class DBCommandExpr extends DBExpr
+{
+    // Internal Classes
+    protected static class DBCmdQuery extends DBRowSet
+    {
+        private DBCommandExpr cmd;
+
+        /**
+         * Creates a new DBCmdQueryObject
+         */
+        public DBCmdQuery(DBCommandExpr cmd, DBColumnExpr[] colList)
+        { // Set the column expressions
+            super(cmd.getDatabase());
+            this.cmd = cmd;
+            // Add Expressions to vector
+            for (int i = 0; i < colList.length; i++)
+                columns.add(colList[i].getUpdateColumn());
+        }
+
+        /** Not applicable - returns null */
+        @Override
+        public String getName()
+        {
+            return null;
+        }
+
+        /** Not applicable - returns null */
+        @Override
+        public String getAlias()
+        {
+            return null;
+        }
+
+        /**
+         * @see org.apache.empire.db.DBExpr#addReferencedColumns(Set)
+         */
+        @Override
+        public void addReferencedColumns(Set<DBColumn> list)
+        {
+            list.addAll(columns);
+        }
+
+        /**
+         * Creates the SQL-Command adds the select statement into the SQL-Command.
+         * 
+         * @param buf the SQL-Command
+         * @param context the current SQL-Command context
+         */
+        @Override
+        public void addSQL(StringBuilder buf, long context)
+        {
+            buf.append("(");
+            buf.append(cmd.getSelect());
+            buf.append(")");
+        }
+
+        /**
+         * Prints the error message: ERR_NOTSUPPORTED.
+         * 
+         * @return null
+         */
+        @Override
+        public DBColumn[] getKeyColumns()
+        {
+            error(Errors.NotSupported, "getKeyColumns");
+            return null;
+        }
+
+        /**
+         * Prints the error message: ERR_NOTSUPPORTED.
+         * 
+         * @return null
+         */
+        @Override
+        public Object[] getRecordKey(DBRecord rec)
+        {
+            error(Errors.NotSupported, "getRecordKey");
+            return null;
+        }
+
+        /** Returns the error message: ERR_NOTSUPPORTED */
+        @Override
+        public boolean initRecord(DBRecord rec, Object[] keyValues)
+        {
+            return error(Errors.NotSupported, "initRecord");
+        }
+
+        /** Returns the error message: ERR_NOTSUPPORTED */
+        @Override
+        public boolean createRecord(DBRecord rec, Connection conn)
+        {
+            return error(Errors.NotSupported, "addRecord");
+        }
+
+        /** Returns the error message: ERR_NOTSUPPORTED */
+        @Override
+        public boolean readRecord(DBRecord rec, Object[] keys, Connection conn)
+        {
+            return error(Errors.NotSupported, "getRecord");
+        }
+
+        /** Returns the error message: ERR_NOTSUPPORTED */
+        @Override
+        public boolean updateRecord(DBRecord rec, Connection conn)
+        {
+            return error(Errors.NotSupported, "updateRecord");
+        }
+
+        /** Returns the error message: ERR_NOTSUPPORTED */
+        @Override
+        public boolean deleteRecord(Object[] keys, Connection conn)
+        {
+            return error(Errors.NotSupported, "deleteRecord");
+        }
+    }
+
+    /**
+     * This class wrapps a column of sql command in a special command column object. 
+     * @author ESTEAM
+     */
+    protected static class DBCmdColumn extends DBColumn
+    {
+        private DBColumnExpr expr;
+
+        /**
+         * Constructs a new DBCmdColumn object set the specified parameters to this object
+         */
+        public DBCmdColumn(DBRowSet query, DBColumnExpr expr)
+        { // call base
+            super(query, expr.getName());
+            // set Expression
+            this.expr = expr;
+        }
+
+        /**
+         * create the SQL-Command set the expression name to the SQL-Command
+         * 
+         * @param buf the SQL-Command
+         * @param context the current SQL-Command context
+         */
+        @Override
+        public void addSQL(StringBuilder buf, long context)
+        { // append UNQUALIFIED name only!
+            buf.append(expr.getName());
+        }
+
+        /**
+         * Returns the data type of the DBColumnExpr object.
+         * 
+         * @return the data type
+         */
+        @Override
+        public DataType getDataType()
+        {
+            return expr.getDataType();
+        }
+
+        /**
+         * Not applicable - always returns 0.
+         */
+        @Override
+        public double getSize()
+        {
+            return 0;
+        }
+
+        /**
+         * Not applicable - always returns true
+         */
+        @Override
+        public boolean isReadOnly()
+        {
+            return true; // expr.isReadOnly();
+        }
+
+        /**
+         * Checks whether the column is mandatory.
+         * 
+         * @return true if the column is mandatory or false otherwise
+         */
+        @Override
+        public boolean isRequired()
+        {
+            return false;
+        }
+
+        /**
+         * Get Attributes of underlying table column.
+         */
+        @Override
+        public Object getAttribute(String name)
+        {
+            if (attributes != null && attributes.containsKey(name))
+                return attributes.get(name);
+            // Otherwise ask expression
+            DBColumn column = expr.getUpdateColumn();
+            if (column!=null)
+                return column.getAttribute(name);
+            return null;
+        }
+
+        /**
+         * Get Options of underlying table column.
+         */
+        @Override
+        public Options getOptions()
+        {
+            if (options != null)
+                return options;
+            // Otherwise ask expression
+            DBColumn column = expr.getUpdateColumn();
+            if (column!=null)
+                return column.getOptions();
+            return null;
+        }
+
+        /**
+         * Not applicable - always returns true.
+         */
+        @Override
+        public boolean checkValue(Object value)
+        {
+            return true;
+        }
+
+        /**
+         * Adds the expression definition to the xml element.
+         */
+        @Override
+        public Element addXml(Element parent, long flags)
+        {
+            return expr.addXml(parent, flags);
+        }
+
+    }
+
+    protected static class DBOrderByInfo extends DBExpr
+    {
+        public DBColumnExpr expr;
+        public boolean      desc;
+
+        /**
+         * Construct a new DBOrderByInfo object set the specified
+         * parameters to this object.
+         */
+        public DBOrderByInfo(DBColumnExpr expr, boolean desc)
+        {
+            this.expr = expr;
+            this.desc = desc;
+        }
+
+        /** Returns the current database object */
+        @Override
+        public DBDatabase getDatabase()
+        {
+            return expr.getDatabase();
+        }
+
+        /**
+         * @see org.apache.empire.db.DBExpr#addColumns(List)
+         */
+        @Override
+        public void addReferencedColumns(Set<DBColumn> list)
+        {
+            expr.addReferencedColumns(list);
+        }
+
+        /**
+         * Creates the SQL-Command set "DESC" command after the order by statement.
+         * 
+         * @param buf the SQL-Command
+         * @param context the current SQL-Command context
+         */
+        @Override
+        public void addSQL(StringBuilder buf, long context)
+        { // Set SQL-Order By
+            expr.addSQL(buf, context);
+            if (desc)
+                buf.append(" DESC");
+        }
+    }
+
+    // Members
+    protected DBCmdQuery          cmdQuery = null;
+    protected List<DBOrderByInfo> orderBy  = null;
+
+    /** Constructs an empty DBCommandExpr object */
+    public DBCommandExpr()
+    {
+        // Default Construtor
+    }
+
+    // get Select SQL
+    public abstract boolean isValid();
+
+    public abstract boolean getSelect(StringBuilder buf);
+
+    public abstract DBColumnExpr[] getSelectExprList();
+
+    public DBColumnExpr getCmdColumn(DBColumnExpr col)
+    {
+        // Check the Instance of col
+        if ((col instanceof DBCmdColumn))
+        { // Check Owner
+            DBCmdColumn c = (DBCmdColumn) col;
+            if (c.getRowSet() == cmdQuery)
+                return col; // it's aready a command column
+            // extract the expression
+            col = c.expr;
+        }
+        // Check if we already have a Command Query
+        if (cmdQuery == null)
+            cmdQuery = new DBCmdQuery(this, getSelectExprList());
+        // create a command column
+        return new DBCmdColumn(cmdQuery, col);
+    }
+
+    public DBColumnExpr getCmdColumn(int i)
+    {
+        DBColumnExpr[] list = getSelectExprList();
+        if (i >= list.length)
+            return null;
+        return getCmdColumn(list[i]);
+    }
+
+    /**
+     * returns an SQL select command for querying records.
+     * @return the SQL-Command
+     */
+    public String getSelect()
+    {
+        StringBuilder buf = new StringBuilder();
+        if (getSelect(buf) == false)
+        {
+            log.error(getErrorMessage());
+            return null;
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Internally used to build a string from a list of database expressions
+     * @param buf the sql target buffer
+     * @param list list of database objects
+     * @param context the sql command context
+     * @param separator string to use as separator between list items
+     */
+    protected void addListExpr(StringBuilder buf, List<? extends DBExpr> list, long context, String separator)
+    {
+        for (int i = 0; i < list.size(); i++)
+        { // Selectfelder zusammenbauen
+            if (i > 0)
+                buf.append(separator);
+            list.get(i).addSQL(buf, context);
+        }
+    }
+
+    /**
+     * Creates the SQL-Command.
+     * 
+     * @param buf the SQL-Command
+     * @param context the current SQL-Command context
+     */
+    @Override
+    public void addSQL(StringBuilder buf, long context)
+    {
+        buf.append("(");
+        buf.append(getSelect());
+        buf.append(")");
+    }
+
+    /**
+     * Constructs a new DBCombinedCmd object with this object,
+     * the key word= "UNION" and the selected DBCommandExpr.
+     * 
+     * @see org.apache.empire.db.DBCombinedCmd
+     * @param other the secend DBCommandExpr
+     * @return the new DBCombinedCmd object
+     */
+    // Combinations
+    public DBCommandExpr union(DBCommandExpr other)
+    {
+        return new DBCombinedCmd(this, "UNION", other);
+    }
+
+    /**
+     * Constructs a new DBCombinedCmd object with this object,
+     * the key word= "INTERSECT" and the selected DBCommandExpr.
+     * 
+     * @param other the secend DBCommandExpr
+     * @return the new DBCombinedCmd object
+     */
+    public DBCommandExpr intersect(DBCommandExpr other)
+    {
+        return new DBCombinedCmd(this, "INTERSECT", other);
+    }
+
+    /**
+     * Clears the list of order by expressions.
+     */
+    public void clearOrderBy()
+    {
+        orderBy = null;
+    }
+
+    /**
+     * Creates a new DBOrderByInfo object and add it to the Vector 'orderBy'.
+     * 
+     * @param expr the DBColumnExpr object
+     * @param desc if true, the results from select statement will sort top down
+     */
+    public void orderBy(DBColumnExpr expr, boolean desc)
+    {
+        if (orderBy == null)
+            orderBy = new ArrayList<DBOrderByInfo>();
+        // Add order by excpression
+        orderBy.add(new DBOrderByInfo(expr, desc));
+    }
+
+    /**
+     * This helper function calls the method orderBy(DBColumnExpr, boolean)
+     * and sets the second parameter to false,creates a new
+     * DBOrderByInfo object and adds it to the Vector 'orderBy'.
+     * 
+     * @see org.apache.empire.db.DBCommandExpr#orderBy(DBColumnExpr, boolean)
+     */
+    public void orderBy(DBColumnExpr expr)
+    {
+        orderBy(expr, false);
+    }
+
+    /**
+     * Create the insert into SQL-Command which copies data
+     * from a select statement to a destination table.
+     * 
+     * @return the insert into SQL-Command
+     */
+    protected String getInsertInto(DBTable table, DBColumnExpr[] select, List<DBColumnExpr> columns)
+    {
+        if (select == null)
+        { // invalid Object
+            error(Errors.ObjectNotValid, getClass().getName());
+            return null;
+        }
+        StringBuilder buf = new StringBuilder("INSERT INTO ");
+        table.addSQL(buf, CTX_FULLNAME);
+        // destination columns
+        if (columns != null && columns.size() > 0)
+        { // Check Count
+            if (columns.size() != select.length)
+            {
+                error(Errors.InvalidArg, columns, "columns");
+                return null;
+            }
+            // Append Names
+            buf.append(" (");
+            addListExpr(buf, columns, CTX_NAME, ", ");
+            buf.append(")");
+        }
+        // append select statement
+        buf.append("\r\n");
+        getSelect(buf);
+        // done
+        return buf.toString();
+    }
+
+    /**
+     * Create the insert into SQL-Command which copies
+     * data from a select statement to a destination table.
+     * 
+     * @return the insert into SQL-Command
+     */
+    public final String getInsertInto(DBTable table, List<DBColumnExpr> columns)
+    {
+        return getInsertInto(table, getSelectExprList(), columns);
+    }
+
+    /**
+     * Create the insert into SQL-Command which copies
+     * data from a select statement to a destination table.
+     * 
+     * @return the insert into SQL-Command
+     */
+    public final String getInsertInto(DBTable table)
+    {
+        DBColumnExpr[] select = getSelectExprList();
+        if (select == null || select.length < 1)
+        {
+            error(Errors.ObjectNotValid, getClass().getName());
+            return null;
+        }
+        // Match Columns
+        List<DBColumnExpr> inscols = new ArrayList<DBColumnExpr>(select.length);
+        for (int i = 0; i < select.length; i++)
+        {
+            DBColumnExpr expr = select[i];
+            DBColumn col = table.getColumn(expr.getName());
+            if (col == null)
+            { // Cannot find a match for that name
+                log.warn("InsertInto: Column " + expr.getName() + " not found!");
+                col = table.getColumn(i);
+            }
+            inscols.add(col);
+        }
+        return getInsertInto(table, select, inscols);
+    }
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabase.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabase.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabase.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabase.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,1112 @@
+/*
+ * ESTEAM Software GmbH
+ */
+package org.apache.empire.db;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.Options;
+import org.apache.empire.data.DataType;
+import org.apache.empire.db.expr.column.DBValueExpr;
+
+
+/**
+ * This abstract class is the applicaton's interface for a particular database schema.
+ * <P>
+ * It provides access to the various database objects such als tables, views and relations.
+ * <P>
+ * It also provides methods to execute DQL and DML SQL-commands.
+ * <P>
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ */
+public abstract class DBDatabase extends DBObject
+{
+    /**
+     * This class represents the database systems current date and time.
+     * <P>
+     * There is no need to use this class directly.<BR>
+     * Instead you can use the constant {@link DBDatabase#SYSDATE}
+     */
+    public static final class DBSystemDate 
+    {   
+        // System Date Class for internal use
+        private DBSystemDate() 
+        { 
+            /* no instances */ 
+        }
+        @Override
+        public String toString()
+        {   return "sysdate";
+        }
+    }
+    
+    // Database specific date
+    public static final DBSystemDate SYSDATE  = new DBSystemDate();
+    
+    public static final String EMPTY_STRING = "\0"; // will be replaced by ''
+
+    // Logger
+    private static final Log log = LogFactory.getLog(DBDatabase.class);
+
+    /** the database schema * */
+    protected String           schema    = null; // database schema name
+    protected String           linkName  = null; // database link name
+    protected List<DBTable>    tables    = new ArrayList<DBTable>();
+    protected List<DBRelation> relations = new ArrayList<DBRelation>();
+    protected List<DBView>     views     = new ArrayList<DBView>();
+    protected DBDatabaseDriver driver    = null;
+
+    /**
+     * Constructs a new DBDatabase object set the variable 'schema' = null.
+     */
+    public DBDatabase()
+    {
+        this.schema = null;
+    }
+
+    /**
+     * Constructs a new DBDatabase object and sets the specified schema object.
+     * 
+     * @param schema the database schema
+     */
+    public DBDatabase(String schema)
+    {
+        this.schema = schema;
+    }
+
+    /**
+     * Constructs a new DBDatabase object and sets the specified schema object.
+     * 
+     * @param schema the database schema
+     * @param linkName the database link name
+     */
+    public DBDatabase(String schema, String linkName)
+    {
+        this.schema = schema;
+        this.linkName = linkName;
+    }
+
+    // ------------------------------
+    // -- Database methods --
+    // ------------------------------
+
+    /**
+     * Returns the driver for this database.
+     * 
+     * @return Returns the driver for this database
+     */
+    public DBDatabaseDriver getDriver()
+    {
+        return driver;
+    }
+
+    /**
+     * Sets the database driver for this database. <br>
+     * ------ DO NOT CALL DIRECTLY! ------- <br>
+     * This function is called internally by DBDatabaseDriver:openDatabase()
+     */
+    public boolean open(DBDatabaseDriver driver, Connection conn)
+    {
+        // Close Database if already open
+        if (isOpen())
+            close(conn);
+        // Attach to driver
+        if (driver.attachDatabase(this, conn)==false)
+            return error(driver);
+        // set new driver
+        this.driver = driver;
+        return success();
+    }
+
+    /**
+     * closes this database object by detaching it from the driver
+     * this is a shortcut for calling
+     *  getDriver().closeDatabase(db, conn) 
+     */
+    public void close(Connection conn)
+    {
+        if (driver != null)
+            driver.detachDatabase(this, conn);
+        // No diver
+        this.driver = null;
+    }
+
+    /**
+     * Creates a DDL Script for creating all database objects on the target database.<BR>
+     * This function may be called even if the database has not been previously opened.<BR>
+     * <P>
+     * Once the database is open you can use getDriver().getDLLCommand()
+     * to create, alter or delete other database objects<BR>
+     * <P>
+     * @param driver The driver for which to create a DDL Script
+     * @return the DLL script for creating the entire database schema
+     */
+    public synchronized boolean getCreateDDLScript(DBDatabaseDriver driver, DBSQLScript script)
+    {
+        DBDatabaseDriver prevDriver = this.driver;
+        try {
+            // Set driver
+            if (this.driver!=null && this.driver!=driver && driver!=null)
+            {   // The database belongs to a different driver
+                return error(Errors.Internal, "The database is attached to a different driver.");
+            }
+            // Temporarily change driver
+            if (this.driver== null)
+                this.driver = driver;
+            // Get DDL Command
+            if (driver.getDDLScript(DBCmdType.CREATE, this, script)==false)
+            {   // DDL-creation failed 
+                return error(driver);
+            }
+            return success();
+            
+        } finally {
+            this.driver = prevDriver; 
+        }
+    }
+    
+    /**
+     * @see org.apache.empire.db.DBObject#getDatabase()
+     */
+    @Override
+    public DBDatabase getDatabase()
+    {
+        return this;
+    }
+
+    /**
+     * Returns the schema for SQL statements.
+     * 
+     * @return the schema
+     */
+    public String getSchema()
+    {
+        return schema;
+    }
+
+    /**
+     * Sets the schema for SQL statements.
+     */
+    public boolean setSchema(String schema)
+    {   // Database must not be open so far
+        if (driver != null)
+            return error(Errors.NoAccess);
+        // Set Schema 
+        this.schema = schema;
+        return success();
+    }
+
+    /**
+     * Returns the schema-prefix for SQL statements e.g. "SCHEMA."
+     * or empty string if no schema is defined.
+     * 
+     * @return the schema-prefix
+     */
+    public String getSchemaPrefix()
+    {
+        if (schema == null)
+        {
+            return "";
+        }
+        return schema + ".";
+    }
+
+    /**
+     * Returns the database link name.
+     * 
+     * @return the name of the database link
+     */
+    public String getLinkName()
+    {
+        return linkName;
+    }
+
+    /**
+     * Sets the name of the database link used to identify objects.
+     * 
+     * @param linkName the database link name
+     */
+    public boolean setLinkName(String linkName)
+    {   // Database must not be open so far
+        if (driver != null)
+            return error(Errors.NoAccess);
+        // Set Link 
+        this.linkName = linkName;
+        return success();
+    }
+
+    /**
+     * Returns the full qualified object name including schema prefix
+     * and database link postfix (if any).
+     * 
+     * @param name the object's name
+     * 
+     * @return the qualified object name
+     */
+    public String getQualifiedName(String name)
+    {
+        StringBuilder buf = new StringBuilder();
+        appendQualifiedName(buf, name);
+        return buf.toString();
+    }
+    
+    /**
+     * Adds a full qualified object name including schema prefix
+     * and database link postfix (if any).
+     * to the string buffer suppield
+     * 
+     * @param buf the string buffer to which to append the qualified object name
+     * @param name the object's name
+     */
+    public void appendQualifiedName(StringBuilder buf, String name)
+    {
+        // Schema
+        if (schema != null && driver!=null)
+        { // Add Schema
+            buf.append(schema);
+            buf.append(".");
+        }
+        buf.append(name);
+        // Database Link
+        if (linkName!=null && driver!=null)
+        { // Add Schema
+            buf.append(driver.getSQLPhrase(DBDatabaseDriver.SQL_DATABASE_LINK));
+            buf.append(linkName);
+        }
+    }
+    
+    /**
+     * Creates and returns a value object for the database systems
+     * current date and time.
+     * 
+     * @return a DBValueExpr object
+     */
+    public DBValueExpr getSystemDateExpr()
+    {
+        return new DBValueExpr(this, SYSDATE, DataType.DATETIME);
+    }
+
+    /**
+     * Creates and returns a value object for the given string value.
+     * 
+     * @param value the String value
+     * @return the new DBValueExpr object
+     */
+    public DBValueExpr getValueExpr(String value)
+    {
+        return new DBValueExpr(this, value, DataType.TEXT);
+    }
+
+    /**
+     * Creates and returns a value object for the given boolean value.
+     * 
+     * @param value the Boolean value
+     * @return the new DBValueExpr object
+     */
+    public DBValueExpr getValueExpr(boolean value)
+    {
+        return new DBValueExpr(this, value, DataType.BOOL);
+    }
+
+    /**
+     * Creates and returns a value object for the given integer value.
+     * 
+     * @param value the int value
+     * @return the new DBValueExpr object
+     */
+    public DBValueExpr getValueExpr(int value)
+    {
+        return new DBValueExpr(this, new Integer(value), DataType.INTEGER);
+    }
+
+    /**
+     * Creates and returns a value object for the given long value.
+     * 
+     * @param value the long value
+     * @return the new DBValueExpr object
+     */
+    public DBValueExpr getValueExpr(long value)
+    {
+        return new DBValueExpr(this, new Long(value), DataType.INTEGER);
+    }
+
+    /**
+     * Creates and returns a value object for the given value.
+     * 
+     * @param value the value
+     * @param dataType the database systems data type used for this value
+     * @return the new DBValueExpr object
+     */
+    public DBValueExpr getValueExpr(Object value, DataType dataType)
+    {
+        return new DBValueExpr(this, value, dataType);
+    }
+
+    /**
+     * Adds a DBTable object to list of database tables.<BR>
+     * There is usually no need to call this function directly 
+     * since it is internally called from the DBTable's constructor.
+     * <P> 
+     * @param table the DBTable object
+     * @return true if successful
+     */
+    public boolean addTable(DBTable table)
+    { // find column by name
+        if (table == null || table.getDatabase() != this)
+            return error(Errors.InvalidArg, table, "table");
+        if (tables.contains(table)==true)
+            return error(Errors.ItemExists, table.getName());
+        // Check for second instances
+        DBTable existing = getTable(table.getName()); 
+        if (existing!=null)
+        {   // Check classes
+            if (existing.getClass().equals(table.getClass()))
+                return success(); // Ingore other instances 
+            // Table exists with different class
+            return error(Errors.ItemExists, table.getName());
+        }
+        // add now
+        tables.add(table);
+        return true;
+    }
+
+    /**
+     * Returns the tables which has been defined in the database.
+     * 
+     * @return db tables.
+     */
+    public List<DBTable> getTables()
+    {
+        return tables;
+    }
+
+    /**
+     * Finds a DBTable object by name.
+     * <P>
+     * @param name the name of the table
+     * @return the located DBTable object
+     */
+    public DBTable getTable(String name)
+    { // find table by name
+        for (int i = 0; i < tables.size(); i++)
+        { // search for the table
+            DBTable tab = tables.get(i);
+            if (tab.getName().equalsIgnoreCase(name))
+                return tab;
+        }
+        return null;
+    }
+
+    /**
+     * Adds a foreign key relation to the database.
+     * <P>
+     * @param reference a reference for a source and target column pair
+     * @return true if the relations was successfully created.
+     */
+    public final boolean addRelation(DBRelation.DBReference reference)
+    {
+        String table = reference.getSourceColumn().getRowSet().getName();
+        String col1 = reference.getSourceColumn().getName();
+        // Create Relation Name
+        String name = table.substring(0, Math.min(table.length(), 14)) + "_" + col1.substring(0, Math.min(col1.length(), 12))
+        			  + "_FK";
+        return addReleation(name, new DBRelation.DBReference[] { reference });
+    }
+
+    /**
+     * Add a foreign key relation to the database.
+     * 
+     * @param ref1 a reference for a source and target column pair
+     * @param ref2 a reference for a source and target column pair
+     * @return true if the relations was successfully created.
+     */
+    public final boolean addRelation(DBRelation.DBReference ref1, DBRelation.DBReference ref2)
+    {
+        String table = ref1.getSourceColumn().getRowSet().getName();
+        String col1 = ref1.getSourceColumn().getName();
+        String col2 = ref2.getSourceColumn().getName();
+        // Create Relation Name
+        String name = table.substring(0, Math.min(table.length(), 9))
+                    + "_" + col1.substring(0, Math.min(col1.length(), 9))
+                    + "_" + col2.substring(0, Math.min(col2.length(), 9)) + "_FK";
+        return addReleation(name, new DBRelation.DBReference[] { ref1, ref2 });
+    }
+
+    /**
+     * Adds a foreign key relation to the database.
+     * 
+     * @param references a list of source and target column pairs
+     * @return true if the relations was successfully created.
+     */
+    public boolean addReleation(String name, DBRelation.DBReference[] references)
+    {
+        // Add a Relation
+        DBRelation relation = new DBRelation(this, name, references);
+        if (relations.contains(relation))
+            return error(Errors.ItemExists, name); // Itemn already exists
+        // Add Reference column to table
+        for (DBRelation.DBReference ref : references)
+        {   // add the reference column
+            DBRowSet rset = ref.getSourceColumn().getRowSet();
+            rset.addColumnReference(ref.getSourceColumn(), ref.getTargetColumn());
+        }
+        // OK
+        relations.add(relation);
+        return true;
+    }
+
+    /**
+     * Returns the tables which has been defined in the database.
+     * 
+     * @return db tables.
+     */
+    public List<DBRelation> getRelations()
+    {
+        return relations;
+    }
+
+    /**
+     * Adds a DBView object to list of database views.<BR>
+     * There is usually no need to call this function directly 
+     * since it is internally called from the DBView's constructor.
+     * <P> 
+     * @param view the DBView object
+     * @return true if successful
+     */
+    public boolean addView(DBView view)
+    { // find column by name
+        if (view == null || view.getDatabase() != this)
+            return error(Errors.InvalidArg, view, "view");
+        if (views.contains(view) == true)
+            return error(Errors.ItemExists, view.getName());
+        // add now
+        views.add(view);
+        return true;
+    }
+
+    /**
+     * Returns the tables which has been defined in the database.
+     * 
+     * @return db tables.
+     */
+    public List<DBView> getViews()
+    {
+        return views;
+    }
+
+    /**
+     * Finds a DBView object by name.
+     * 
+     * @param name the name of the view
+     * @return the located DBTable object
+     */
+    public DBView getView(String name)
+    { // find table by name
+        for (int i = 0; i < views.size(); i++)
+        { // search for the table
+            DBView view = views.get(i);
+            if (view.getName().equalsIgnoreCase(name))
+                return view;
+        }
+        return null;
+    }
+
+    /**
+     * Indicates whether the database has been opened.
+     * 
+     * @return The name of the encoding or null if a single byte encoding is used.
+     */
+    public boolean isOpen()
+    {
+        return (driver != null);
+    }
+
+    /**
+     * @return true if the database has been opened or false otherwise 
+     */
+    protected boolean checkOpen()
+    {
+        if (driver == null)
+            return error(DBErrors.DatabaseNotOpen);
+        return success();
+    }
+    
+    /**
+     * Creates a new Command object for this database
+     * 
+     * @return the command obejct.
+     */
+    public DBCommand createCommand()
+    {
+        if (checkOpen()==false)
+            return null;
+        return driver.createCommand(this);
+    }
+
+    /**
+     * Returns a timestamp that is used for record updates.
+     * 
+     * @return the current date and time.
+     */
+    public java.sql.Timestamp getUpdateTimestamp(Connection conn)
+    {
+        // Default implementation
+        if (checkOpen()==false)
+            return null;
+        // Ask driver
+        return driver.getUpdateTimestamp(conn);
+    }
+
+    // Sequences
+    public Object getNextSequenceValue(String seqName, Connection conn)
+    {
+        // Default implementation
+        if (checkOpen()==false)
+            return null;
+        // Ask driver
+        return driver.getNextSequenceValue(this, seqName, 1, conn);
+    }
+
+    /**
+     * Returns the value of the first row/column of a sql-query as an object.
+     * 
+     * @param sqlCmd the SQL-Command
+     * @param conn a valid connection to the database.
+     * @exception java.sql.SQLException if a database access error occurs
+     * @return the first column in the current row as a Java object
+     */
+
+    public Object querySingleValue(String sqlCmd, Connection conn)
+    {
+        ResultSet rs = null;
+        try
+        {	// Check Open
+            if (checkOpen()==false)
+                return null;
+            // Debug
+            long start = System.currentTimeMillis();
+            if (log.isDebugEnabled())
+                log.debug("executing: " + sqlCmd);
+            // Get the next Value
+            rs = driver.executeQuery(sqlCmd, null, false, conn);
+            if (rs == null)
+            { // Error
+                error(driver);
+                return null;
+            }
+            // Check Result
+            if (rs.next() == false)
+            {
+                //log.warn("querySingleValue returned no result : Stack", new Exception("Just to show the stack"));
+                log.debug("querySingleValue returned no result");
+                error(DBErrors.QueryNoResult, sqlCmd);
+                return null;
+            }
+            // No Value
+            clearError();
+            Object result = rs.getObject(1);
+            if (log.isDebugEnabled())
+	            log.debug("querySingleValue complete in " + String.valueOf(System.currentTimeMillis() - start) + " ms -> value="
+	                        + String.valueOf(result));
+            return result;
+        } catch (SQLException e) 
+        {
+            log.error("querySingleValue exception: " + e.toString());
+            error(DBErrors.QueryFailed, e);
+            return null;
+        } finally
+        { // Cleanup
+            closeResultSet(rs);
+        }
+    }
+
+    /**
+     * Returns the value of the first row/column of a sql-query as an int.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param defVal the default value if no value was returned by the database
+     * @param conn a valid connection to the database.
+     * @return the result as a int value, if no result the int value 0
+     */
+    public int querySingleInt(String sqlCmd, int defVal, Connection conn)
+    { 
+        Object value = querySingleValue(sqlCmd, conn);
+        return ((value != null) ? Integer.parseInt(value.toString()) : defVal);
+    }
+
+    /**
+     * Returns the value of the first row/column of a sql-query as an int.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return the result as a int value, if no result the int value 0
+     */
+    public final int querySingleInt(String sqlCmd, Connection conn)
+    { 
+        return querySingleInt(sqlCmd, 0, conn);
+    }
+    
+    /**
+     * Returns the value of the first row/column of a sql-query as a long.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return the result as a long value, if no result the long value 0
+     */
+    public long querySingleLong(String sqlCmd, long defVal, Connection conn)
+    { 
+        Object value = querySingleValue(sqlCmd, conn);
+        return ((value != null) ? Long.parseLong(value.toString()) : defVal);
+    }
+
+    /**
+     * Returns the value of the first row/column of a sql-query as a long.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return the result as a long value, if no result the long value 0
+     */
+    public final long querySingleLong(String sqlCmd, Connection conn)
+    { 
+        return querySingleLong(sqlCmd, 0, conn);
+    }
+    
+    /**
+     * Returns the value of the first row/column of a sql-query as a double.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return the result as a long value, if no result the long value 0
+     */
+    public double querySingleDouble(String sqlCmd, double defVal, Connection conn)
+    { 
+        Object value = querySingleValue(sqlCmd, conn);
+        return ((value != null) ? Double.parseDouble(value.toString()) : defVal);
+    }
+
+    /**
+     * Returns the value of the first row/column of a sql-query as a double.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return the result as a long value, if no result the long value 0
+     */
+    public final double querySingleDouble(String sqlCmd, Connection conn)
+    { 
+        return querySingleDouble(sqlCmd, 0.0, conn);
+    }
+    
+    /**
+     * Returns the value of the first row/column of a sql-query as a string.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param defVal the default value if no value was returned by the database
+     * @param conn a valid connection to the database.
+     * @return the result as a String object, if no result a emtpy String
+     */
+    public String querySingleString(String sqlCmd, String defVal, Connection conn)
+    { 
+        Object value = querySingleValue(sqlCmd, conn);
+        return ((value != null) ? value.toString() : defVal);
+    }
+    
+    /**
+     * Returns the value of the first row/column of a sql-query as a string.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return the result as a String object, if no result a emtpy String
+     */
+    public final String querySingleString(String sqlCmd, Connection conn)
+    { 
+        return querySingleString(sqlCmd, "", conn);
+    }
+    
+    /**
+     * Returns a one dimensional array from an sql query.
+     * The array is filled with the values of the first column.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return a list of the values of the first column of an sql query 
+     */
+    public <T> List<T> querySimpleList(Class<T> c, String sqlCmd, Connection conn)
+    {   // Execute the  Statement
+        if (checkOpen()==false)
+            return null;
+        // Debug
+        ResultSet rs = null;
+        try
+        {	// Check Open
+            if (checkOpen()==false)
+                return null;
+            // Debug
+            long start = System.currentTimeMillis();
+            if (log.isInfoEnabled())
+                log.info("executing: " + sqlCmd);
+            // Get the next Value
+            rs = driver.executeQuery(sqlCmd, null, false, conn);
+            if (rs == null)
+            { // Error
+                error(driver);
+                return null;
+            }
+            // Check Result
+            List<T> result = new ArrayList<T>();
+            while (rs.next())
+            {
+                T item = ObjectUtils.convert(c, rs.getObject(1));
+                result.add(item);
+            }
+            // No Value
+            if (log.isInfoEnabled())
+                log.info("querySimpleList retured "+String.valueOf(result.size())+" items. Query completed in " + String.valueOf(System.currentTimeMillis() - start) + " ms");
+            clearError();
+            return result;
+        } catch (ClassCastException e) 
+        {   
+            log.error("querySingleValue cast exception: ", e);
+            error(Errors.Exception, e);
+            return null;
+        } catch (SQLException e) 
+        {
+            log.error("querySimpleList exception: ", e);
+            error(DBErrors.QueryFailed, e);
+            return null;
+        } finally
+        { // Cleanup
+            closeResultSet(rs);
+        }
+    }
+
+    /**
+     * Returns a one dimensional array from an sql query.
+     * The array is filled with the values of the first column.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return a list of values of type Object 
+     */
+    public List<Object> querySimpleList(String sqlCmd, Connection conn)
+    {   // Execute the  Statement
+        return querySimpleList(Object.class, sqlCmd, conn);
+    }
+    
+    /**
+     * Returns a list of key value pairs from an sql query.
+     * The opton list is filled with the values of the first and second column.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return an Options object containing a set a of values and their corresponding names 
+     */
+    public Options queryOptionList(String sqlCmd, Connection conn)
+    {   // Execute the  Statement
+        if (checkOpen()==false)
+            return null;
+        // Debug
+        ResultSet rs = null;
+        try
+        {   // Check Open
+            if (checkOpen()==false)
+                return null;
+            // Debug
+            long start = System.currentTimeMillis();
+            if (log.isInfoEnabled())
+                log.info("executing: " + sqlCmd);
+            // Get the next Value
+            rs = driver.executeQuery(sqlCmd, null, false, conn);
+            if (rs == null)
+            { // Error
+                error(driver);
+                return null;
+            }
+            if (rs.getMetaData().getColumnCount()<2)
+            {   // Not enough columns
+                error(Errors.InvalidArg, sqlCmd, "sqlCmd");
+                return null;
+            }
+            // Check Result
+            Options result = new Options();
+            while (rs.next())
+            {
+                Object value = rs.getObject(1);
+                String text  = rs.getString(2);
+                result.add(value, text, true);
+            }
+            // No Value
+            if (log.isInfoEnabled())
+                log.info("queryOptionList retured "+String.valueOf(result.size())+" items. Query completed in " + String.valueOf(System.currentTimeMillis() - start) + " ms");
+            clearError();
+            return result;
+        } catch (SQLException e) 
+        {
+            error(DBErrors.QueryFailed, e);
+            return null;
+        } finally
+        { // Cleanup
+            closeResultSet(rs);
+        }
+    }
+
+    /**
+     * Returns a list Object-Arrays holding the result of a query.
+     * This function should only be used for small lists.
+     * 
+     * @param sqlCmd the SQL statement
+     * @param conn a valid connection to the database.
+     * @return a list of object arrays 
+     */
+    public List<Object[]> queryObjectList(String sqlCmd, Connection conn)
+    {   // Execute the  Statement
+        if (checkOpen()==false)
+            return null;
+        // Debug
+        ResultSet rs = null;
+        try
+        {   // Check Open
+            if (checkOpen()==false)
+                return null;
+            // Debug
+            long start = System.currentTimeMillis();
+            if (log.isInfoEnabled())
+                log.info("executing: " + sqlCmd);
+            // Get the next Value
+            rs = driver.executeQuery(sqlCmd, null, false, conn);
+            if (rs == null)
+            { // Error
+                error(driver);
+                return null;
+            }
+            // Read List
+            int colCount = rs.getMetaData().getColumnCount(); 
+            List<Object[]> result = new ArrayList<Object[]>();
+            while (rs.next())
+            {
+                Object[] item = new Object[colCount];
+                for (int i=0; i<colCount; i++)
+                {   // Read from Resultset
+                    item[i] = rs.getObject(i+1);
+                }
+                result.add(item);
+            }
+            // No Value
+            if (log.isInfoEnabled())
+                log.info("queryObjectList retured "+String.valueOf(result.size())+" items. Query completed in " + String.valueOf(System.currentTimeMillis() - start) + " ms");
+            clearError();
+            return result;
+        } catch (SQLException e) 
+        {
+            error(DBErrors.QueryFailed, e);
+            return null;
+        } finally
+        { // Cleanup
+            closeResultSet(rs);
+        }
+    }
+    
+    /**
+     * Executes an update, insert or delete SQL-Statement.<BR>
+     * We recommend to use a DBCommand object in order to build the sqlCmd.<BR>
+     * <P>
+     * @param sqlCmd the SQL-Command
+     * @param sqlParams a list of objects to replace sql parameters
+     * @param conn a valid connection to the database.
+     * @return the row count for insert, update or delete or 0 for SQL statements that return nothing
+     */
+    public int executeSQL(String sqlCmd, Object[] sqlParams, Connection conn)
+    {
+        try 
+        {
+            // check driver
+            if (checkOpen()==false)
+                return -1;
+            // Debug
+            if (log.isInfoEnabled())
+                log.info("Executing: " + sqlCmd);
+            // execute SQL
+            long start = System.currentTimeMillis();
+            int affected = driver.executeSQL(sqlCmd, sqlParams, conn);
+            // Log
+            if (log.isInfoEnabled())
+	            log.info("executeSQL affected " + String.valueOf(affected) + " Records / " + (System.currentTimeMillis() - start) + "ms");
+            // number of affected records
+            if (affected < 0)
+            {
+                error(driver);
+                return -1;
+            }
+            // Return number of affected records
+            return affected;
+            
+	    } catch (SQLException sqle) 
+        { 	// Error
+	        error(sqle);
+	        return -1;
+	    }    
+    }
+
+    /**
+     * Executes an update, insert or delete SQL-Statement.<BR>
+     * We recommend to use a DBCommand object in order to build the sqlCmd.<BR>
+     * <P>
+     * @param sqlCmd the SQL-Command
+     * @param conn a valid connection to the database.
+     * @return the row count for insert, update or delete or 0 for SQL statements that return nothing
+     */
+    public final int executeSQL(String sqlCmd, Connection conn)
+    {
+        return executeSQL(sqlCmd, null, conn); 
+    }
+    
+    /**
+     * Executes a select SQL-Statement and returns a resulset containing the query results.<BR>
+     * This function returns a JDBC ResultSet.<BR>
+     * Insteam of using this function directly you should use a DBReader object instead.<BR>
+     * <P>
+     * @param sqlCmd the SQL-Command
+     * @param sqlParams a list of parameters for parameter queries (may depend on driver)
+     * @param scrollable true if the reader should be scrollable or false if not
+     * @param conn a valid connection to the database.
+     * @return the JDBC ResutSet
+     */
+    public ResultSet executeQuery(String sqlCmd, Object[] sqlParams, boolean scrollable, Connection conn)
+    {
+        try
+        {   // check driver
+            if (checkOpen()==false)
+                return null;
+            // Debug
+            if (log.isDebugEnabled())
+    	        log.debug("Executing: " + sqlCmd);
+            // Execute the Statement
+            long start = System.currentTimeMillis();
+            ResultSet rs = driver.executeQuery(sqlCmd, sqlParams, scrollable, conn);
+            if (rs == null)
+            {   error(driver);
+                return null;
+            }
+            // Debug
+            if (log.isDebugEnabled())
+                log.debug("executeQuery successful in " + String.valueOf(System.currentTimeMillis() - start) + " ms");
+            // Return number of affected records
+            success();
+            return rs;
+
+        } catch (SQLException e) 
+        {   // SQL Query failed!
+            log.error("execute query exception! sql = " + sqlCmd);
+            error(DBErrors.QueryFailed, e);
+            return null; 
+        }
+    }
+
+    /**
+     * Makes all changes made since the previous commit/rollback
+     * permanent and releases any database locks currently held by the
+     * Connection.
+     * <P>
+     * @param conn a valid database connection
+     * @exception java.sql.SQLException if a database access error occurs
+     * @return true if successful
+     */
+    public boolean commit(Connection conn)
+    {
+        try
+        {   // Check arguement
+            if (conn==null)
+                return error(Errors.InvalidArg, null, "conn");
+            // Commit
+            conn.commit();
+            return true;
+        } catch (SQLException sqle) 
+        { 
+            // Commit failed!
+            return error(sqle);
+        }
+    }
+
+    /**
+     * Discards all changes made since the previous commit/rollback
+     * and releases any database locks currently held by this
+     * Connection.
+     * <P>
+     * @param conn a valid database connection
+     * @exception java.sql.SQLException if a database access error occurs
+     * @return true if successful
+     */
+    public boolean rollback(Connection conn)
+    {
+        try
+        {   // Check arguement
+            if (conn==null)
+                return error(Errors.InvalidArg, null, "conn");
+            // Rollback
+            log.info("Database rollback issued!");
+            conn.rollback();
+            return true;
+        } catch (SQLException sqle) 
+        {
+            return error(sqle);
+        }
+    }
+
+    /**
+     * Convenience function for closing a JDBC Resultset<BR>
+     * Use it instead of stmt.close()<BR> 
+     * <P>
+     * @param stmt a Statement object
+     */
+    public void closeStatement(Statement stmt)
+    {
+        try
+        { // Statement close
+            if (stmt != null)
+                stmt.close();
+            // done
+            success();
+        } catch (SQLException sqle)
+        {
+            error(sqle);
+        }
+    }
+
+    /**
+     * Convenience function for closing a JDBC Resultset<BR>
+     * Use it instead of rset.close() and stmt.close()<BR> 
+     * <P>
+     * @param rset a ResultSet object
+     * @exception java.sql.SQLException if a database access error occurs
+     */
+    public void closeResultSet(ResultSet rset)
+    {
+        try
+        { 	// check ResultSet
+            if (rset == null)
+                return; // nothing to do
+            // close Resutlset
+            Statement stmt = rset.getStatement();
+            rset.close();
+            // check Statement
+            if (stmt == null)
+                return;
+            // close Statement
+            stmt.close();
+            success();
+            
+        } catch (SQLException sqle) 
+        {
+            error(sqle);
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabaseDriver.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabaseDriver.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabaseDriver.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDatabaseDriver.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,560 @@
+/*
+ * ESTEAM Software GmbH, 13.12.2004
+ */
+package org.apache.empire.db;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.empire.commons.ErrorObject;
+import org.apache.empire.commons.Errors;
+import org.apache.empire.commons.ObjectUtils;
+import org.apache.empire.commons.StringUtils;
+import org.apache.empire.data.DataType;
+
+
+/**
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ * 
+ */
+public abstract class DBDatabaseDriver extends ErrorObject
+{
+    // sql-phrases
+    public static final int SQL_NULL_VALUE       = 1;   // Oracle: null
+    public static final int SQL_RENAME_COLUMN    = 2;   // Oracle: AS
+    public static final int SQL_PARAMETER        = 3;   // Oracle: ?
+    public static final int SQL_CONCAT_EXPR      = 4;   // Oracle: ||
+    public static final int SQL_RENAME_TABLE     = 5;   // Oracle: AS
+    public static final int SQL_DATABASE_LINK    = 6;   // Oracle: @
+    // data types
+    public static final int SQL_BOOLEAN_TRUE     = 10;  // Oracle: "'Y'"      SQL: "1"
+    public static final int SQL_BOOLEAN_FALSE    = 11;  // Oracle: "'N'"      SQL: "0"
+    public static final int SQL_CURRENT_DATE     = 20;  // Oracle: "sysdate"
+    public static final int SQL_DATE_PATTERN     = 21;  // "yyyy.MM.dd"
+    public static final int SQL_DATE_TEMPLATE    = 22;  // Oracle: "TO_DATE('{0}', 'YYYY-MM-DD')"
+    public static final int SQL_CURRENT_DATETIME = 25;  // Oracle: "sysdate"
+    public static final int SQL_DATETIME_PATTERN = 26;  // "yyyy.MM.dd HH:mm:ss"
+    public static final int SQL_DATETIME_TEMPLATE= 27;  // Oracle: "TO_DATE('{0}', 'YYYY-MM-DD HH24:MI:SS')"
+    // functions
+    public static final int SQL_FUNC_COALESCE    = 100; // Oracle: nvl(?, {0})
+    public static final int SQL_FUNC_SUBSTRING   = 101; // Oracle: substr(?,{0})
+    public static final int SQL_FUNC_SUBSTRINGEX = 102; // Oracle: substr(?,{0},{1})
+    public static final int SQL_FUNC_REPLACE     = 103; // Oracle: replace(?,{0},{1})
+    public static final int SQL_FUNC_REVERSE     = 104; // Oracle: reverse(?) 
+    public static final int SQL_FUNC_STRINDEX    = 105; // Oracle: instr(?, {0})
+    public static final int SQL_FUNC_STRINDEXFROM= 106; // Oracle: instr(?, {0}, {1}) 
+    public static final int SQL_FUNC_LENGTH      = 107; // Oracle: length(?,{0})
+    public static final int SQL_FUNC_UPPER       = 110; // Oracle: upper(?)
+    public static final int SQL_FUNC_LOWER       = 111; // Oracle: lower(?)
+    public static final int SQL_FUNC_TRIM        = 112; // Oracle: trim(?)
+    public static final int SQL_FUNC_LTRIM       = 113; // Oracle: ltrim(?)
+    public static final int SQL_FUNC_RTRIM       = 114; // Oracle: rtrim(?)
+    public static final int SQL_FUNC_ESCAPE      = 119; // Oracle: ? escape '{0}'
+    // Numeric
+    public static final int SQL_FUNC_ABS         = 120; // Oracle: abs(?,{0})
+    public static final int SQL_FUNC_ROUND       = 121; // Oracle: round(?, {0})
+    public static final int SQL_FUNC_TRUNC       = 122; // Oracle: trunc(?, {0})
+    public static final int SQL_FUNC_FLOOR       = 123; // Oracle: floor(?)
+    public static final int SQL_FUNC_CEILING     = 124; // Oracle: ceil(?)
+    // Date
+    public static final int SQL_FUNC_DAY         = 132; // MS SQL month(?)
+    public static final int SQL_FUNC_MONTH       = 133; // MS SQL month(?)
+    public static final int SQL_FUNC_YEAR        = 134; // MS SQL year (?)
+    // Aggregation
+    public static final int SQL_FUNC_SUM         = 140; // Oracle: sum(?)
+    public static final int SQL_FUNC_COUNT       = 141; // Oracle: count(?)
+    public static final int SQL_FUNC_MAX         = 142; // Oracle: max(?)
+    public static final int SQL_FUNC_MIN         = 143; // Oracle: min(?)
+    public static final int SQL_FUNC_AVG         = 144; // Oracle: avg(?)
+    // Decode
+    public static final int SQL_FUNC_DECODE      = 150; // Oracle: "decode(? {0})" SQL: "case ?{0} end"
+    public static final int SQL_FUNC_DECODE_SEP  = 151; // Oracle: ","             SQL: " "
+    public static final int SQL_FUNC_DECODE_PART = 152; // Oracle: "{0}, {1}"      SQL: "when {0} then {1}"
+    public static final int SQL_FUNC_DECODE_ELSE = 153; // Oracle: "{0}"           SQL: "else {0}"
+
+    // Logger
+    protected static Log log = LogFactory.getLog(DBDatabaseDriver.class);
+    
+    // Flag wether or not to set column defaults when crating dll statements
+    protected boolean ddlColumnDefaults = false;
+    
+    // DBSeqTable
+    public static class DBSeqTable extends DBTable
+    {
+        public DBColumn C_SEQNAME;
+        public DBColumn C_SEQVALUE;
+        public DBColumn C_TIMESTAMP;
+
+        /**
+         * Constructor
+         */
+        public DBSeqTable(String tableName, DBDatabase db)
+        {
+            super(tableName, db);
+            // Add all Colums
+            C_SEQNAME   = addColumn("SeqName",  DataType.TEXT,      40, true);
+            C_SEQVALUE  = addColumn("SeqValue", DataType.INTEGER,    0, true);
+            C_TIMESTAMP = addColumn("SeqTime",  DataType.DATETIME,   0, true);
+            // Primary Key
+            setPrimaryKey(new DBColumn[] { C_SEQNAME });
+        }
+
+        // Overridables
+        public Object getNextValue(String SeqName, long minValue, Connection conn)
+        {
+            DBDatabaseDriver driver = db.getDriver();
+            // Create a Command
+            Statement stmt = null;
+            try
+            {   // The select Statement
+                DBCommand cmd = driver.createCommand(db);
+                cmd.select(C_SEQVALUE);
+                cmd.select(C_TIMESTAMP);
+                cmd.where (C_SEQNAME.is(SeqName));
+                String selectCmd = cmd.getSelect();
+                // Get the next Value
+                long seqValue = 0;
+                while (seqValue == 0)
+                {
+                    stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
+                    // Query existing value
+                    ResultSet rs = stmt.executeQuery(selectCmd);
+                    if (rs.next())
+                    { // Read the Sequence Value
+                        seqValue = Math.max(rs.getLong(1) + 1, minValue);
+                        java.sql.Timestamp current = rs.getTimestamp(2);
+                        db.closeResultSet(rs);
+                        // Update existing Record
+                        cmd.clear();
+                        cmd.set(C_SEQVALUE.to(seqValue));
+                        cmd.set(C_TIMESTAMP.to(DBDatabase.SYSDATE));
+                        cmd.where(C_SEQNAME.is(SeqName));
+                        cmd.where(C_TIMESTAMP.is(current));
+                        if (db.executeSQL(cmd.getUpdate(), null, conn) < 1)
+                            seqValue = 0; // Try again
+                    } 
+                    else
+                    { // Close Reader
+                        db.closeResultSet(rs);
+                        // neu angelegen!
+                        seqValue = minValue;
+                        log.warn("warn: Sequence '" + SeqName
+                                       + "' does not exist! Creating sequence with start-value of " + seqValue);
+                        // Add a new Sequence
+                        cmd.clear();
+                        cmd.set(C_SEQNAME.to(SeqName));
+                        cmd.set(C_SEQVALUE.to(seqValue));
+                        cmd.set(C_TIMESTAMP.to(DBDatabase.SYSDATE));
+                        if (db.executeSQL(cmd.getInsert(), null, conn) < 1)
+                            seqValue = 0; // Try again
+                    }
+                    // concurreny problem?
+                    if (seqValue == 0)
+                        log.warn("Failed to increment sequence '" + SeqName + "'. Trying again!");
+                    // close
+                    db.closeStatement(stmt);
+                    cmd.clear();
+                    rs = null;
+                }
+                return new Long(seqValue);
+            } catch (Exception e) 
+            {
+                log.error("getNextValue exception: " + e.toString());
+                error(e);
+                return null;
+            } finally
+            { // Cleanup
+                db.closeStatement(stmt);
+            }
+        }
+    }
+
+    /**
+     * This function creates a DBCommand derived object this database
+     * @param db the database for which to create a command object for
+     * @return a DBCommand object
+     */
+    public abstract DBCommand createCommand(DBDatabase 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
+     */
+    public abstract boolean isSupported(DBDriverFeature type);
+    
+    /**
+     * Returns an sql phrase template for this database system.<br>
+     * Templates for sql function expressions must contain a '?' character which will be 
+     * replaced by the current column expression.<br>
+     * If other parameters are necessary the template must contain placeholders like {0}, {1} etc. 
+     * @param phrase the identifier of the phrase  
+     * @return the phrase template
+     */
+    public abstract String getSQLPhrase(int phrase);
+
+    /**
+     * Returns a data type convertion phrase template for this driver<br>
+     * The returned template must contain a '?' which will be replaced by a column expression.
+     * @param destType the target data type
+     * @param srcType the source data type
+     * @param format additional formatting information (optional) 
+     * @return the data conversion phrase template
+     */
+    public abstract String getConvertPhrase(DataType destType, DataType srcType, Object format);
+
+    /**
+     * Returns the next value of a named sequence The numbers are used for fields of type DBExpr.DT_AUTOINC.<BR>
+     * If a driver supports this function it must return true for isSupported(DBDriverFeature.SEQUENCES).
+     * 
+     * @param db the database
+     * @param SeqName the name of the sequence
+     * @param minValue the minmum value of the sequence
+     * @param conn a valid database connection
+     * @return a new unique sequence value or null if an error occurred
+     */
+    public abstract Object getNextSequenceValue(DBDatabase db, String SeqName, int minValue, Connection conn);
+
+    /**
+     * Returns the value of an AutoIncrement field for the last inserted record.<BR>
+     * This function is only used for databases that do not support sequences.<BR>
+     * Hence getNextSequenceValue() must return 'null'
+     * @param db the database
+     * @param conn a valid database connection
+     * @return the id of the last inserted record null if this feature is not supported
+     */
+    public Object getPostInsertAutoIncValue(DBDatabase db, Connection conn)
+    {
+        error(Errors.NotSupported);
+        return null; 
+    }
+    
+    /**
+     * Prepares an sql statement by setting the supplied objects as parameters.
+     * 
+     * @param pstmt the prepared statement
+     * @param sqlParams list of objects
+     */
+    protected void prepareStatement(PreparedStatement pstmt, Object[] sqlParams)
+    	throws SQLException
+	{
+        for (int i=0; i<sqlParams.length; i++)
+        {
+            if(sqlParams[i] instanceof DBBlobData)
+            {
+                // handling for blobs
+                DBBlobData blobData = (DBBlobData)sqlParams[i];
+                pstmt.setBinaryStream(i + 1, blobData.getInputStream(), blobData.getLength());
+            }
+            else if(sqlParams[i] instanceof DBClobData)
+            {
+                // handling for clobs
+                DBClobData clobData = (DBClobData)sqlParams[i];
+                pstmt.setCharacterStream(i + 1, clobData.getReader(), clobData.getLength());
+            }
+            else
+            {
+                pstmt.setObject(i + 1, sqlParams[i]);
+            }
+        }
+	}
+
+    /**
+     * Extracts native error message of an sqlExeption.
+     * 
+     * @param e the SQLException
+     * @return the error message of the database 
+     */
+    public String extractErrorMessage(SQLException e)
+    {
+        return e.getMessage();
+    }
+    
+    /**
+     * <P>
+     * Reads a sinlge column value from the given JDBC ResultSet and returns a value object of desired data type.<BR> 
+     * See {@link DBExpr#getValueClass(DataType)} for java class type mapping.
+     * <P>
+     * This gives the driver the oportunity to change the value
+     * i.e. to simulate missing data types with other types.
+     * <P>
+     * @param rset the sql Resultset with the current data row
+     * @param columnIndex one based column Index of the desired column
+     * @param dataType the required data type
+     * @return the value of the Column 
+     */
+    public Object getResultValue(ResultSet rset, int columnIndex, DataType dataType)
+        throws SQLException
+    {
+        // Check for character large object
+        if (dataType == DataType.DATETIME)
+        { // Get Timestamp (do not use getObject()!) 
+            return rset.getTimestamp(columnIndex);
+        } 
+        else if (dataType == DataType.CLOB)
+        { // Get character large object
+            java.sql.Clob clob = rset.getClob(columnIndex);
+            return ((clob != null) ? clob.getSubString(1, (int) clob.length()) : null);
+        } 
+        else if (dataType == DataType.BLOB)
+        { // Get bytes of a binary large object
+            java.sql.Blob blob = rset.getBlob(columnIndex);
+            return ((blob != null) ? blob.getBytes(1, (int) blob.length()) : null);
+        } 
+        // Default
+        return rset.getObject(columnIndex);
+    }
+    
+    /**
+     * Executes the select, update or delete SQL-Command with a Statement object.
+     * 
+     * @param sqlCmd the SQL-Command
+     * @param sqlParams array of sql command parameters used for prepared statements (Optional).
+     * @param conn a valid connection to the database.
+     * @return the row count for insert, update or delete or 0 for SQL statements that return nothing
+     */
+    public int executeSQL(String sqlCmd, Object[] sqlParams, Connection conn)
+        throws SQLException
+    {   // Execute the Statement
+        Statement stmt = null;
+        try
+        {
+            if (sqlParams!=null)
+            {
+                PreparedStatement pstmt = conn.prepareStatement(sqlCmd);
+	            stmt = pstmt;
+	            prepareStatement(pstmt, sqlParams);
+                return pstmt.executeUpdate(); 
+            }
+            else
+            {   // Execute a simple statement
+                stmt = conn.createStatement();
+                return stmt.executeUpdate(sqlCmd);
+            }
+        } finally
+        { // Close
+            close(stmt);
+        }
+    }
+
+    // executeQuery
+    public ResultSet executeQuery(String sqlCmd, Object[] sqlParams, boolean scrollable, Connection conn)
+        throws SQLException
+    {
+        Statement stmt = null;
+        try
+        {   // Set scroll type
+            int type = (scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE
+                                   : ResultSet.TYPE_FORWARD_ONLY);
+            // Create an execute a query statement
+	        if (sqlParams!=null)
+	        {	// Use prepared statment
+	            PreparedStatement pstmt = conn.prepareStatement(sqlCmd, type, ResultSet.CONCUR_READ_ONLY);
+	            stmt = pstmt;
+	            prepareStatement(pstmt, sqlParams);
+	            return pstmt.executeQuery();
+	        }
+	        {	// Use simple statment
+	            stmt = conn.createStatement(type, ResultSet.CONCUR_READ_ONLY);
+	            return stmt.executeQuery(sqlCmd);
+	        }
+        } catch(SQLException e) 
+        {
+            // close statement (if not null)
+            close(stmt);
+            throw e;
+        }
+    }
+
+    // close
+    protected void close(Statement stmt)
+    {
+        try
+        { // Statement close
+            if (stmt != null)
+                stmt.close();
+        } catch (SQLException sqle) 
+        {
+            log.error("close statement:" + sqle.toString());
+        }
+    }
+
+    // helper for Date and DateTime Strings
+    protected String getDateTimeString(Object value, int sqlTemplate, int sqlPattern, int sqlCurrentDate)
+    {
+        // is it a sysdate expression
+        if (DBDatabase.SYSDATE.equals(value))
+            return getSQLPhrase(sqlCurrentDate);
+        // Format the date (ymd)
+        String datetime = value.toString(); 
+        SimpleDateFormat sqlFormat = new SimpleDateFormat(getSQLPhrase(sqlPattern));
+        if ((value instanceof Date)==false)
+        {   // Convert String to Date
+            try
+            {
+                DateFormat source = DateFormat.getDateInstance(DateFormat.SHORT);
+                Date dt = source.parse(value.toString());
+               datetime = sqlFormat.format(dt);
+            } catch (ParseException e)
+            {
+                log.error("Date parsing error ", e);
+            }
+        }
+        else
+        {   // Format the date as string
+            datetime = sqlFormat.format((Date)value);
+        }
+        // Now Build String
+        String template = getSQLPhrase(sqlTemplate);
+        return StringUtils.replace(template, "{0}", datetime);
+    }
+    
+    /**
+     * Creates a sql string for a given value. 
+     * Text will be enclosed in single quotes and existing single quotes will be doubled.
+     * Empty strings are treated as null.
+     * Syntax of Date, Datetime and Boolean values are vendor specific.
+     * 
+     * @param value the value which is inserted to the new String
+     * @param type the sql data type of the supplied value
+     * @return the sql string representing this value
+     */
+    public String getValueString(Object value, DataType type)
+    { 
+        if (ObjectUtils.isEmpty(value))
+        {
+            return getSQLPhrase(SQL_NULL_VALUE);
+        }
+        // set string buffer
+        switch (type)
+        {
+            case DATE:
+                return getDateTimeString(value, SQL_DATE_TEMPLATE, SQL_DATE_PATTERN, SQL_CURRENT_DATE);
+            case DATETIME:
+                // System date is special case
+                if (!DBDatabase.SYSDATE.equals(value) && value.toString().length()<=10)
+                    return getDateTimeString(value, SQL_DATE_TEMPLATE, SQL_DATE_PATTERN, SQL_CURRENT_DATETIME);
+                // Vollständiges Date-Time Object mit Zeit 
+                return getDateTimeString(value, SQL_DATETIME_TEMPLATE, SQL_DATETIME_PATTERN, SQL_CURRENT_DATETIME);
+            case TEXT:
+            case CHAR:
+            case CLOB:
+            {   // Text value
+                StringBuilder valBuf = new StringBuilder();
+                valBuf.append("'");
+                if (DBDatabase.EMPTY_STRING.equals(value)==false)
+                    appendTextValue(valBuf, value.toString());
+                valBuf.append("'");
+                return valBuf.toString();
+            }
+            case BOOL:
+            {   // Get Boolean value   
+                boolean boolVal = false;
+                if (value instanceof Boolean)
+                {   boolVal = ((Boolean) value).booleanValue();
+                } 
+                else
+                { // Boolean from String
+                    String strVal = value.toString();
+                    boolVal = strVal.equals("1") |
+                              strVal.equalsIgnoreCase("true") |
+                              strVal.equalsIgnoreCase("y");
+                }
+                return getSQLPhrase((boolVal) ? SQL_BOOLEAN_TRUE : SQL_BOOLEAN_FALSE);
+            }
+            default:
+                return value.toString();
+        }
+    }
+
+    /**
+     * Called when a database is opened
+     */
+    protected boolean attachDatabase(DBDatabase db, Connection conn)
+    {
+        return success();
+    }
+
+    /**
+     * Called when a database is closed
+     */
+    protected void detachDatabase(DBDatabase db, Connection conn)
+    {
+        // Override to implement closing behaviour
+    }
+
+    /**
+     * Checks the database whether or not it is consistent with the description.
+     */
+    public boolean checkDatabase(DBDatabase db, String owner, Connection conn)
+    {
+    	return error(Errors.NotImplemented, "checkDatabase");
+    }
+    
+    /**
+     * gets an SQL command for creating, modifying or deleting objects in the database (tables, columns, constraints, etc.)
+     */
+    public boolean getDDLScript(DBCmdType type, DBObject dbo, DBSQLScript script)
+    {
+        return error(Errors.NotSupported, "getDDLScript");
+    }
+    
+    /**
+     * @return true if column default values are created with dll statements or false if not
+     */
+    public boolean isDDLColumnDefaults()
+    {
+        return ddlColumnDefaults;
+    }
+
+    /**
+     * Set true if column default values should be included in DDL Statements  
+     * @param enable true if dll statements should include column default values or false if not
+     */
+    public void setDDLColumnDefaults(boolean enable)
+    {
+        ddlColumnDefaults = enable;
+    }
+
+    /**
+     * Returns a timestamp that is used for record updates.
+     * 
+     * @return the current date and time.
+     */
+    public java.sql.Timestamp getUpdateTimestamp(Connection conn)
+    {
+        // Default implementation
+        java.util.Date date = new java.util.Date();
+        return new java.sql.Timestamp(date.getTime());
+    }
+
+    /** this helper function doubles up single quotes for SQL */
+    protected void appendTextValue(StringBuilder buf, String value)
+    {
+        if (value.indexOf('\'') >= 0)
+        { // a routine to double up single quotes for SQL
+            int len = value.length();
+            for (int i = 0; i < len; i++)
+            {
+                if (value.charAt(i) == '\'')
+                    buf.append("''");
+                else
+                    buf.append(value.charAt(i));
+            }
+        } 
+        else
+        {
+            buf.append(value);
+        }
+    }
+
+}
\ No newline at end of file

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDriverFeature.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDriverFeature.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDriverFeature.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBDriverFeature.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,15 @@
+/*
+ * ESTEAM Software GmbH, 04.04.2008
+ */
+package org.apache.empire.db;
+
+/**
+ * This enum is used with the DBDatabaseDriver::isSupported method to query database driver capabilities.
+ *
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ */
+public enum DBDriverFeature {
+    // Support Flags used by DBDatabaseDriver::isSupported()
+    CREATE_SCHEMA,
+    SEQUENCES,    
+}

Added: incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBErrors.java
URL: http://svn.apache.org/viewvc/incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBErrors.java?rev=683173&view=auto
==============================================================================
--- incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBErrors.java (added)
+++ incubator/empire-db/trunk/core/Empire-db/src/org/apache/empire/db/DBErrors.java Wed Aug  6 01:47:37 2008
@@ -0,0 +1,57 @@
+/*
+ * ESTEAM Software GmbH, 14.07.2007
+ */
+package org.apache.empire.db;
+
+import org.apache.empire.commons.ErrorType;
+
+/**
+ * This class contains the definition of database specific errors.
+ * <P>
+ * For more informations see {@link org.apache.empire.commons.Errors}
+ * @author ESTEAM software <A TARGET="esteam" HREF="http://www.esteam.de">www.esteam.de </A>
+ */
+public class DBErrors
+{
+    // Database
+    public static final ErrorType DatabaseNotOpen        = new ErrorType("error.db.databasenotopen",
+                                                                         "the database has not been opened.");
+    public static final ErrorType ConnecitonInvalid      = new ErrorType("error.db.connectioninvalid",
+                                                                         "the database connection is not valid");
+    public static final ErrorType SQLException           = new ErrorType("error.db.sqlexception",
+                                                                         "The database operation failed. Native error is {0}.");
+    public static final ErrorType ObjectNotFound         = new ErrorType("error.db.objectnotfound",
+                                                                         "an object of type {0} named {1} does not exists or is inaccessible.");
+    public static final ErrorType ObjectCreationFailed   = new ErrorType("error.db.objectcreationfailed",
+                                                                         "error creating the {0} of name {1}.");
+    public static final ErrorType NoPrimaryKey           = new ErrorType("error.db.noprimarykey",
+                                                                         "No primary key is defined for {0}");
+    // Query errors
+    public static final ErrorType QueryFailed            = new ErrorType("error.db.queryfailed",
+                                                                         "The query failed. Native error is {0}.");
+    public static final ErrorType QueryNoResult          = new ErrorType("error.db.querynoresult",
+                                                                         "No records found for query {0}");
+    // Record errors
+    public static final ErrorType RecordInvalidKey       = new ErrorType("error.db.recordinvalidkey", "Invalid record key {0}");
+    public static final ErrorType RecordNotFound         = new ErrorType("error.db.recordnotfound",
+                                                                         "The record {0} does not exist. It might have been deleted by another user.");
+    public static final ErrorType RecordUpdateFailed     = new ErrorType("error.db.recordupatefailed",
+                                                                         "Updating the record {0} failed. It might have been changed or deleted by another user.");
+    public static final ErrorType RecordUpdateInvalid    = new ErrorType("error.db.recordupateinvalid",
+                                                                         "Updating the record {0} failed. The given record key is ambiguous.");
+    public static final ErrorType RecordDeleteFailed     = new ErrorType("error.db.recorddeletefailed",
+                                                                         "Deleting the record {0} failed. The record might have been deleted already by another user.");
+    // Field errors
+    public static final ErrorType FieldIsReadOnly        = new ErrorType("error.db.fieldisreadonly",
+                                                                         "The field {0} is read only.");
+    public static final ErrorType FieldValueTooLong      = new ErrorType("error.db.fieldvaluetoolong",
+                                                                         "The value supplied for field {0} is too long. The maximum number of characters is {1}.");
+    public static final ErrorType FieldNotNull           = new ErrorType("error.db.fieldnotnull",
+                                                                         "The value for field {0} must not be null.");
+    public static final ErrorType FieldNotNumeric        = new ErrorType("error.db.fieldnotnumeric",
+                                                                         "The field value supplied for field {0} is not numeric.");
+    public static final ErrorType FieldInvalidDateFormat = new ErrorType("error.db.fieldinvaliddateformat",
+                                                                         "The date supplied for field {0} is not valid.");
+    public static final ErrorType FieldInvalidValue      = new ErrorType("error.db.fieldinvalidvalue",
+                                                                         "The value for field {0} is invalid.");
+}