package org.simpleflatmapper.jdbc.impl;
import org.simpleflatmapper.jdbc.JdbcColumnKey;
import org.simpleflatmapper.jdbc.JdbcMapperFactory;
import org.simpleflatmapper.jdbc.SqlTypeColumnProperty;
import org.simpleflatmapper.map.property.AutoGeneratedProperty;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.property.IgnoreAutoGeneratedProperty;
import org.simpleflatmapper.map.property.KeyProperty;
import org.simpleflatmapper.map.mapper.ColumnDefinitionProvider;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class CrudMeta {
private final DatabaseMeta databaseMeta;
private final String table;
private final ColumnMeta[] columnMetas;
public CrudMeta(DatabaseMeta databaseMeta, String table, ColumnMeta[] columnMetas) {
this.databaseMeta = databaseMeta;
this.table = table;
this.columnMetas = columnMetas;
}
public DatabaseMeta getDatabaseMeta() {
return databaseMeta;
}
public String getTable() {
return table;
}
public ColumnMeta[] getColumnMetas() {
return columnMetas;
}
public boolean hasGeneratedKeys() {
for(ColumnMeta cm : columnMetas) {
if (cm.isKey() && cm.isGenerated()) {
return true;
}
}
return false;
}
public static CrudMeta of(Connection connection,
String table,
ColumnDefinitionProvider<FieldMapperColumnDefinition<JdbcColumnKey>, JdbcColumnKey> columnDefinitionProvider) throws SQLException {
Statement statement = connection.createStatement();
try {
ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " WHERE 1 = 2");
try {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
DatabaseMetaData metaData = connection.getMetaData();
DatabaseMeta databaseMeta = new DatabaseMeta(metaData.getDatabaseProductName(), metaData.getDatabaseMajorVersion(), metaData.getDatabaseMinorVersion());
ColumnMeta[] columnMetas = new ColumnMeta[resultSetMetaData.getColumnCount()];
List<String> primaryKeys = getPrimaryKeys(connection, resultSetMetaData, columnDefinitionProvider);
for(int i = 0; i < columnMetas.length; i++) {
String columnName = resultSetMetaData.getColumnName(i + 1);
FieldMapperColumnDefinition<JdbcColumnKey> columnDefinition = columnDefinitionProvider.getColumnDefinition(JdbcColumnKey.of(resultSetMetaData, i + 1));
AutoGeneratedProperty autoGeneratedProperty = columnDefinition.lookFor(AutoGeneratedProperty.class);
if (autoGeneratedProperty == null
&& resultSetMetaData.isAutoIncrement(i + 1)
&& ! columnDefinition.has(IgnoreAutoGeneratedProperty.class)) {
autoGeneratedProperty = AutoGeneratedProperty.DEFAULT;
}
columnMetas[i] = new ColumnMeta(
columnName,
resultSetMetaData.getColumnType(i + 1),
primaryKeys.contains(columnName),
autoGeneratedProperty);
}
return new CrudMeta(databaseMeta, table, columnMetas);
} finally {
resultSet.close();
}
} finally {
statement.close();
}
}
private static List<String> getPrimaryKeys(Connection connection, ResultSetMetaData resultSetMetaData, ColumnDefinitionProvider<FieldMapperColumnDefinition<JdbcColumnKey>, JdbcColumnKey> columnDefinitionProvider) throws SQLException {
List<String> primaryKeys = new ArrayList<String>();
for(int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
JdbcColumnKey key = JdbcColumnKey.of(resultSetMetaData, i);
if (columnDefinitionProvider.getColumnDefinition(key).has(KeyProperty.class)) {
primaryKeys.add(key.getName());
}
}
if (!primaryKeys.isEmpty()) {
return primaryKeys;
}
ResultSet set = connection.getMetaData().getPrimaryKeys(resultSetMetaData.getCatalogName(1), resultSetMetaData.getSchemaName(1), resultSetMetaData.getTableName(1));
try {
while (set.next()) {
primaryKeys.add(set.getString("COLUMN_NAME"));
}
} finally {
set.close();
}
return primaryKeys;
}
public void addColumnProperties(JdbcMapperFactory mapperFactory) {
for(ColumnMeta columnMeta : columnMetas) {
mapperFactory.addColumnProperty(columnMeta.getColumn(), SqlTypeColumnProperty.of(columnMeta.getSqlType()));
if (columnMeta.isKey()) {
mapperFactory.addColumnProperty(columnMeta.getColumn(), KeyProperty.DEFAULT);
}
}
}
}