001    package org.apache.ojb.broker.platforms;
002    
003    /* Copyright 2002-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import java.sql.PreparedStatement;
019    import java.sql.SQLException;
020    import java.sql.Types;
021    import java.util.Properties;
022    
023    import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
024    
025    /**
026     * This class extends <code>PlatformDefaultImpl</code> and defines specific
027     * behavior for the DB2 platform.
028     *
029     * <p/>
030     * Many of the database sequence specific properties can be specified using
031     * <em>custom attributes</em> within the <em>sequence-manager</em> element.
032     * <br/>
033     * The database sequence specific properties are generally speaking, see database user guide
034     * for detailed description.
035     *
036     * <p>
037     * Supported properties on sequence creation:
038     * </p>
039     *
040     * <table cellspacing="2" cellpadding="2" border="3" frame="box">
041     * <tr>
042     *     <td><strong>Property Key</strong></td>
043     *     <td><strong>Property Values</strong></td>
044     * </tr>
045     * <tr>
046     *     <td>seq.as</td>
047     *     <td>
048     *          Database sequence specific property.<br/>
049     *          Specifies the datatype used for the sequence.
050     *          Allowed: all numeric datatypes? e.g. <em>INTEGER</em>
051     *    </td>
052     * </tr>
053     * <tr>
054     *     <td>sequenceStart</td>
055     *     <td>
056     *          DEPRECATED. Database sequence specific property.<br/>
057     *          Specifies the first sequence number to be
058     *          generated. Allowed: <em>1</em> or greater.
059     *    </td>
060     * </tr>
061     * <tr>
062     *     <td>seq.start</td>
063     *     <td>
064     *          Database sequence specific property.<br/>
065     *          Specifies the first sequence number to be
066     *          generated. Allowed: <em>1</em> or greater.
067     *    </td>
068     * </tr>
069     * <tr>
070     *     <td>seq.incrementBy</td>
071     *     <td>
072     *          Database sequence specific property.<br/>
073     *          Specifies the interval between sequence numbers.
074     *          This value can be any positive or negative
075     *          integer, but it cannot be 0.
076     *    </td>
077     * </tr>
078     * <tr>
079     *     <td>seq.maxValue</td>
080     *     <td>
081     *          Database sequence specific property.<br/>
082     *          Set max value for sequence numbers.
083     *    </td>
084     * </tr>
085     * <tr>
086     *     <td>seq.minValue</td>
087     *     <td>
088     *          Database sequence specific property.<br/>
089     *          Set min value for sequence numbers.
090     *    </td>
091     * </tr>
092     * <tr>
093     *     <td>seq.cycle</td>
094     *     <td>
095     *          Database sequence specific property.<br/>
096     *          If <em>true</em>, specifies that the sequence continues to generate
097     *          values after reaching either its maximum or minimum value.
098     *          <br/>
099     *          If <em>false</em>, specifies that the sequence cannot generate more values after
100     *          reaching its maximum or minimum value.
101     *    </td>
102     * </tr>
103     * <tr>
104     *     <td>seq.cache</td>
105     *     <td>
106     *          Database sequence specific property.<br/>
107     *          Specifies how many values of the sequence Oracle
108     *          preallocates and keeps in memory for faster access.
109     *          Allowed values: <em>2</em> or greater. If set <em>0</em>,
110     *          an explicite <em>nocache</em> expression will be set.
111     *    </td>
112     * </tr>
113     * <tr>
114     *     <td>seq.order</td>
115     *     <td>
116     *          Database sequence specific property.<br/>
117     *          If set <em>true</em>, guarantees that sequence numbers
118     *          are generated in order of request.
119     *          <br/>
120     *          If <em>false</em>, a <em>no order</em> expression will be set.
121     *    </td>
122     * </tr>
123     * </table>
124     *
125     * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
126     * @version $Id: PlatformDb2Impl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
127     */
128    public class PlatformDb2Impl extends PlatformDefaultImpl
129    {
130        /**
131         * Patch provided by Avril Kotzen (hi001@webmail.co.za)
132         * DB2 handles TINYINT (for mapping a byte).
133         */
134        public void setObjectForStatement(PreparedStatement ps, int index,
135                                          Object value, int sqlType) throws SQLException
136        {
137            if (sqlType == Types.TINYINT)
138            {
139                ps.setByte(index, ((Byte) value).byteValue());
140            }
141            else
142            {
143                super.setObjectForStatement(ps, index, value, sqlType);
144            }
145        }
146    
147        public String createSequenceQuery(String sequenceName)
148        {
149            return "create sequence " + sequenceName;
150        }
151    
152        public String createSequenceQuery(String sequenceName, Properties prop)
153        {
154            /*
155            Read syntax diagramSkip visual syntax diagram
156                                                  .-AS INTEGER----.
157            >>-CREATE SEQUENCE--sequence-name--*--+---------------+--*------>
158                                                  '-AS--data-type-'
159    
160            >--+------------------------------+--*-------------------------->
161               '-START WITH--numeric-constant-'
162    
163               .-INCREMENT BY 1-----------------.
164            >--+--------------------------------+--*------------------------>
165               '-INCREMENT BY--numeric-constant-'
166    
167               .-NO MINVALUE----------------.
168            >--+----------------------------+--*---------------------------->
169               '-MINVALUE--numeric-constant-'
170    
171               .-NO MAXVALUE----------------.     .-NO CYCLE-.
172            >--+----------------------------+--*--+----------+--*----------->
173               '-MAXVALUE--numeric-constant-'     '-CYCLE----'
174    
175               .-CACHE 20----------------.     .-NO ORDER-.
176            >--+-------------------------+--*--+----------+--*-------------><
177               +-CACHE--integer-constant-+     '-ORDER----'
178               '-NO CACHE----------------'
179            */
180            StringBuffer query = new StringBuffer(createSequenceQuery(sequenceName));
181            if(prop != null)
182            {
183                Boolean b;
184                Long value;
185                String str;
186    
187                str = SequenceManagerHelper.getSeqAsValue(prop);
188                if(str != null)
189                {
190                    query.append(" AS ").append(str);
191                }
192    
193                value = SequenceManagerHelper.getSeqStart(prop);
194                if(value != null)
195                {
196                    query.append(" START WITH ").append(value.longValue());
197                }
198    
199                value = SequenceManagerHelper.getSeqIncrementBy(prop);
200                if(value != null)
201                {
202                    query.append(" INCREMENT BY ").append(value.longValue());
203                }
204    
205                value = SequenceManagerHelper.getSeqMinValue(prop);
206                if(value != null)
207                {
208                    query.append(" MINVALUE ").append(value.longValue());
209                }
210    
211                value = SequenceManagerHelper.getSeqMaxValue(prop);
212                if(value != null)
213                {
214                    query.append(" MAXVALUE ").append(value.longValue());
215                }
216    
217                b = SequenceManagerHelper.getSeqCycleValue(prop);
218                if(b != null)
219                {
220                    if(b.booleanValue()) query.append(" CYCLE");
221                    else query.append(" NO CYCLE");
222                }
223    
224                value = SequenceManagerHelper.getSeqCacheValue(prop);
225                if(value != null)
226                {
227                    query.append(" CACHE ").append(value.longValue());
228                }
229    
230                b = SequenceManagerHelper.getSeqOrderValue(prop);
231                if(b != null)
232                {
233                    if(b.booleanValue()) query.append(" ORDER");
234                    else query.append(" NO ORDER");
235                }
236            }
237            return query.toString();
238        }
239    
240        public String nextSequenceQuery(String sequenceName)
241        {
242            return "values nextval for "+ sequenceName;
243        }
244    
245        public String dropSequenceQuery(String sequenceName)
246        {
247            return "drop sequence " + sequenceName;
248        }
249    
250        public String getLastInsertIdentityQuery(String tableName)
251        {
252            // matthias.roth@impart.ch
253            // the function is used by the org.apache.ojb.broker.util.sequence.SequenceManagerNativeImpl
254                    // this call must be made before commit the insert command, so you
255            // must turn off autocommit by seting the useAutoCommit="2"
256            // or use useAutoCommit="1" or use a connection with autoCommit set false
257            // by default (e.g. in managed environments)
258            // transaction demarcation is mandatory
259            return "values IDENTITY_VAL_LOCAL()";
260        }
261    }