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 org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
019    import org.apache.ojb.broker.query.LikeCriteria;
020    
021    import java.sql.CallableStatement;
022    import java.sql.Connection;
023    import java.sql.PreparedStatement;
024    import java.sql.ResultSet;
025    import java.sql.SQLException;
026    import java.sql.Statement;
027    import java.util.Properties;
028    
029    /**
030     * This interface provides callbacks that allow to perform
031     * RDBMS Platform specific operations wherever neccessary.
032     * The Platform implementation is selected by the platform attribute for
033     * each jdbc-connection-descriptor entry in the repository file.
034     *
035     * @version $Id: Platform.java,v 1.1 2007-08-24 22:17:35 ewestfal Exp $
036     * @author       Thomas Mahler
037     */
038    public interface Platform
039    {
040    
041        /**
042         * Called after a statement has been created.
043         */
044        void afterStatementCreate(Statement stmt) throws PlatformException;
045    
046        /**
047         * Called by {@link org.apache.ojb.broker.accesslayer.StatementManagerIF} implementation
048         * before invoking <tt>stmt.close()</tt> method.
049         */
050        void beforeStatementClose(Statement stmt, ResultSet rs) throws PlatformException;
051    
052        /**
053         * Called by {@link org.apache.ojb.broker.accesslayer.StatementManagerIF} implementation
054         * after invoking <tt>stmt.close()</tt> method.
055         */
056        void afterStatementClose(Statement stmt, ResultSet rs) throws PlatformException;
057    
058        /**
059         * Called before batching operations on a statement.
060         * @param stmt the statement you want to batch on
061         * @throws PlatformException
062         */
063        void beforeBatch(PreparedStatement stmt) throws PlatformException;
064    
065        /**
066         * Called when adding statements to current batch.
067         * @param stmt the statement you are adding to the batch
068         * @throws PlatformException
069         */
070        void addBatch(PreparedStatement stmt) throws PlatformException;
071    
072        /**
073         * Executes current batch.
074         * @param stmt the statement you want to execute the batch on
075         * @throws PlatformException
076         */
077        int[] executeBatch(PreparedStatement stmt) throws PlatformException;
078    
079        /**
080         * Called immediately after a JDBC connection has been created by a
081         * ConnectionFactory implementation (not used for DataSource connections).
082         * @param conn the Connection to be initialized
083         */
084        void initializeJdbcConnection(JdbcConnectionDescriptor jcd, Connection conn) throws PlatformException;
085    
086        /**
087         * Used to do a temporary change of the m_connection autoCommit state.
088         * When using this method ensure to reset the original state before
089         * m_connection was returned to pool or closed.
090         * Only when
091         * {@link org.apache.ojb.broker.metadata.JdbcConnectionDescriptor#getUseAutoCommit()} was set to
092         * {@link org.apache.ojb.broker.metadata.JdbcConnectionDescriptor#AUTO_COMMIT_SET_TRUE_AND_TEMPORARY_FALSE}
093         * the change of the autoCommit state take effect.
094         */
095        void changeAutoCommitState(JdbcConnectionDescriptor jcd, Connection con, boolean newState);
096    
097        /**
098         * Called to let the Platform implementation perform any JDBC type-specific operations
099         * needed by the driver when binding positional parameters for a PreparedStatement.
100         */
101        void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType)
102                throws SQLException;
103    
104        /**
105         * Called to let the Platform implementation perform any JDBC type-specific operations
106         * needed by the driver when binding null parameters for a PreparedStatement.
107         */
108        void setNullForStatement(PreparedStatement ps, int index, int sqlType)
109                throws SQLException;
110    
111        /**
112         * Get join syntax type for this RDBMS - one of the constants from JoinSyntaxTypes interface.
113         * @see org.apache.ojb.broker.accesslayer.JoinSyntaxTypes#SQL92_JOIN_SYNTAX
114         * @see org.apache.ojb.broker.accesslayer.JoinSyntaxTypes#SQL92_NOPAREN_JOIN_SYNTAX
115         * @see org.apache.ojb.broker.accesslayer.JoinSyntaxTypes#ORACLE_JOIN_SYNTAX
116         * @see org.apache.ojb.broker.accesslayer.JoinSyntaxTypes#SYBASE_JOIN_SYNTAX
117         */
118        byte getJoinSyntaxType();
119    
120        /**
121         * Override default ResultSet size determination (rs.last();rs.getRow())
122         * with select count(*) operation.
123         */
124        boolean useCountForResultsetSize();
125    
126        /**
127         * If this platform supports the batch operations jdbc 2.0 feature. This is
128         * by driver, so we check the driver's metadata once and set something in
129         * the platform.
130         * @return true if the platform supports batch, false otherwise.
131         */
132        boolean supportsBatchOperations();
133    
134    // arminw: think we can handle this internally
135    //    /**
136    //     * Sets platform information for if the jdbc driver/db combo support
137    //     * batch operations. Will only be checked once, then have same batch
138    //     * support setting for the entire session.
139    //     * @param conn
140    //     */
141    //    void checkForBatchSupport(Connection conn);
142    
143        /**
144         * Returns a query to create a sequence entry.
145         *
146         * @param sequenceName The name of the sequence to create.
147         * @param prop The database specific sequence properties.
148         * @return a sql string to create a sequence
149         */
150        String createSequenceQuery(String sequenceName, Properties prop);
151    
152        /**
153         * Returns a query to create a sequence entry.
154         *
155         * @param sequenceName The name of the sequence to create.
156         * @return a sql string to create a sequence
157         * @deprecated use {@link #createSequenceQuery(String)} instead.
158         */
159        String createSequenceQuery(String sequenceName);
160    
161        /**
162         * Returns a query to obtain the next sequence key.
163         * @return a sql string to get next sequence value
164         */
165        String nextSequenceQuery(String sequenceName);
166    
167        /**
168         * Returns a query to drop a sequence entry.
169         * @return a sql string to drop a sequence
170         */
171        String dropSequenceQuery(String sequenceName);
172    
173        /**
174         * Create stored procedure call for a special sequence manager implementation
175         * {@link org.apache.ojb.broker.util.sequence.SequenceManagerStoredProcedureImpl},
176         * because it seems that jdbc-driver differ in handling of CallableStatement.
177         * <br/>
178         * Note: The out-parameter of the stored procedure must be registered at
179         * first position, because lookup for new long id in the implementation:
180         * <br/>
181         * <pre>
182         * Connection con = broker.serviceConnectionManager().getConnection();
183         * cs = getPlatform().prepareNextValProcedureStatement(con, PROCEDURE_NAME, sequenceName);
184         * cs.executeUpdate();
185         * return cs.getLong(1);
186         * </pre>
187         */
188        CallableStatement prepareNextValProcedureStatement(Connection con, String procedureName,
189                                                           String sequenceName) throws PlatformException;
190    
191        /**
192         * If database supports native key generation via identity column, this
193         * method should return the sql-query to obtain the last generated id.
194         */
195        String getLastInsertIdentityQuery(String tableName);
196    
197        /**
198         * Answer true if LIMIT or equivalent is supported
199         * <b> SQL-Paging is not yet supported </b>
200         */
201        boolean supportsPaging();
202    
203        /**
204         * Add the LIMIT or equivalent to the SQL 
205         * <b> SQL-Paging is not yet supported </b>
206         */
207        void addPagingSql(StringBuffer anSqlString);
208    
209        /**
210         * Answer true if the LIMIT parameters are bound before the query parameters
211         * <b> SQL-Paging is not yet supported </b>
212         */
213        boolean bindPagingParametersFirst();
214    
215        /**
216         * Bind the Paging Parameters
217         * <b> SQL-Paging is not yet supported </b>
218         * @param ps
219         * @param index parameter index
220         * @param startAt
221         * @param endAt
222         */
223        int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException;
224    
225        /**
226         * Whether the platform supports a COUNT DISTINCT across multiple columns.
227         * 
228         * @return <code>true</code> if it is supported
229         */
230        boolean supportsMultiColumnCountDistinct();
231        
232        /**
233         * Concatenate the columns </br>
234         * ie: col1 || col2 || col3 (ANSI)</br>
235         * ie: col1 + col2 + col3 (MS SQL-Server)</br>
236         * ie: concat(col1, col2, col3) (MySql)
237         * 
238         * @param theColumns
239         * @return the concatenated String 
240         */
241        String concatenate(String[] theColumns);
242    
243        /**
244         * Answer the Clause used Escape wildcards in LIKE 
245         * @param aCriteria
246         */
247        String getEscapeClause(LikeCriteria aCriteria);
248    
249    // arminw: Check is not necessary any longer
250    //    /**
251    //     * Determines whether statement is {@link CallableStatement} or not.
252    //     *
253    //     * @param stmt the statement
254    //     * @return true if statement is {@link CallableStatement}.
255    //     */
256    //    boolean isCallableStatement(PreparedStatement stmt);
257    
258        /**
259         * Registers call argument at <code>position</code> as returning
260         * a {@link ResultSet} value.
261         *
262         * @param stmt     the statement
263         * @param position argument position
264         */
265        void registerOutResultSet(CallableStatement stmt, int position)
266                throws SQLException;
267    
268    }