Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/objectstyle/cayenne/dba/db2/DB2PkGenerator.java


1   /* ====================================================================
2    * 
3    * The ObjectStyle Group Software License, Version 1.0 
4    *
5    * Copyright (c) 2002-2003 The ObjectStyle Group 
6    * and individual authors of the software.  All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer. 
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution, if
21   *    any, must include the following acknowlegement:  
22   *       "This product includes software developed by the 
23   *        ObjectStyle Group (http://objectstyle.org/)."
24   *    Alternately, this acknowlegement may appear in the software itself,
25   *    if and wherever such third-party acknowlegements normally appear.
26   *
27   * 4. The names "ObjectStyle Group" and "Cayenne" 
28   *    must not be used to endorse or promote products derived
29   *    from this software without prior written permission. For written 
30   *    permission, please contact andrus@objectstyle.org.
31   *
32   * 5. Products derived from this software may not be called "ObjectStyle"
33   *    nor may "ObjectStyle" appear in their names without prior written
34   *    permission of the ObjectStyle Group.
35   *
36   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   * DISCLAIMED.  IN NO EVENT SHALL THE OBJECTSTYLE GROUP OR
40   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   * SUCH DAMAGE.
48   * ====================================================================
49   *
50   * This software consists of voluntary contributions made by many
51   * individuals on behalf of the ObjectStyle Group.  For more
52   * information on the ObjectStyle Group, please see
53   * <http://objectstyle.org/>.
54   *
55   */ 
56  
57  package org.objectstyle.cayenne.dba.db2;
58  
59  import java.sql.Connection;
60  import java.sql.ResultSet;
61  import java.sql.SQLException;
62  import java.sql.Statement;
63  import java.util.ArrayList;
64  import java.util.Collections;
65  import java.util.Iterator;
66  import java.util.List;
67  
68  import org.objectstyle.cayenne.CayenneRuntimeException;
69  import org.objectstyle.cayenne.access.DataNode;
70  import org.objectstyle.cayenne.access.QueryLogger;
71  import org.objectstyle.cayenne.dba.JdbcPkGenerator;
72  import org.objectstyle.cayenne.map.DbEntity;
73  
74  /**
75   * PK Generator for IBM DB2 using sequences.
76   * 
77   * @author Mario Linke, Holger Hoffstaette
78   */
79  public class DB2PkGenerator extends JdbcPkGenerator {
80  
81    public static final String SEQUENCE_PREFIX = "S_";
82  
83    public void createAutoPk(DataNode node, List dbEntities) throws Exception {
84      List sequences = this.getExistingSequences(node);
85      Iterator it = dbEntities.iterator();
86  
87      while (it.hasNext()) {
88        DbEntity ent = (DbEntity) it.next();
89        if (!sequences.contains(sequenceName(ent))) {
90          this.runUpdate(node, this.createSequenceString(ent));
91        }
92      }
93    }
94  
95    public List createAutoPkStatements(List dbEntities) {
96      List list = new ArrayList();
97      Iterator it = dbEntities.iterator();
98  
99      while (it.hasNext()) {
100       DbEntity ent = (DbEntity) it.next();
101       list.add(this.createSequenceString(ent));
102     }
103 
104     return list;
105   }
106   
107   public void dropAutoPk(DataNode node, List dbEntities) throws Exception {
108     List sequences = this.getExistingSequences(node);
109     
110     Iterator it = dbEntities.iterator();
111     while (it.hasNext()) {
112       DbEntity ent = (DbEntity) it.next();
113       if (sequences.contains(this.sequenceName(ent))) {
114         this.runUpdate(node, this.dropSequenceString(ent));
115       }
116     }
117   }
118 
119   public List dropAutoPkStatements(List dbEntities) {
120      List list = new ArrayList();
121      Iterator it = dbEntities.iterator();
122 
123      while (it.hasNext()) {
124        DbEntity ent = (DbEntity) it.next();
125        list.add(this.dropSequenceString(ent));
126      }
127 
128      return list;
129    }  
130   
131   /**
132    * Returns the sequence name for a given table name.
133    */
134   protected String sequenceName(DbEntity ent) {
135     String seqName = SEQUENCE_PREFIX + ent.getName();
136 
137     if (ent.getSchema() != null && ent.getSchema().length() > 0) {
138       seqName = ent.getSchema() + "." + seqName;
139     }
140 
141     return seqName;
142   }  
143   
144   
145   /**
146    * Creates SQL needed for creating a sequence.
147    */
148   protected String createSequenceString(DbEntity ent) {
149     StringBuffer buf = new StringBuffer();
150     buf.append("CREATE SEQUENCE ")
151       .append(this.sequenceName(ent))
152       .append(" START WITH 200")
153       .append(" INCREMENT BY ").append(getPkCacheSize())
154       .append(" NO MAXVALUE ")
155       .append(" NO CYCLE ")
156       .append(" CACHE ").append(getPkCacheSize());
157     return buf.toString();
158   }  
159   
160   /**
161    * Creates SQL needed for dropping a sequence.
162    */
163   protected String dropSequenceString(DbEntity ent) {
164     return "DROP SEQUENCE " + this.sequenceName(ent) + " RESTRICT ";
165   }
166   
167   /**
168    * Creates a new PK from a sequence returned by
169    * <code>
170    * SELECT NEXTVAL FOR sequence_name FROM SYSIBM.SYSDUMMY1 
171    * </code>
172    * SYSIBM.SYSDUMMY1 corresponds to DUAL in Oracle.
173    */
174   protected int pkFromDatabase(DataNode node, DbEntity ent) throws Exception {
175 
176     String seq_name = sequenceName (ent);
177     Connection con = node.getDataSource().getConnection();
178     try {
179       Statement st = con.createStatement();
180       try {
181         String pkQueryString = "SELECT NEXTVAL FOR "
182                     + seq_name
183                     + " FROM SYSIBM.SYSDUMMY1";
184       QueryLogger.logQuery(QueryLogger.DEFAULT_LOG_LEVEL, pkQueryString, Collections.EMPTY_LIST);
185       ResultSet rs = st.executeQuery(pkQueryString);
186       try {
187         if (!rs.next()) {
188         throw new CayenneRuntimeException(
189           "Error in pkFromDatabase() for table "
190           + ent.getName()
191           + " / sequence "
192           + seq_name);
193         }
194         return rs.getInt(1);
195       } finally {
196         rs.close();
197       }
198       } finally {
199       st.close();
200       }
201     } finally {
202       con.close();
203     }
204   }  
205   
206   
207   /**
208    * Returns a List of all existing, accessible sequences.
209    */
210   protected List getExistingSequences(DataNode node) throws SQLException {
211     Connection con = node.getDataSource().getConnection();
212     try {
213       Statement sel = con.createStatement();
214       try {
215         StringBuffer q = new StringBuffer();
216         q.append("SELECT SEQNAME FROM SYSCAT.SEQUENCES WHERE SEQNAME")
217           .append(" LIKE '")
218           .append(SEQUENCE_PREFIX)
219           .append("%'");
220 
221         ResultSet rs = sel.executeQuery(q.toString());
222         try {
223           List sequenceList = new ArrayList(32);
224           while (rs.next()) {
225             sequenceList.add(rs.getString(1));
226           }
227           return sequenceList;
228         } finally {
229           rs.close();
230         }
231       } finally {
232         sel.close();
233       }
234     } finally {
235       con.close();
236     }
237   }  
238 }