/* * JEF - Copyright 2009-2010 Jiyi (mr.jiyi@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jef.database.dialect; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Statement; import java.util.Date; import java.util.List; import java.util.Map; import javax.sql.rowset.CachedRowSet; import jef.database.ConnectInfo; import jef.database.DbFunction; import jef.database.DbMetaData; import jef.database.datasource.DataSourceInfo; import jef.database.dialect.handler.LimitHandler; import jef.database.dialect.type.AColumnMapping; import jef.database.dialect.type.AutoIncrementMapping; import jef.database.dialect.type.ParserFactory; import jef.database.exception.ViolatedConstraintNameExtracter; import jef.database.jdbc.JDBCTarget; import jef.database.jsqlparser.expression.BinaryExpression; import jef.database.jsqlparser.expression.Function; import jef.database.jsqlparser.expression.Interval; import jef.database.meta.DbProperty; import jef.database.meta.Feature; import jef.database.meta.FunctionMapping; import jef.database.meta.SequenceInfo; import jef.database.support.RDBMS; import jef.database.wrapper.clause.InsertSqlClause; /** * 这个类原本只用于SQL方言的转换,今后将逐渐代替dbmsprofile的作用 * * @author Administrator * */ public interface DatabaseDialect { /** * 得到RDBMS的名称 * * @return */ RDBMS getName(); /** * 在创建数据库连接之前,在datasource中增加一些properties的值。用于指定一些连接属性。 * 比如今后可以对MYSQL的fetchSize,隔离级别等进行设置 * * 目前仅对oracle作了处理。 * * @param dsw */ void processConnectProperties(DataSourceInfo dsw); /** * 得到用于建表的数据类型 * * @param vType * @param typeStrOnly * 为true时,只返回数据类型,不返回not null default等值 */ String getCreationComment(ColumnType vType, boolean typeStrOnly); /** * 得到该数据库上该种数据类型的真实实现类型。 * 比如,在不支持boolean类型的数据库上,会以char类型代替boolean;在不支持blob的数据库上,会以varbinary类型代替blob * * @param vType * @return */ int getImplementationSqlType(int sqlType); /** * 将表达式或值转换为文本形式的缺省值描述 * @param defaultValue * @param sqlType * @return */ String toDefaultString(Object defaultValue, int sqlType,int changeTo); /** * 得到用于缓存结果的resultSet的实例(备注,Oracle需要特别的容器) */ CachedRowSet newCacheRowSetInstance() throws SQLException; /** * 已知数据库中的字段类型,返回JEF对应的meta类型 */ ColumnType getProprtMetaFromDbType(jef.database.meta.Column dbTypeName); /** * 判断数据库是否不支持某项特性 * * @param feature * @return */ boolean notHas(Feature feature); /** * 判断数据库是否支持某项特性 * * @param feature * @return */ boolean has(Feature feature); /** * 像Oracle,其Catlog是不用的,那么返回null mySQL没有Schema,每个database是一个catlog,那么返回值 * 同时修正返回的大小写 * * @param schema * @return */ String getCatlog(String schema); /** * 对于表名前缀的XX. MYSQL是作为catlog的,不是作为schema的 同时修正返回的大小写 * * @param schema * @return */ String getSchema(String schema); /** * 获取数据库的默认驱动类 * * @param url * Derby根据连接方式的不同,会有两种不同的DriverClass,因此需要传入url * @return 驱动类 */ String getDriverClass(String url); /** * 生成数据库连接字串 * * @param host * <=0则会使用默认端口 * @param port * @param filepath * @param dbname * @return */ String generateUrl(String host, int port, String pathOrName); /** * 得到分页管理器 * @return */ LimitHandler getLimitHandler(); /** * Oracle会将所有未加引号的数据库对象名称都按照大写对象名来处理,MySQL则对表名一律转小写,列名则保留原来的大小写。 * 为了体现这一数据库策略的不同,这里处理大小写的问题。 * * 目前的原则是:凡是涉及 * schema/table/view/sequence/dbname等转换的,都是用此方法,凡是设计列名转换,列别名定义的都用 * {@link #getColumnNameIncase}方法 * * @param name * @return */ String getObjectNameToUse(String name); /** * 获得大小写正确的列名 * @param name * @return */ String getColumnNameToUse(AColumnMapping name); /** * 根据数据库特性,从数据库系统表中返回序列信息,如果不支持则返回null。如果不存在返回空列表 * @param conn * @param schema 允许为null。可以使用% * @param seqName 允许为null。可以使用% */ List<SequenceInfo> getSequenceInfo(DbMetaData conn, String schema, String seqName); /** * 当使用Timestamp类型的绑定变量操作时,转换为什么值 * * @param timestamp * @return */ java.sql.Timestamp toTimestampSqlParam(Date timestamp); /** * 当出现异常时,使用此方法检查这个异常是否因为网络连接异常引起的。<br> * 如果是那么会触发连接池的检查、清洗和重连等操作。 * * @param se * @return */ boolean isIOError(SQLException se); /** * 根据 JDBC的URL,解析出其中的dbname,host,user等信息。目的是为了在不必连接数据库的情况下,得到数据库名称 * * @param connectInfo */ public void parseDbInfo(ConnectInfo connectInfo); /** * 返回指定的属性 * * @return */ public String getProperty(DbProperty key); /** * 返回指定的属性 * * @return */ public String getProperty(DbProperty key, String defaultValue); /** * 返回指定属性,如果无值返回0 * @param key * @return */ public int getPropertyInt(DbProperty key); /** * 返回指定属性,如果无值返回0 * @param key * @return */ public long getPropertyLong(DbProperty key); /** * 不同数据库登录后,所在的默认schema是不一样的 * <ul> * <li>Oracle是以登录的用户名作为schema的。</li> * <li>mysql是只有catlog不区分schema的。</li> * <li>derby支持匿名访问,此时好像是位于APP这个schema下。</li> * <li>SQL Server默认是在dbo这个schema下</li> * </ul> * <br>因此对于无法确定当前schema的场合,使用这里提供的schema名称作为当前schema * @return */ String getDefaultSchema(); /** * 返回所有支持的SQL函数 四种情况 * <ul> * <li>1、数据库的函数已经实现了所需要的标准函数。无需任何更改</li> * <li>2、数据库的函数和标准函数参数含义(基本)一样,仅需变化一下名称,如 nvl -> ifnull</li> * <li>3、数据库的函数和标准函数差别较大,通过多个其他函数模拟实现。(参数一致)</li> * <li>4、数据库的无法实现指定的函数。</li> * </ul> * * @return */ Map<String, FunctionMapping> getFunctions(); /** * 返回所有标准函数 * * @return */ Map<DbFunction, FunctionMapping> getFunctionsByEnum(); /** * 返回指定的函数的SQL实现(不会查找自定义的函数) * * @param function * @param params * @return */ String getFunction(DbFunction function, Object... params); /** * SQL语法处理 * * @param parent * @param interval */ void processIntervalExpression(BinaryExpression parent, Interval interval); /** * SQL语法处理 * * @param func * @param interval */ void processIntervalExpression(Function func, Interval interval); /** * 检查数据库是否包含指定的关键字,用来进行检查的对象名称都是按照getColumnNameIncase转换后的,因此对于大小写统一的数据库, * 这里无需考虑传入的大小写问题。 * * @param name * @return */ boolean containKeyword(String name); /** * 针对非绑定变量SQL,生成SQL语句所用的文本值。 Java -> SQL String */ String getSqlDateExpression(Date value); /** * 针对非绑定变量SQL,生成SQL语句所用的文本值。 Java -> SQL String */ String getSqlTimeExpression(Date value); /** * 针对非绑定变量SQL,生成SQL语句所用的文本值。 Java -> SQL String */ String getSqlTimestampExpression(Date value); /** * 当使用了列自增的方式时,尝试在不插入列的情况下消耗一个自增值。 * * @param meta * @return */ long getColumnAutoIncreamentValue(AutoIncrementMapping mapping, JDBCTarget db); /** * 允许数据库方言对Statement再进行一次包装 * * @param stmt * @param isInJpaTx * @return */ Statement wrap(Statement stmt, boolean isInJpaTx) throws SQLException; /** * 允许数据库方言对PreparedStatement再进行一次包装 * * @param stmt * @param isInJpaTx * @return */ PreparedStatement wrap(PreparedStatement stmt, boolean isInJpaTx) throws SQLException; /** * 当有一个数据库实例连接初次创建时调用. Dialect可以通过直接连接数据库判断版本、函数等,调整Dialect内部的一些配置和数据。 * * @param db */ void accept(DbMetaData db); /** * 将插入语句转化为最快操作的语句 * * @param sql */ void toExtremeInsert(InsertSqlClause sql); /** * 获得SQL解析器。目前内置了两套解析器,一套是作者基于JavaCC自行编写的,性能较差,一套是直接使用Druid的SQL解析器. * Druid解析器是分不同的数据库语法的,因此要根据数据库类型来获得对应的解析器 * @return */ ParserFactory getParserFactory(); /** * 从异常信息中解析出约束冲突的信息。此处返回约束冲突的解析器 * @return * @see ViolatedConstraintNameExtracter */ ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter(); /** * 数据库对象是否为大小写敏感的 * 一般来说对应引号中的表名列名都是大小写敏感的。此处仅指没有引号的情况下是否大小写敏感 * @return */ boolean isCaseSensitive(); }