cool.scx.jdbc.sqlite.SQLiteDialect Maven / Gradle / Ivy
package cool.scx.jdbc.sqlite;
import cool.scx.jdbc.dialect.Dialect;
import cool.scx.jdbc.mapping.Column;
import cool.scx.jdbc.sqlite.type_handler.SQLiteLocalDateTimeTypeHandler;
import org.sqlite.SQLiteDataSource;
import org.sqlite.core.CorePreparedStatement;
import org.sqlite.core.CoreStatement;
import org.sqlite.jdbc4.JDBC4PreparedStatement;
import javax.sql.DataSource;
import java.lang.System.Logger;
import java.lang.reflect.Field;
import java.sql.Driver;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import static cool.scx.util.StringUtils.notBlank;
/**
* @see https://www.sqlite.org/lang_createtable.html
*/
public class SQLiteDialect extends Dialect {
public static final Logger logger = System.getLogger(SQLiteDialect.class.getName());
static final Field CoreStatement_sql;
static final Field CoreStatement_batch;
static final Field CorePreparedStatement_batchQueryCount;
private static final org.sqlite.JDBC DRIVER;
static {
try {
CoreStatement_sql = CoreStatement.class.getDeclaredField("sql");
CoreStatement_batch = CoreStatement.class.getDeclaredField("batch");
CorePreparedStatement_batchQueryCount = CorePreparedStatement.class.getDeclaredField("batchQueryCount");
CoreStatement_sql.setAccessible(true);
CoreStatement_batch.setAccessible(true);
CorePreparedStatement_batchQueryCount.setAccessible(true);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
try {
DRIVER = new org.sqlite.JDBC();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public SQLiteDialect() {
// 注册自定义的 TypeHandler
typeHandlerSelector.registerTypeHandler(LocalDateTime.class, new SQLiteLocalDateTimeTypeHandler());
}
private static String getFinalSQL0(String sql, Object[] batch) {
final StringBuilder sb = new StringBuilder();
int currentParameter = 0;
for (int pos = 0; pos < sql.length(); pos = pos + 1) {
char character = sql.charAt(pos);
if (character == '?' && currentParameter <= batch.length) {
// 替换 ?
Object value = batch[currentParameter];
sb.append(value != null ? value.toString() : "NULL");
currentParameter = currentParameter + 1;
} else {
sb.append(character);
}
}
return sb.toString();
}
@Override
public boolean canHandle(String url) {
return DRIVER.acceptsURL(url);
}
@Override
public boolean canHandle(DataSource dataSource) {
try {
return dataSource instanceof SQLiteDataSource || dataSource.isWrapperFor(SQLiteDataSource.class);
} catch (SQLException e) {
return false;
}
}
@Override
public boolean canHandle(Driver driver) {
return driver instanceof org.sqlite.JDBC;
}
@Override
public String getFinalSQL(Statement statement) {
CorePreparedStatement corePreparedStatement;
try {
corePreparedStatement = statement.unwrap(JDBC4PreparedStatement.class);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
final String sql;
final Object[] batch;
final int batchQueryCount;
try {
sql = (String) CoreStatement_sql.get(corePreparedStatement);
batch = (Object[]) CoreStatement_batch.get(corePreparedStatement);
batchQueryCount = (int) CorePreparedStatement_batchQueryCount.get(corePreparedStatement);
} catch (IllegalAccessException e) {
return null;
}
var finalSQL = getFinalSQL0(sql, batch);
return batchQueryCount > 1 ? finalSQL + "... 额外的 " + (batchQueryCount - 1) + " 项" : finalSQL;
}
@Override
public String getLimitSQL(String sql, Long offset, Long limit) {
var limitClauses = limit == null ? "" : offset == null || offset == 0 ? " LIMIT " + limit : " LIMIT " + offset + "," + limit;
return sql + limitClauses;
}
@Override
public DataSource createDataSource(String url, String username, String password, String[] parameters) {
SQLiteDataSource sqLiteDataSource = new SQLiteDataSource();
sqLiteDataSource.setUrl(url);
return sqLiteDataSource;
}
@Override
public String getDataTypeDefinitionByClass(Class> javaType) {
if (javaType == Integer.class || javaType == Long.class) {
return "INTEGER";
} else if (javaType == String.class) {
return "TEXT";
} else {
return "BLOB";
}
}
/**
* 当前列对象通常的 DDL 如设置 字段名 类型 是否可以为空 默认值等 (建表语句片段 , 需和 specialDDL 一起使用才完整)
*/
@Override
public List getColumnConstraint(Column column) {
var list = new ArrayList();
if (column.primaryKey() && column.autoIncrement()) {
list.add("PRIMARY KEY AUTOINCREMENT");
}
list.add(column.notNull() || column.primaryKey() ? "NOT NULL" : "NULL");
if (column.unique()) {
list.add("UNIQUE");
}
if (notBlank(column.defaultValue())) {
list.add("DEFAULT " + column.defaultValue());
}
return list;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy