You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by Ig...@adminteractive.com.ua on 2003/01/29 14:19:25 UTC

[PATCH] Database identity support for MSSQL server

Hello,

This patch adds IDENTITY support for the MSSQL server.


repository.xml:
  <class-descriptor class="my.model.Member"
    table="Members"
    >
    <!-- IDENTITY column -->
    <attribute attribute-name="identity" attribute-value="uid" />

    <field-descriptor
      name="uid" column="id"
      jdbc-type="INTEGER"
      primarykey="true"
      nullable="false"/>


OJB.properties:
SqlGeneratorClass=org.apache.ojb.broker.accesslayer.sql.MSSQLSqlGeneratorImpl
StatementManagerClass=org.apache.ojb.broker.accesslayer.MSSQLStatementManager
JdbcAccessClass=org.apache.ojb.broker.accesslayer.MSSQLJdbcAccessImpl

--
Good Luck,
Igor S. Petrenko
www.adminteractive.com
mailto:nofate@ukr.net #ICQ: 19254900 





diff -urN /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java
--- /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java	Tue Jan 21 09:33:31 2003
+++ /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/JdbcAccessImpl.java	Wed Jan 29 14:48:53 2003
@@ -84,7 +84,7 @@
  */
 public class JdbcAccessImpl implements JdbcAccess
 {
-	private static final String SQL_STATE_KEY_VIOLATED = "23000";
+	protected static final String SQL_STATE_KEY_VIOLATED = "23000";
     /**
      * The logger used.
      */
diff -urN /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLJdbcAccessImpl.java /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLJdbcAccessImpl.java
--- /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLJdbcAccessImpl.java	Thu Jan  1 03:00:00 1970
+++ /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLJdbcAccessImpl.java	Wed Jan 29 14:49:16 2003
@@ -0,0 +1,131 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.ojb.broker.accesslayer;
+
+import org.apache.ojb.broker.accesslayer.JdbcAccessImpl;
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.PersistenceBrokerSQLException;
+import org.apache.ojb.broker.KeyConstraintViolatedException;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+
+import java.sql.SQLException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+
+/**
+ * @author <a href="mailto:nofate@ukr.net">Igor.Petrenko</a>
+ */
+public class MSSQLJdbcAccessImpl extends JdbcAccessImpl {
+  protected static final String IDENTITY_COLUMN = "identity";
+
+  public MSSQLJdbcAccessImpl(PersistenceBroker broker) {
+    super(broker);
+  }
+
+
+  /**
+   * performs an INSERT operation against RDBMS.
+   * @param obj The Object to be inserted as a row of the underlying table.
+   * @param cld ClassDescriptor providing mapping information.
+   */
+  public void executeInsert(ClassDescriptor cld, Object obj) throws PersistenceBrokerException {
+    logger.safeDebug("MSSQL: executeInsert", obj);
+
+    PreparedStatement stmt = null;
+    try {
+      stmt = broker.serviceStatementManager().getInsertStatement(cld);
+      if (stmt == null) {
+        logger.error("MSSQL: getInsertStatement returned a null statement");
+        throw new PersistenceBrokerException("MSSQL: getInsertStatement returned a null statement");
+      }
+      broker.serviceStatementManager().bindInsert(stmt, cld, obj);
+      stmt.executeUpdate();
+
+      String identity = cld.getAttribute(IDENTITY_COLUMN);
+      if (identity != null) {
+        try {
+          FieldDescriptor fd = cld.getFieldDescriptorByName(identity);
+          Statement statement  = broker.serviceConnectionManager().getConnection().createStatement();
+          ResultSet rs = statement.executeQuery("SELECT @@IDENTITY");
+          if (rs.next()) {
+            fd.getPersistentField().set(obj, new Integer(rs.getInt(1)));
+          }
+          rs.close();
+          statement.close();
+        } catch (Exception e) {
+          e.printStackTrace();  //To change body of catch statement use Options | File Templates.
+        }
+      }
+
+    } catch (PersistenceBrokerException e) {
+      logger.error("MSSQL: PersistenceBrokerException during the execution of the insert: " + e.getMessage(), e);
+      throw e;
+    } catch (SQLException e) {
+      logger.error("MSSQL: SQLException during the execution of the insert (for a " + cld.getClassOfObject().getName() + "): " + e.getMessage(), e);
+      /**
+       * throw a specific type of runtime exception for a key constraint.
+       */
+      if (SQL_STATE_KEY_VIOLATED.equals(e.getSQLState())) {
+        throw new KeyConstraintViolatedException(e);
+      } else {
+        throw new PersistenceBrokerSQLException(e);
+      }
+    } finally {
+      broker.serviceStatementManager().closeResources(stmt, null);
+    }
+  }
+}
diff -urN /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLStatementManager.java /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLStatementManager.java
--- /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLStatementManager.java	Thu Jan  1 03:00:00 1970
+++ /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/MSSQLStatementManager.java	Wed Jan 29 14:49:17 2003
@@ -0,0 +1,139 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+package org.apache.ojb.broker.accesslayer;
+
+import org.apache.ojb.broker.PersistenceBroker;
+import org.apache.ojb.broker.PersistenceBrokerException;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
+import org.apache.ojb.broker.util.SqlHelper;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+
+import java.sql.PreparedStatement;
+
+/**
+ * manages JDBC Connection and Statement resources.
+ *
+ * @author Thomas Mahler
+ * @author <a href="mailto:nofate@ukr.net">Igor.Petrenko</a>
+ */
+public class MSSQLStatementManager extends StatementManager {
+  private Logger log = LoggerFactory.getLogger(MSSQLStatementManager.class);
+
+  public MSSQLStatementManager(final PersistenceBroker pBroker, Logger log) {
+    super(pBroker);
+    this.log = log;
+  }
+
+  /**
+   * binds the values of the object obj to the statements parameters
+   */
+  public void bindInsert(PreparedStatement stmt, ClassDescriptor cld, Object obj)
+      throws java.sql.SQLException {
+    Object[] values;
+    cld.updateLockingValues(obj); // BRJ : provide useful defaults for locking fields
+
+    values = getAllValues(cld, obj);
+    for (int i = 0; i < values.length; i++) {
+      Object val = values[i];
+      if (val != null) {
+        platform.setObjectForStatement(stmt, i + 1, val, SqlHelper.getSqlTypeAll(cld, i));
+      } else {
+        platform.setNullForStatement(stmt, i + 1, SqlHelper.getSqlTypeAll(cld, i));
+      }
+
+    }
+  }
+
+  /**
+   * returns an array containing values for all the Objects attribute
+   * @throws org.apache.ojb.broker.metadata.MetadataException if tehre is an erros accessing obj field values
+   */
+  protected Object[] getAllValues(ClassDescriptor cld, Object obj) throws PersistenceBrokerException {
+    FieldDescriptor[] allFields = cld.getFieldDescriptions();
+    String identity = cld.getAttribute("identity");
+    int modify = 0;
+    if (cld.getFieldDescriptorByName(identity) != null) {
+      modify = 1;
+    }
+
+    Object[] result = new Object[allFields.length - modify];
+
+    modify = 0;
+
+    for (int i = 0; i < result.length; i++) {
+      FieldDescriptor fmd = allFields[i];
+      if (!fmd.getAttributeName().equals(identity)) {
+        PersistentField f = fmd.getPersistentField();
+        Object cv = f.get(obj);
+
+        // handle autoincrement attributes if not filled
+        if (fmd.isAutoIncrement()) {
+          cv = broker.serviceBrokerHelper().getAutoIncrementValue(fmd, obj, cv);
+        }
+
+        // apply type and value mapping
+        cv = fmd.getFieldConversion().javaToSql(cv);
+        result[i - modify] = cv;
+      } else {
+        modify = 1;
+      }
+    }
+    return result;
+  }
+
+}
diff -urN /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java
--- /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java	Tue Jan 21 09:33:32 2003
+++ /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/StatementManager.java	Wed Jan 29 14:47:48 2003
@@ -102,8 +102,8 @@
     /** internal table of StatementForClass objects */
     private Map statementTable = new WeakHashMap();
     /** the associated broker */
-    private final PersistenceBroker broker;
-    private Platform platform;
+    protected final PersistenceBroker broker;
+    protected Platform platform;
     /**
      * Used when OJB run in JBoss
      * @todo Find a better solution to handle OJB within JBoss
diff -urN /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlGeneratorImpl.java /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlGeneratorImpl.java
--- /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlGeneratorImpl.java	Thu Jan  1 03:00:00 1970
+++ /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlGeneratorImpl.java	Wed Jan 29 14:49:25 2003
@@ -0,0 +1,90 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+package org.apache.ojb.broker.accesslayer.sql;
+
+import org.apache.ojb.broker.platforms.Platform;
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+
+/**
+ * This Class is responsible for building sql statements
+ * Objects fields and their repective values are accessed by Java reflection
+ *
+ * @author <a href="mailto:nofate@ukr.net">Igor Petrenko<a>
+ */
+public class MSSQLSqlGeneratorImpl extends SqlGeneratorDefaultImpl {
+  private Logger logger = LoggerFactory.getLogger(MSSQLSqlGeneratorImpl.class);
+
+  public MSSQLSqlGeneratorImpl(Platform pf) {
+    super(pf);
+  }
+
+  /**
+   * generate a prepared INSERT-Statement for the Class
+   * described by cld.
+   * @param cld the ClassDescriptor
+   */
+  public String getPreparedInsertStatement(ClassDescriptor cld)
+  {
+      SqlStatement sql;
+      String result;
+
+      sql = new MSSQLSqlInsertStatement(cld, logger);
+      result = sql.getStatement();
+
+      logger.debug("MSSQL SQL: " + result);
+      return result;
+  }
+}
diff -urN /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlInsertStatement.java /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlInsertStatement.java
--- /home/nofate/cvs/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlInsertStatement.java	Thu Jan  1 03:00:00 1970
+++ /home/nofate/1/jakarta-ojb/src/java/org/apache/ojb/broker/accesslayer/sql/MSSQLSqlInsertStatement.java	Wed Jan 29 14:49:26 2003
@@ -0,0 +1,155 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ *
+ * Created by IntelliJ IDEA.
+ * User: Igor.Petrenko
+ * Date: 29.01.2003
+ * Time: 13:02:03
+ */
+package org.apache.ojb.broker.accesslayer.sql;
+
+import org.apache.ojb.broker.metadata.ClassDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.ojb.broker.util.logging.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Model an INSERT Statement
+ *
+ * @author <a href="mailto:jbraeuchi@hotmail.com">Jakob Braeuchi</a>
+ * @author <a href="mailto:nofate@ukr.net">Igor Petrenko</a>
+ * @version $Id: SqlInsertStatement.java,v 1.3 2002/10/08 13:20:18 brj Exp $
+ */
+public class MSSQLSqlInsertStatement extends SqlInsertStatement {
+  protected static final String IDENTITY_COLUMN = "identity";
+
+  /**
+   * Constructor for SqlInsertStatement.
+   * @param cld
+   * @param logger
+   */
+  public MSSQLSqlInsertStatement(ClassDescriptor cld, Logger logger) {
+    super(cld, logger);
+  }
+
+
+  /**
+   * @see org.apache.ojb.broker.accesslayer.sql.SqlStatement#getStatement()
+   */
+  public String getStatement() {
+    StringBuffer stmt = new StringBuffer(1024);
+    ClassDescriptor cld = getClassDescriptor();
+
+    String identityColumn = cld.getAttribute(IDENTITY_COLUMN);
+
+    stmt.append("INSERT INTO ");
+    appendTable(cld, stmt);
+    stmt.append(" (");
+    appendListOfColumns(cld, stmt, identityColumn);
+    stmt.append(")");
+    appendListOfValues(cld, stmt, identityColumn);
+
+    return stmt.toString();
+  }
+
+  protected List appendListOfColumns(ClassDescriptor cld, StringBuffer buf, String identityColumn) {
+    FieldDescriptor[] fieldDescriptors = cld.getFieldDescriptions();
+
+    ArrayList columnList = new ArrayList();
+    boolean isFirst = true;
+    for (int i = 0; i < fieldDescriptors.length; i++) {
+      FieldDescriptor fd = fieldDescriptors[i];
+      if (!fd.getAttributeName().equals(identityColumn)) {
+        if (!isFirst) {
+          buf.append(",");
+        } else {
+          isFirst = false;
+        }
+        buf.append(fd.getColumnName());
+        columnList.add(fd.getAttributeName());
+      }
+    }
+    return columnList;
+  }
+
+  /**
+   * generates a values(?,) for a prepared insert statement.
+   * returns null if there are no fields
+   * @param stmt the StringBuffer
+   */
+  protected void appendListOfValues(ClassDescriptor cld, StringBuffer stmt, String identityColumn) {
+    FieldDescriptor[] fields = cld.getFieldDescriptions();
+
+    if (fields.length == 0) {
+      return;
+    }
+
+    boolean isFirst = true;
+    stmt.append(" VALUES ( ");
+    for (int i = 0; i < fields.length; i++) {
+      FieldDescriptor fd = fields[i];
+      if (!fd.getAttributeName().equals(identityColumn)) {
+        if (!isFirst) {
+          stmt.append(", ");
+        } else {
+          isFirst = false;
+        }
+        stmt.append("?");
+      }
+    }
+    stmt.append(" ) ");
+  }
+}