KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc > JDBCStartCommand


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.cmp.jdbc;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.Statement JavaDoc;
26 import java.util.Collection JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Set JavaDoc;
32 import javax.sql.DataSource JavaDoc;
33 import javax.transaction.Transaction JavaDoc;
34 import javax.transaction.TransactionManager JavaDoc;
35
36 import org.jboss.deployment.DeploymentException;
37 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge;
38 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractCMRFieldBridge;
39 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCAbstractEntityBridge;
40 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityMetaData;
41 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCRelationMetaData;
42 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCFunctionMappingMetaData;
43 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCRelationshipRoleMetaData;
44 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData;
45 import org.jboss.ejb.plugins.cmp.bridge.EntityBridge;
46 import org.jboss.logging.Logger;
47
48 /**
49  * JDBCStartCommand creates the table if specified in xml.
50  *
51  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
52  * @author <a HREF="mailto:rickard.oberg@telkel.com">Rickard Öberg</a>
53  * @author <a HREF="mailto:marc.fleury@telkel.com">Marc Fleury</a>
54  * @author <a HREF="mailto:shevlandj@kpi.com.au">Joe Shevland</a>
55  * @author <a HREF="mailto:justin@j-m-f.demon.co.uk">Justin Forder</a>
56  * @author <a HREF="mailto:michel.anke@wolmail.nl">Michel de Groot</a>
57  * @author <a HREF="mailto:alex@jboss.org">Alex Loubyansky</a>
58  * @author <a HREF="mailto:heiko.rupp@cellent.de">Heiko W.Rupp</a>
59  * @author <a HREF="mailto:joachim@cabsoft.be">Joachim Van der Auwera</a>
60  * @version $Revision: 46026 $
61  */

62 public final class JDBCStartCommand
63 {
64    private static final String JavaDoc IDX_POSTFIX = "_idx";
65    private static final String JavaDoc COULDNT_SUSPEND = "Could not suspend current transaction before ";
66    private static final String JavaDoc COULDNT_REATTACH = "Could not reattach original transaction after ";
67    private final static Object JavaDoc CREATED_TABLES_KEY = new Object JavaDoc();
68    private final JDBCEntityPersistenceStore manager;
69    private final JDBCAbstractEntityBridge entity;
70    private final JDBCEntityMetaData entityMetaData;
71    private final Logger log;
72    private static int idxCount = 0;
73
74    public JDBCStartCommand(JDBCEntityPersistenceStore manager)
75    {
76       this.manager = manager;
77       entity = manager.getEntityBridge();
78       entityMetaData = manager.getMetaData();
79
80       // Create the Log
81
log = Logger.getLogger(this.getClass().getName() +
82          "." +
83          manager.getMetaData().getName());
84
85       // Create the created tables set
86
Set JavaDoc tables = (Set JavaDoc) manager.getApplicationData(CREATED_TABLES_KEY);
87       if(tables == null)
88       {
89          manager.putApplicationData(CREATED_TABLES_KEY, new HashSet JavaDoc());
90       }
91    }
92
93    public void execute() throws DeploymentException
94    {
95       Set JavaDoc existedTables = getExistedTables(manager);
96
97       boolean tableExisted = SQLUtil.tableExists(entity.getQualifiedTableName(), entity.getDataSource());
98       if(tableExisted)
99       {
100          existedTables.add(entity.getEntityName());
101       }
102
103       if(tableExisted)
104       {
105          if(entityMetaData.getAlterTable())
106          {
107             SQLUtil.OldColumns oldColumns = SQLUtil.getOldColumns(entity.getQualifiedTableName(), entity.getDataSource());
108             ArrayList JavaDoc oldNames = oldColumns.getColumnNames();
109             ArrayList JavaDoc oldTypes = oldColumns.getTypeNames();
110             ArrayList JavaDoc oldSizes = oldColumns.getColumnSizes();
111             SQLUtil.OldIndexes oldIndexes = null;
112             ArrayList JavaDoc newNames = new ArrayList JavaDoc();
113             JDBCFieldBridge fields[] = entity.getTableFields();
114             String JavaDoc tableName = entity.getQualifiedTableName();
115             for(int i = 0; i < fields.length; i++)
116             {
117                JDBCFieldBridge field = fields[i];
118                JDBCType jdbcType = field.getJDBCType();
119                String JavaDoc[] columnNames = jdbcType.getColumnNames();
120                String JavaDoc[] sqlTypes = jdbcType.getSQLTypes();
121                boolean[] notNull = jdbcType.getNotNull();
122
123                for(int j = 0; j < columnNames.length; j++)
124                {
125                   String JavaDoc name = columnNames[j];
126                   String JavaDoc ucName = name.toUpperCase();
127
128                   newNames.add( ucName );
129
130                   int oldIndex = oldNames.indexOf( ucName );
131                   if(oldIndex == -1)
132                   {
133                      // add new column
134
StringBuffer JavaDoc buf = new StringBuffer JavaDoc( sqlTypes[j] );
135                      if( notNull[j] )
136                      {
137                         buf.append(SQLUtil.NOT).append(SQLUtil.NULL);
138                      }
139                      alterTable(entity.getDataSource(),
140                            entityMetaData.getTypeMapping().getAddColumnTemplate(),
141                            tableName, name, buf.toString());
142                   }
143                   else
144                   {
145                      // alter existing columns
146
// only CHAR and VARCHAR fields are altered, and only when they are longer then before
147
String JavaDoc type = (String JavaDoc) oldTypes.get(oldIndex);
148                      if(type.equals("CHAR") || type.equals("VARCHAR"))
149                      {
150                         try
151                         {
152                            // get new length
153
String JavaDoc l = sqlTypes[j];
154                            l = l.substring(l.indexOf('(') + 1, l.length() - 1);
155                            Integer JavaDoc oldLength = (Integer JavaDoc) oldSizes.get(oldIndex);
156                            if(Integer.parseInt(l) > oldLength.intValue())
157                            {
158                               alterTable(entity.getDataSource(),
159                                     entityMetaData.getTypeMapping().getAlterColumnTemplate(),
160                                     tableName, name, sqlTypes[j] );
161                            }
162                         }
163                         catch(Exception JavaDoc e)
164                         {
165                            log.warn("EXCEPTION ALTER :" + e.toString());
166                         }
167                      }
168                   }
169                }
170
171                // see if we have to add an index for the field
172
JDBCCMPFieldMetaData fieldMD = entity.getMetaData().getCMPFieldByName(field.getFieldName());
173                if(fieldMD != null && fieldMD.isIndexed())
174                {
175                   if(oldIndexes == null)
176                   {
177                      oldIndexes = SQLUtil.getOldIndexes(entity.getQualifiedTableName(), entity.getDataSource());
178                      idxCount = oldIndexes.getIndexNames().size();
179                   }
180                   if(!hasIndex(oldIndexes, field))
181                   {
182                      createCMPIndex( entity.getDataSource(), field, oldIndexes.getIndexNames() );
183                   }
184
185                }
186             } // for int i;
187

188             // delete old columns
189
Iterator JavaDoc it = oldNames.iterator();
190             while(it.hasNext())
191             {
192                String JavaDoc name = (String JavaDoc) (it.next());
193                if(!newNames.contains(name))
194                {
195                   alterTable(entity.getDataSource(),
196                         entityMetaData.getTypeMapping().getDropColumnTemplate(),
197                         tableName, name, "");
198                }
199             }
200
201          }
202       }
203
204       // Create table if necessary
205
Set JavaDoc createdTables = getCreatedTables(manager);
206
207       if(entityMetaData.getCreateTable() && !createdTables.contains(entity.getEntityName()))
208       {
209          DataSource JavaDoc dataSource = entity.getDataSource();
210          createTable(dataSource, entity.getQualifiedTableName(), getEntityCreateTableSQL(dataSource));
211
212          // create indices only if table did not yet exist.
213
if(!tableExisted)
214          {
215             createCMPIndices( dataSource,
216                               SQLUtil.getOldIndexes( entity.getQualifiedTableName(),
217                                                      entity.getDataSource() ).getIndexNames() );
218          }
219          else
220          {
221             if(log.isDebugEnabled())
222             {
223                log.debug("Indices for table " + entity.getQualifiedTableName() + "not created as table existed");
224             }
225          }
226
227
228          // issue extra (user-defined) sql for table
229
if(!tableExisted)
230          {
231             issuePostCreateSQL(dataSource,
232                entity.getMetaData().getDefaultTablePostCreateCmd(),
233                entity.getQualifiedTableName());
234          }
235
236          createdTables.add(entity.getEntityName());
237       }
238       else
239       {
240          log.debug("Table not create as requested: " + entity.getQualifiedTableName());
241       }
242
243       // create relation tables
244
JDBCAbstractCMRFieldBridge[] cmrFields = entity.getCMRFields();
245       for(int i = 0; i < cmrFields.length; ++i)
246       {
247          JDBCAbstractCMRFieldBridge cmrField = cmrFields[i];
248          JDBCRelationMetaData relationMetaData = cmrField.getMetaData().getRelationMetaData();
249
250          // if the table for the related entity has been created
251
final EntityBridge relatedEntity = cmrField.getRelatedEntity();
252          if(relationMetaData.isTableMappingStyle() && createdTables.contains(relatedEntity.getEntityName()))
253          {
254             DataSource JavaDoc dataSource = relationMetaData.getDataSource();
255
256             boolean relTableExisted = SQLUtil.tableExists(cmrField.getQualifiedTableName(), entity.getDataSource());
257
258             if(relTableExisted)
259             {
260                if(relationMetaData.getAlterTable())
261                {
262                   ArrayList JavaDoc oldNames = SQLUtil.getOldColumns(cmrField.getQualifiedTableName(), dataSource).getColumnNames();
263                   ArrayList JavaDoc newNames = new ArrayList JavaDoc();
264                   JDBCFieldBridge[] leftKeys = cmrField.getTableKeyFields();
265                   JDBCFieldBridge[] rightKeys = cmrField.getRelatedCMRField().getTableKeyFields();
266                   JDBCFieldBridge[] fields = new JDBCFieldBridge[leftKeys.length + rightKeys.length];
267                   System.arraycopy(leftKeys, 0, fields, 0, leftKeys.length);
268                   System.arraycopy(rightKeys, 0, fields, leftKeys.length, rightKeys.length);
269                   // have to append field names to leftKeys, rightKeys...
270

271                   boolean different = false;
272                   for(int j = 0; j < fields.length; j++)
273                   {
274                      JDBCFieldBridge field = fields[j];
275
276                      String JavaDoc name = field.getJDBCType().getColumnNames()[0].toUpperCase();
277                      newNames.add(name);
278
279                      if(!oldNames.contains(name))
280                      {
281                         different = true;
282                         break;
283                      }
284                   } // for int j;
285

286                   if(!different)
287                   {
288                      Iterator JavaDoc it = oldNames.iterator();
289                      while(it.hasNext())
290                      {
291                         String JavaDoc name = (String JavaDoc) (it.next());
292                         if(!newNames.contains(name))
293                         {
294                            different = true;
295                            break;
296                         }
297                      }
298                   }
299
300                   if(different)
301                   {
302                      // only log, don't drop table is this can cause data loss
303
log.error("CMR table structure is incorrect for " + cmrField.getQualifiedTableName());
304                      //SQLUtil.dropTable(entity.getDataSource(), cmrField.getQualifiedTableName());
305
}
306
307                } // if alter-table
308

309             } // if existed
310

311             // create the relation table
312
if(relationMetaData.isTableMappingStyle() && !relationMetaData.isTableCreated())
313             {
314                if(relationMetaData.getCreateTable())
315                {
316                   createTable(dataSource, cmrField.getQualifiedTableName(),
317                      getRelationCreateTableSQL(cmrField, dataSource));
318                }
319                else
320                {
321                   log.debug("Relation table not created as requested: " + cmrField.getQualifiedTableName());
322                }
323                // create Indices if needed
324
createCMRIndex(dataSource, cmrField);
325
326                if(relationMetaData.getCreateTable())
327                {
328                   issuePostCreateSQL(dataSource,
329                      relationMetaData.getDefaultTablePostCreateCmd(),
330                      cmrField.getQualifiedTableName());
331                }
332             }
333          }
334       }
335    }
336
337    public void addForeignKeyConstraints() throws DeploymentException
338    {
339       // Create table if necessary
340
Set JavaDoc createdTables = getCreatedTables(manager);
341
342       JDBCAbstractCMRFieldBridge[] cmrFields = entity.getCMRFields();
343       for(int i = 0; i < cmrFields.length; ++i)
344       {
345          JDBCAbstractCMRFieldBridge cmrField = cmrFields[i];
346          JDBCRelationMetaData relationMetaData = cmrField.getMetaData().getRelationMetaData();
347
348          // if the table for the related entity has been created
349
final EntityBridge relatedEntity = cmrField.getRelatedEntity();
350
351          // Only generate indices on foreign key columns if
352
// the table was freshly created. If not, we risk
353
// creating an index twice and get an exception from the DB
354
if(relationMetaData.isForeignKeyMappingStyle() && createdTables.contains(relatedEntity.getEntityName()))
355          {
356             createCMRIndex(((JDBCAbstractEntityBridge)relatedEntity).getDataSource(), cmrField);
357          }
358
359          // Create my fk constraint
360
addForeignKeyConstraint(cmrField);
361       }
362    }
363
364    public static Set JavaDoc getCreatedTables(JDBCEntityPersistenceStore manager)
365    {
366       final String JavaDoc key = "CREATED_TABLES";
367       Set JavaDoc createdTables = (Set JavaDoc) manager.getApplicationData(key);
368       if(createdTables == null)
369       {
370          createdTables = new HashSet JavaDoc();
371          manager.putApplicationData(key, createdTables);
372       }
373       return createdTables;
374    }
375
376    public static Set JavaDoc getExistedTables(JDBCEntityPersistenceStore manager)
377    {
378       final String JavaDoc key = "EXISTED_TABLES";
379       Set JavaDoc existedTables = (Set JavaDoc) manager.getApplicationData(key);
380       if(existedTables == null)
381       {
382          existedTables = new HashSet JavaDoc();
383          manager.putApplicationData(key, existedTables);
384       }
385       return existedTables;
386    }
387
388    /**
389     * Check whether a required index already exists on a table
390     *
391     * @param oldIndexes list of existing indexes
392     * @param field field we test the existence of an index for
393     * @return True if the field has an index; otherwise false
394     */

395    private boolean hasIndex(SQLUtil.OldIndexes oldIndexes, JDBCFieldBridge field)
396    {
397       JDBCType jdbcType = field.getJDBCType();
398       String JavaDoc[] columns = jdbcType.getColumnNames();
399       ArrayList JavaDoc idxNames = oldIndexes.getIndexNames();
400       ArrayList JavaDoc idxColumns = oldIndexes.getColumnNames();
401
402       // check if the columns are in the same index
403
String JavaDoc indexName = null;
404       for(int i = 0; i < columns.length; ++i)
405       {
406          String JavaDoc column = columns[i];
407          int index = columnIndex(idxColumns, column);
408          if(index == -1)
409          {
410             return false;
411          }
412
413          if(indexName == null)
414          {
415             indexName = (String JavaDoc)idxNames.get(index);
416          }
417          else if(!indexName.equals(idxNames.get(index)))
418          {
419             return false;
420          }
421       }
422
423       return true;
424 /*
425 previous implementation
426       ArrayList idxAscDesc = oldIndexes.getColumnAscDesc();
427
428       // search for for column in index
429       if(idxAscDesc != null)
430       {
431          for(int i = 0; i < idxColumns.size(); i++)
432          {
433             // only match ascending columns
434             if("A".equals(idxAscDesc.get(i)))
435             {
436                String name = columns[0];
437                String testCol = (String) idxColumns.get(i);
438                if(testCol.charAt(0) == '\"' &&
439                   testCol.charAt(testCol.charAt(testCol.length() - 1)) == '\"')
440                {
441                   testCol = testCol.substring(1, testCol.length() - 1);
442                }
443
444                if(testCol.equalsIgnoreCase(name))
445                {
446                   // first column matches, now check the others
447                   String idxName = (String) idxNames.get(i);
448                   int j = 1;
449                   for(; j < columns.length; j++)
450                   {
451                      name = columns[j];
452                      testCol = (String) idxColumns.get(i + j);
453                      if(testCol.charAt(0) == '\"' &&
454                         testCol.charAt(testCol.charAt(testCol.length() - 1)) == '\"')
455                      {
456                         testCol = testCol.substring(1, testCol.length() - 1);
457                      }
458
459                      String testName = (String) idxNames.get(i + j);
460                      if(!(testName.equals(idxName)
461                         &&
462                         testCol.equalsIgnoreCase(name)
463                         && idxAscDesc.get(i + j).equals("A")))
464                      {
465                         break;
466                      }
467                   }
468                   // if they all matched -> found
469                   if(j == columns.length) return true;
470                }
471             }
472          }
473       }
474       return false;
475 */

476    }
477
478    private int columnIndex(ArrayList JavaDoc idxColumns, String JavaDoc column)
479    {
480       for(int j = 0; j < idxColumns.size(); ++j)
481       {
482          String JavaDoc idxColumn = (String JavaDoc)idxColumns.get(j);
483          if(idxColumn.charAt(0) == '\"' &&
484             idxColumn.charAt(idxColumn.charAt(idxColumn.length() - 1)) == '\"')
485          {
486             idxColumn = idxColumn.substring(1, idxColumn.length() - 1);
487          }
488
489          if(idxColumn.equalsIgnoreCase(column))
490          {
491             return j;
492          }
493       }
494       return -1;
495    }
496
497    private void alterTable(DataSource JavaDoc dataSource, JDBCFunctionMappingMetaData mapping, String JavaDoc tableName, String JavaDoc fieldName, String JavaDoc fieldStructure)
498       throws DeploymentException
499    {
500       StringBuffer JavaDoc sqlBuf = new StringBuffer JavaDoc();
501       mapping.getFunctionSql( new String JavaDoc[]{tableName, fieldName, fieldStructure}, sqlBuf );
502       String JavaDoc sql = sqlBuf.toString();
503
504       log.warn( sql );
505
506       // suspend the current transaction
507
TransactionManager JavaDoc tm = manager.getContainer().getTransactionManager();
508       Transaction JavaDoc oldTransaction;
509       try
510       {
511          oldTransaction = tm.suspend();
512       }
513       catch(Exception JavaDoc e)
514       {
515          throw new DeploymentException(COULDNT_SUSPEND + " alter table.", e);
516       }
517
518       try
519       {
520          Connection JavaDoc con = null;
521          Statement JavaDoc statement = null;
522          try
523          {
524             con = dataSource.getConnection();
525             statement = con.createStatement();
526             statement.executeUpdate(sql);
527          }
528          finally
529          {
530             // make sure to close the connection and statement before
531
// comitting the transaction or XA will break
532
JDBCUtil.safeClose(statement);
533             JDBCUtil.safeClose(con);
534          }
535       }
536       catch(Exception JavaDoc e)
537       {
538          log.error("Could not alter table " + tableName + ": " + e.getMessage());
539          throw new DeploymentException("Error while alter table " + tableName + " " + sql, e);
540       }
541       finally
542       {
543          try
544          {
545             // resume the old transaction
546
if(oldTransaction != null)
547             {
548                tm.resume(oldTransaction);
549             }
550          }
551          catch(Exception JavaDoc e)
552          {
553             throw new DeploymentException(COULDNT_REATTACH + "alter table");
554          }
555       }
556
557       // success
558
if ( log.isDebugEnabled() )
559          log.debug("Table altered successfully.");
560    }
561
562    private void createTable(DataSource JavaDoc dataSource, String JavaDoc tableName, String JavaDoc sql)
563       throws DeploymentException
564    {
565       // does this table already exist
566
if(SQLUtil.tableExists(tableName, dataSource))
567       {
568          log.debug("Table '" + tableName + "' already exists");
569          return;
570       }
571
572       // since we use the pools, we have to do this within a transaction
573

574       // suspend the current transaction
575
TransactionManager JavaDoc tm = manager.getContainer().getTransactionManager();
576       Transaction JavaDoc oldTransaction;
577       try
578       {
579          oldTransaction = tm.suspend();
580       }
581       catch(Exception JavaDoc e)
582       {
583          throw new DeploymentException(COULDNT_SUSPEND + "creating table.", e);
584       }
585
586       try
587       {
588          Connection JavaDoc con = null;
589          Statement JavaDoc statement = null;
590          try
591          {
592             // execute sql
593
if(log.isDebugEnabled())
594             {
595                log.debug("Executing SQL: " + sql);
596             }
597
598             con = dataSource.getConnection();
599             statement = con.createStatement();
600             statement.executeUpdate(sql);
601          }
602          finally
603          {
604             // make sure to close the connection and statement before
605
// comitting the transaction or XA will break
606
JDBCUtil.safeClose(statement);
607             JDBCUtil.safeClose(con);
608          }
609       }
610       catch(Exception JavaDoc e)
611       {
612          log.debug("Could not create table " + tableName);
613          throw new DeploymentException("Error while creating table " + tableName, e);
614       }
615       finally
616       {
617          try
618          {
619             // resume the old transaction
620
if(oldTransaction != null)
621             {
622                tm.resume(oldTransaction);
623             }
624          }
625          catch(Exception JavaDoc e)
626          {
627             throw new DeploymentException(COULDNT_REATTACH + "create table");
628          }
629       }
630
631       // success
632
Set JavaDoc createdTables = (Set JavaDoc) manager.getApplicationData(CREATED_TABLES_KEY);
633       createdTables.add(tableName);
634    }
635
636    /**
637     * Create an index on a field. Does the create
638     *
639     * @param dataSource
640     * @param tableName In which table is the index?
641     * @param indexName Which is the index?
642     * @param sql The SQL statement to issue
643     * @throws DeploymentException
644     */

645    private void createIndex(DataSource JavaDoc dataSource, String JavaDoc tableName, String JavaDoc indexName, String JavaDoc sql)
646       throws DeploymentException
647    {
648       // we are only called directly after creating a table
649
// since we use the pools, we have to do this within a transaction
650
// suspend the current transaction
651
TransactionManager JavaDoc tm = manager.getContainer().getTransactionManager();
652       Transaction JavaDoc oldTransaction;
653       try
654       {
655          oldTransaction = tm.suspend();
656       }
657       catch(Exception JavaDoc e)
658       {
659          throw new DeploymentException(COULDNT_SUSPEND + "creating index.", e);
660       }
661
662       try
663       {
664          Connection JavaDoc con = null;
665          Statement JavaDoc statement = null;
666          try
667          {
668             // execute sql
669
if(log.isDebugEnabled())
670             {
671                log.debug("Executing SQL: " + sql);
672             }
673             con = dataSource.getConnection();
674             statement = con.createStatement();
675             statement.executeUpdate(sql);
676          }
677          finally
678          {
679             // make sure to close the connection and statement before
680
// comitting the transaction or XA will break
681
JDBCUtil.safeClose(statement);
682             JDBCUtil.safeClose(con);
683          }
684       }
685       catch(Exception JavaDoc e)
686       {
687          log.debug("Could not create index " + indexName + "on table" + tableName);
688          throw new DeploymentException("Error while creating table", e);
689       }
690       finally
691       {
692          try
693          {
694             // resume the old transaction
695
if(oldTransaction != null)
696             {
697                tm.resume(oldTransaction);
698             }
699          }
700          catch(Exception JavaDoc e)
701          {
702             throw new DeploymentException(COULDNT_REATTACH + "create index");
703          }
704       }
705    }
706
707
708    /**
709     * Send (user-defined) SQL commands to the server.
710     * The commands can be found in the &lt;sql-statement&gt; elements
711     * within the &lt;post-table-create&gt; tag in jbossjdbc-cmp.xml
712     *
713     * @param dataSource
714     */

715    private void issuePostCreateSQL(DataSource JavaDoc dataSource, List JavaDoc sql, String JavaDoc table)
716       throws DeploymentException
717    {
718       if(sql == null)
719       { // no work to do.
720
log.trace("issuePostCreateSQL: sql is null");
721          return;
722       }
723
724       log.debug("issuePostCreateSQL::sql: " + sql.toString() + " on table " + table);
725
726       TransactionManager JavaDoc tm = manager.getContainer().getTransactionManager();
727       Transaction JavaDoc oldTransaction;
728
729       try
730       {
731          oldTransaction = tm.suspend();
732       }
733       catch(Exception JavaDoc e)
734       {
735          throw new DeploymentException(COULDNT_SUSPEND + "sending sql command.", e);
736       }
737
738       String JavaDoc currentCmd = "";
739
740       try
741       {
742          Connection JavaDoc con = null;
743          Statement