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.query.LikeCriteria;
024    import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
025    
026    /**
027     * This class extends <code>PlatformDefaultImpl</code> and defines specific
028     * behavior for the PostgreSQL platform.
029     *
030     * <p/>
031     * Many of the database sequence specific properties can be specified using
032     * <em>custom attributes</em> within the <em>sequence-manager</em> element.
033     * <br/>
034     * The database sequence specific properties are generally speaking, see database user guide
035     * for detailed description.
036     *
037     * <p>
038     * Implementation configuration properties:
039     * </p>
040     *
041     * <table cellspacing="2" cellpadding="2" border="3" frame="box">
042     * <tr>
043     *     <td><strong>Property Key</strong></td>
044     *     <td><strong>Property Values</strong></td>
045     * </tr>
046     * <tr>
047     *     <td>sequenceStart</td>
048     *     <td>
049     *          DEPRECATED. Database sequence specific property.<br/>
050     *          Specifies the first sequence number to be
051     *          generated. Allowed: <em>1</em> or greater.
052     *    </td>
053     * </tr>
054     * <tr>
055     *     <td>seq.start</td>
056     *     <td>
057     *          Database sequence specific property.<br/>
058     *          Specifies the first sequence number to be
059     *          generated. Allowed: <em>1</em> or greater.
060     *    </td>
061     * </tr>
062     * <tr>
063     *     <td>seq.incrementBy</td>
064     *     <td>
065     *          Database sequence specific property.<br/>
066     *          Specifies the interval between sequence numbers.
067     *          This value can be any positive or negative
068     *          integer, but it cannot be 0.
069     *    </td>
070     * </tr>
071     * <tr>
072     *     <td>seq.maxValue</td>
073     *     <td>
074     *          Database sequence specific property.<br/>
075     *          Set max value for sequence numbers.
076     *    </td>
077     * </tr>
078     * <tr>
079     *     <td>seq.minValue</td>
080     *     <td>
081     *          Database sequence specific property.<br/>
082     *          Set min value for sequence numbers.
083     *    </td>
084     * </tr>
085     * <tr>
086     *     <td>seq.cycle</td>
087     *     <td>
088     *          Database sequence specific property.<br/>
089     *          If <em>true</em>, specifies that the sequence continues to generate
090     *          values after reaching either its maximum or minimum value.
091     *          <br/>
092     *          If <em>false</em>, specifies that the sequence cannot generate more values after
093     *          reaching its maximum or minimum value.
094     *    </td>
095     * </tr>
096     * <tr>
097     *     <td>seq.cache</td>
098     *     <td>
099     *          Database sequence specific property.<br/>
100     *          Specifies how many values of the sequence Oracle
101     *          preallocates and keeps in memory for faster access.
102     *          Allowed values: <em>2</em> or greater. If set <em>0</em>,
103     *          an explicite <em>nocache</em> expression will be set.
104     *    </td>
105     * </tr>
106     * <tr>
107     *     <td>seq.order</td>
108     *     <td>
109     *          Database sequence specific property.<br/>
110     *          If set <em>true</em>, guarantees that sequence numbers
111     *          are generated in order of request.
112     *          <br/>
113     *          If <em>false</em>, a <em>no order</em> expression will be set.
114     *    </td>
115     * </tr>
116     * </table>
117     *
118     * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
119     * @version $Id: PlatformPostgreSQLImpl.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
120     */
121    
122    public class PlatformPostgreSQLImpl extends PlatformDefaultImpl
123    {
124        public void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType) throws SQLException
125        {
126            if ((value instanceof byte[]) && (sqlType == Types.LONGVARBINARY))
127            {
128                ps.setBytes(index, (byte[]) value);
129            }
130            else
131            {
132                super.setObjectForStatement(ps, index, value, sqlType);
133            }
134        }
135    
136        public String createSequenceQuery(String sequenceName)
137        {
138            return "create sequence " + sequenceName;
139        }
140    
141        public String createSequenceQuery(String sequenceName, Properties prop)
142        {
143            /*
144            CREATE [ TEMPORARY | TEMP ] SEQUENCE seqname [ INCREMENT increment ]
145                [ MINVALUE minvalue ] [ MAXVALUE maxvalue ]
146                [ START start ] [ CACHE cache ] [ CYCLE ]
147            */
148            StringBuffer query = new StringBuffer(createSequenceQuery(sequenceName));
149            if(prop != null)
150            {
151                Boolean b;
152                Long value;
153    
154                value = SequenceManagerHelper.getSeqIncrementBy(prop);
155                if(value != null)
156                {
157                    query.append(" INCREMENT ").append(value.longValue());
158                }
159    
160                value = SequenceManagerHelper.getSeqMinValue(prop);
161                if(value != null)
162                {
163                    query.append(" MINVALUE ").append(value.longValue());
164                }
165    
166                value = SequenceManagerHelper.getSeqMaxValue(prop);
167                if(value != null)
168                {
169                    query.append(" MAXVALUE ").append(value.longValue());
170                }
171    
172                value = SequenceManagerHelper.getSeqStart(prop);
173                if(value != null)
174                {
175                    query.append(" START ").append(value.longValue());
176                }
177    
178                value = SequenceManagerHelper.getSeqCacheValue(prop);
179                if(value != null)
180                {
181                    query.append(" CACHE ").append(value.longValue());
182                }
183    
184                b = SequenceManagerHelper.getSeqCycleValue(prop);
185                if(b != null)
186                {
187                    if(b.booleanValue()) query.append(" CYCLE");
188                }
189            }
190            return query.toString();
191        }
192    
193        public String nextSequenceQuery(String sequenceName)
194        {
195            return "select nextval('" + sequenceName + "')";
196        }
197    
198        public String dropSequenceQuery(String sequenceName)
199        {
200            return "drop sequence " + sequenceName;
201        }
202    
203        /* (non-Javadoc)
204        * @see org.apache.ojb.broker.platforms.Platform#addPagingSql(java.lang.StringBuffer)
205        */
206        public void addPagingSql(StringBuffer anSqlString)
207        {
208            anSqlString.append(" LIMIT ? OFFSET ?");
209        }
210    
211        /* (non-Javadoc)
212        * @see org.apache.ojb.broker.platforms.Platform#supportsPaging()
213        */
214        public boolean supportsPaging()
215        {
216            return true;
217        }
218    
219        /* (non-Javadoc)
220         * @see org.apache.ojb.broker.platforms.Platform#bindPagingParameters(java.sql.PreparedStatement, int, int, int)
221         */
222        public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException
223        {
224            ps.setInt(index, endAt - (startAt - 1));    // number of rows to fetch
225            index++;
226            ps.setInt(index, startAt - 1);              // zero based start
227            index++;
228            return index;
229        }
230    
231        /**
232         * @see org.apache.ojb.broker.platforms.Platform#getEscapeClause(org.apache.ojb.broker.query.LikeCriteria)
233         */
234        public String getEscapeClause(LikeCriteria aCriteria)
235        {
236            if (LikeCriteria.getEscapeCharacter() != LikeCriteria.DEFAULT_ESCPAPE_CHARACTER)
237            {
238                // the default escape character is \, so there's no need for an escape clause
239                return super.getEscapeClause(aCriteria);
240            }
241            else
242            {
243                return "";
244            }
245        }
246    }