001/*
002 * HA-JDBC: High-Availability JDBC
003 * Copyright (C) 2012  Paul Ferraro
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Lesser General Public License as published by
007 * the Free Software Foundation, either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Lesser General Public License for more details.
014 *
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018package net.sf.hajdbc.dialect;
019
020import java.sql.Connection;
021import java.sql.DatabaseMetaData;
022import java.sql.SQLException;
023import java.util.Collection;
024import java.util.List;
025import java.util.Map;
026
027import javax.transaction.xa.XAException;
028
029import net.sf.hajdbc.ColumnProperties;
030import net.sf.hajdbc.ColumnPropertiesFactory;
031import net.sf.hajdbc.Database;
032import net.sf.hajdbc.DumpRestoreSupport;
033import net.sf.hajdbc.ForeignKeyConstraint;
034import net.sf.hajdbc.ForeignKeyConstraintFactory;
035import net.sf.hajdbc.IdentifierNormalizer;
036import net.sf.hajdbc.IdentityColumnSupport;
037import net.sf.hajdbc.QualifiedName;
038import net.sf.hajdbc.QualifiedNameFactory;
039import net.sf.hajdbc.SequenceSupport;
040import net.sf.hajdbc.TableProperties;
041import net.sf.hajdbc.TriggerSupport;
042import net.sf.hajdbc.UniqueConstraint;
043import net.sf.hajdbc.UniqueConstraintFactory;
044import net.sf.hajdbc.codec.Decoder;
045
046
047/**
048 * Encapsulates database vendor specific SQL syntax.  
049 * 
050 * @author  Paul Ferraro
051 * @since   1.1
052 */
053public interface Dialect
054{
055        /**
056         * Returns a SQL statement used to truncate a table.
057         * @param properties table meta data
058         * @return a SQL statement
059         * @throws SQLException if there was an error fetching meta data.
060         */
061        String getTruncateTableSQL(TableProperties properties) throws SQLException;
062        
063        /**
064         * Returns a SQL statement used to create a foreign key constraint.
065         * @param constraint foreign key constraint meta data
066         * @return a SQL statement
067         * @throws SQLException if there was an error fetching meta data.
068         */
069        String getCreateForeignKeyConstraintSQL(ForeignKeyConstraint constraint) throws SQLException;
070
071        /**
072         * Returns a SQL statement used to drop a foreign key constraint.
073         * @param constraint foreign key constraint meta data
074         * @return a SQL statement
075         * @throws SQLException if there was an error fetching meta data.
076         */
077        String getDropForeignKeyConstraintSQL(ForeignKeyConstraint constraint) throws SQLException;
078
079        /**
080         * Returns a SQL statement used to create a unique constraint.
081         * @param constraint unique constraint meta data
082         * @return a SQL statement
083         * @throws SQLException if there was an error fetching meta data.
084         */
085        String getCreateUniqueConstraintSQL(UniqueConstraint constraint) throws SQLException;
086
087        /**
088         * Returns a SQL statement used to drop a unique constraint.
089         * @param constraint unique constraint meta data
090         * @return a SQL statement
091         * @throws SQLException if there was an error fetching meta data.
092         */
093        String getDropUniqueConstraintSQL(UniqueConstraint constraint) throws SQLException;
094        
095        /**
096         * Determines whether the specified SQL is a SELECT ... FOR UPDATE statement
097         * @param sql a SQL statement
098         * @return true if this is a SELECT ... FOR UPDATE statement, false if it is not
099         * @throws SQLException if there was an error fetching meta data.
100         */
101        boolean isSelectForUpdate(String sql) throws SQLException;
102        
103        /**
104         * Returns the data type of the specified column of the specified schema and table.
105         * This method is intended to correct JDBC driver type mapping quirks.
106         * @param properties table column meta data
107         * @return the JDBC data type of this column
108         * @throws SQLException 
109         */
110        int getColumnType(ColumnProperties properties) throws SQLException;
111        
112        /**
113         * Returns a search path of schemas 
114         * @param metaData 
115         * @return a list of schema names
116         * @throws SQLException 
117         * @since 2.0
118         */
119        List<String> getDefaultSchemas(DatabaseMetaData metaData) throws SQLException;
120        
121        /**
122         * Replaces non-deterministic CURRENT_DATE functions with deterministic static values.
123         * @param sql an SQL statement
124         * @param date the replacement date
125         * @return an equivalent deterministic SQL statement
126         * @throws SQLException 
127         * @since 2.0.2
128         */
129        String evaluateCurrentDate(String sql, java.sql.Date date);
130        
131        /**
132         * Replaces non-deterministic CURRENT_TIME functions with deterministic static values.
133         * @param sql an SQL statement
134         * @param time the replacement time
135         * @return an equivalent deterministic SQL statement
136         * @throws SQLException 
137         * @since 2.0.2
138         */
139        String evaluateCurrentTime(String sql, java.sql.Time time);
140        
141        /**
142         * Replaces non-deterministic CURRENT_TIMESTAMP functions with deterministic static values.
143         * @param sql an SQL statement
144         * @param timestamp the replacement timestamp
145         * @return an equivalent deterministic SQL statement
146         * @throws SQLException 
147         * @since 2.0.2
148         */
149        String evaluateCurrentTimestamp(String sql, java.sql.Timestamp timestamp);
150        
151        /**
152         * Replaces non-deterministic RAND() functions with deterministic static values.
153         * @param sql an SQL statement
154         * @return an equivalent deterministic SQL statement
155         * @throws SQLException 
156         * @since 2.0.2
157         */
158        String evaluateRand(String sql);
159        
160        /**
161         * Determines whether the specified exception indicates a catastrophic error.
162         * @param e an exception
163         * @return true, if the exception indicates catastrophe, false otherwise
164         */
165        boolean indicatesFailure(SQLException e);
166        
167        /**
168         * Determines whether the specified exception indicates a catastrophic error.
169         * @param e an exception
170         * @return true, if the exception indicates catastrophe, false otherwise
171         */
172        boolean indicatesFailure(XAException e);
173
174        SequenceSupport getSequenceSupport();
175        
176        IdentityColumnSupport getIdentityColumnSupport();
177        
178        DumpRestoreSupport getDumpRestoreSupport();
179        
180        TriggerSupport getTriggerSupport();
181        
182        String getCreateSchemaSQL(String schema);
183        
184        String getDropSchemaSQL(String schema);
185        
186        /**
187         * Returns all tables in this database mapped by schema.
188         * @param metaData a DatabaseMetaData implementation
189         * @return a Map of schema name to Collection of table names
190         * @throws SQLException if an error occurs access DatabaseMetaData
191         */
192        Collection<QualifiedName> getTables(DatabaseMetaData metaData, QualifiedNameFactory factory) throws SQLException;
193
194        /**
195         * Returns the columns of the specified table.
196         * @param metaData a DatabaseMetaData implementation
197         * @param table a schema qualified table name
198         * @return a Map of column name to column properties
199         * @throws SQLException if an error occurs access DatabaseMetaData
200         */
201        Map<String, ColumnProperties> getColumns(DatabaseMetaData metaData, QualifiedName table, ColumnPropertiesFactory factory) throws SQLException;
202
203        /**
204         * Returns the primary key of the specified table.
205         * @param metaData a DatabaseMetaData implementation
206         * @param table a schema qualified table name
207         * @return a unique constraint
208         * @throws SQLException if an error occurs access DatabaseMetaData
209         */
210        UniqueConstraint getPrimaryKey(DatabaseMetaData metaData, QualifiedName table, UniqueConstraintFactory factory) throws SQLException;
211
212        /**
213         * Returns the foreign key constraints on the specified table.
214         * @param metaData a DatabaseMetaData implementation
215         * @param table a schema qualified table name
216         * @return a Collection of foreign key constraints.
217         * @throws SQLException if an error occurs access DatabaseMetaData
218         */
219        Collection<ForeignKeyConstraint> getForeignKeyConstraints(DatabaseMetaData metaData, QualifiedName table, ForeignKeyConstraintFactory factory) throws SQLException;
220
221        /**
222         * Returns the unique constraints on the specified table - excluding the primary key of the table.
223         * @param metaData a schema qualified table name
224         * @param table a qualified table name
225         * @param primaryKey the primary key of this table
226         * @return a Collection of unique constraints.
227         * @throws SQLException if an error occurs access DatabaseMetaData
228         */
229        Collection<UniqueConstraint> getUniqueConstraints(DatabaseMetaData metaData, QualifiedName table, UniqueConstraint primaryKey, UniqueConstraintFactory factory) throws SQLException;
230        
231        /**
232         * Identifies any identity columns from the from the specified collection of columns
233         * @param columns the columns of a table
234         * @return a collection of column names
235         * @throws SQLException
236         */
237        Collection<String> getIdentityColumns(Collection<ColumnProperties> columns) throws SQLException;
238        
239        /**
240         * Returns a mapping of standard JDBC types to native types
241         * @param metaData database meta data
242         * @return a map of JDBC types
243         * @throws SQLException
244         */
245        Map<Integer, Map.Entry<String, Integer>> getTypes(DatabaseMetaData metaData) throws SQLException;
246
247        IdentifierNormalizer createIdentifierNormalizer(DatabaseMetaData metaData) throws SQLException;
248        
249        QualifiedNameFactory createQualifiedNameFactory(DatabaseMetaData metaData, IdentifierNormalizer normalizer) throws SQLException;
250        
251        ColumnPropertiesFactory createColumnPropertiesFactory(IdentifierNormalizer normalizer);
252        
253        ForeignKeyConstraintFactory createForeignKeyConstraintFactory(QualifiedNameFactory factory);
254        
255        UniqueConstraintFactory createUniqueConstraintFactory(IdentifierNormalizer normalizer);
256        
257        boolean isValid(Connection connection) throws SQLException;
258        
259        <Z, D extends Database<Z>> ConnectionProperties getConnectionProperties(D database, Decoder decoder) throws SQLException;
260}