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     * SapDB specific Platform implementation.
027     *
028     * <p/>
029     * Many of the database sequence specific properties can be specified using
030     * <em>custom attributes</em> within the <em>sequence-manager</em> element.
031     * <br/>
032     * The database sequence specific properties are generally speaking, see database user guide
033     * for detailed description.
034     *
035     * <p>
036     * Implementation configuration properties:
037     * </p>
038     *
039     * <table cellspacing="2" cellpadding="2" border="3" frame="box">
040     * <tr>
041     *     <td><strong>Property Key</strong></td>
042     *     <td><strong>Property Values</strong></td>
043     * </tr>
044     * <tr>
045     *     <td>sequenceStart</td>
046     *     <td>
047     *          DEPRECATED. Database sequence specific property.<br/>
048     *          Specifies the first sequence number to be
049     *          generated. Allowed: <em>1</em> or greater.
050     *    </td>
051     * </tr>
052     * <tr>
053     *     <td>seq.start</td>
054     *     <td>
055     *          Database sequence specific property.<br/>
056     *          Specifies the first sequence number to be
057     *          generated. Allowed: <em>1</em> or greater.
058     *    </td>
059     * </tr>
060     * <tr>
061     *     <td>seq.incrementBy</td>
062     *     <td>
063     *          Database sequence specific property.<br/>
064     *          Specifies the interval between sequence numbers.
065     *          This value can be any positive or negative
066     *          integer, but it cannot be 0.
067     *    </td>
068     * </tr>
069     * <tr>
070     *     <td>seq.maxValue</td>
071     *     <td>
072     *          Database sequence specific property.<br/>
073     *          Set max value for sequence numbers.
074     *    </td>
075     * </tr>
076     * <tr>
077     *     <td>seq.minValue</td>
078     *     <td>
079     *          Database sequence specific property.<br/>
080     *          Set min value for sequence numbers.
081     *    </td>
082     * </tr>
083     * <tr>
084     *     <td>seq.cycle</td>
085     *     <td>
086     *          Database sequence specific property.<br/>
087     *          If <em>true</em>, specifies that the sequence continues to generate
088     *          values after reaching either its maximum or minimum value.
089     *          <br/>
090     *          If <em>false</em>, specifies that the sequence cannot generate more values after
091     *          reaching its maximum or minimum value.
092     *    </td>
093     * </tr>
094     * <tr>
095     *     <td>seq.cache</td>
096     *     <td>
097     *          Database sequence specific property.<br/>
098     *          Specifies how many values of the sequence Oracle
099     *          preallocates and keeps in memory for faster access.
100     *          Allowed values: <em>2</em> or greater. If set <em>0</em>,
101     *          an explicite <em>nocache</em> expression will be set.
102     *    </td>
103     * </tr>
104     * <tr>
105     *     <td>seq.order</td>
106     *     <td>
107     *          Database sequence specific property.<br/>
108     *          If set <em>true</em>, guarantees that sequence numbers
109     *          are generated in order of request.
110     *          <br/>
111     *          If <em>false</em>, a <em>no order</em> expression will be set.
112     *    </td>
113     * </tr>
114     * </table>
115     *
116     * @author Justin A. Stanczak
117     * @author Matthew Baird (mattb
118     * @version $Id: PlatformSapdbImpl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
119     */
120    public class PlatformSapdbImpl extends PlatformDefaultImpl
121    {
122        public void setObjectForStatement(
123                PreparedStatement ps,
124                int index,
125                Object value,
126                int sqlType)
127                throws SQLException
128        {
129            if(((sqlType == Types.VARBINARY) || (sqlType == Types.LONGVARBINARY))
130                    && (value instanceof byte[]))
131            {
132                byte buf[] = (byte[]) value;
133                ps.setBytes(index, buf);
134            }
135            else
136            {
137                super.setObjectForStatement(ps, index, value, sqlType);
138            }
139        }
140    
141        /**
142         * Get join syntax type for this RDBMS - one on of the constants from JoinSyntaxType interface
143         */
144        public byte getJoinSyntaxType()
145        {
146            return ORACLE_JOIN_SYNTAX;
147        }
148    
149        /**
150         * Override default ResultSet size determination (rs.last();rs.getRow())
151         * with select count(*) operation
152         * SAP db doesn't let you use the .last, .getRow() mechanism (.getRow() will return -1)
153         */
154        public boolean useCountForResultsetSize()
155        {
156            return true;
157        }
158    
159        public String createSequenceQuery(String sequenceName)
160        {
161            return "CREATE SEQUENCE " + sequenceName;
162        }
163    
164        public String createSequenceQuery(String sequenceName, Properties prop)
165        {
166            /*
167            CREATE SEQUENCE [<schema_name>.]<sequence_name>
168                [INCREMENT BY <integer>]
169                [START WITH <integer>]
170                [MAXVALUE <integer> | NOMAXVALUE]
171                [MINVALUE <integer> | NOMINVALUE]
172                [CYCLE | NOCYCLE]
173                [CACHE <unsigned_integer> | NOCACHE]
174                [ORDER|NOORDER]
175            */
176            StringBuffer query = new StringBuffer(createSequenceQuery(sequenceName));
177            if(prop != null)
178            {
179                Boolean b;
180                Long value;
181    
182                value = SequenceManagerHelper.getSeqIncrementBy(prop);
183                if(value != null)
184                {
185                    query.append(" INCREMENT BY ").append(value.longValue());
186                }
187    
188                value = SequenceManagerHelper.getSeqStart(prop);
189                if(value != null)
190                {
191                    query.append(" START WITH ").append(value.longValue());
192                }
193    
194                value = SequenceManagerHelper.getSeqMaxValue(prop);
195                if(value != null)
196                {
197                    query.append(" MAXVALUE ").append(value.longValue());
198                }
199    
200                value = SequenceManagerHelper.getSeqMinValue(prop);
201                if(value != null)
202                {
203                    query.append(" MINVALUE ").append(value.longValue());
204                }
205    
206                b = SequenceManagerHelper.getSeqCycleValue(prop);
207                if(b != null)
208                {
209                    if(b.booleanValue()) query.append(" CYCLE");
210                    else query.append(" NOCYCLE");
211                }
212    
213                value = SequenceManagerHelper.getSeqCacheValue(prop);
214                if(value != null)
215                {
216                    query.append(" CACHE ").append(value.longValue());
217                }
218    
219                b = SequenceManagerHelper.getSeqOrderValue(prop);
220                if(b != null)
221                {
222                    if(b.booleanValue()) query.append(" ORDER");
223                    else query.append(" NOORDER");
224                }
225            }
226            return query.toString();
227        }
228    
229        public String nextSequenceQuery(String sequenceName)
230        {
231            return "select " + sequenceName + ".nextval from dual";
232        }
233    
234        public String dropSequenceQuery(String sequenceName)
235        {
236            return "drop sequence " + sequenceName;
237        }
238    
239        /* (non-Javadoc)
240        * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
241        */
242        public void addPagingSql(StringBuffer anSqlString)
243        {
244            anSqlString.append(" ROWNO <= ? ");
245        }
246    
247        /* (non-Javadoc)
248         * @see org.apache.ojb.broker.platforms.Platform#bindPagingParameters(java.sql.PreparedStatement, int, int, int)
249         */
250        public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException
251        {
252    
253            ps.setInt(index, endAt - 1);    // IGNORE startAt !!
254            index++;
255            return index;
256        }
257    
258        /* (non-Javadoc)
259        * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
260        */
261        public boolean supportsPaging()
262        {
263            return true;
264        }
265    }