All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.simpleflatmapper.jdbc.impl.CrudMeta Maven / Gradle / Ivy

package org.simpleflatmapper.jdbc.impl;

import org.simpleflatmapper.jdbc.JdbcColumnKey;
import org.simpleflatmapper.jdbc.JdbcMapperFactory;
import org.simpleflatmapper.jdbc.SqlTypeColumnProperty;
import org.simpleflatmapper.map.mapper.ColumnDefinition;
import org.simpleflatmapper.map.property.AutoGeneratedProperty;
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.SQLSyntaxErrorException;
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 schema, String table, ColumnMeta[] columnMetas) {
        this(databaseMeta, toProtectedFullyQualifiedName(schema, table, databaseMeta), 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 columnDefinitionProvider) throws SQLException {

        DatabaseMetaData metaData = connection.getMetaData();
        DatabaseMeta databaseMeta = new DatabaseMeta(metaData.getDatabaseProductName(), metaData.getDatabaseMajorVersion(), metaData.getDatabaseMinorVersion());

        Statement statement = connection.createStatement();
        try {
            ResultSet resultSet = statement.executeQuery("SELECT * FROM " + table + " WHERE 1 = 2");
            try {
                return getCrudMeta(connection, table, columnDefinitionProvider, resultSet, databaseMeta);
            } finally {
                resultSet.close();
            }
        } catch (SQLException e) {
            ResultSet resultSet = statement.executeQuery(selectProtected(table, databaseMeta));
            try { // try exact match
                return getCrudMeta(connection, CrudMeta.protectField(table, databaseMeta), columnDefinitionProvider, resultSet, databaseMeta);
            } finally {
                resultSet.close();
            }
        } finally {
            statement.close();
        }

    }

    private static String protectField(String table, DatabaseMeta databaseMeta) {
        StringBuilder sb = new StringBuilder();
        appendProtectedField(sb, table, databaseMeta);
        return sb.toString();
    }

    private static String selectProtected(String table, DatabaseMeta dm) {
        StringBuilder sb = new StringBuilder("SELECT * FROM ");
        appendProtectedField(sb, table, dm);
        sb.append(" WHERE 1 = 2");
        return sb.toString();
    }

    private static CrudMeta getCrudMeta(Connection connection, String table, ColumnDefinitionProvider columnDefinitionProvider, ResultSet resultSet, DatabaseMeta databaseMeta) throws SQLException {
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();

        ColumnMeta[] columnMetas = new ColumnMeta[resultSetMetaData.getColumnCount()];
        List primaryKeys = getPrimaryKeys(connection, resultSetMetaData, columnDefinitionProvider);

        
        int length = columnMetas.length;
        
        for(int i = 0; i < length; i++) {
            String columnName = resultSetMetaData.getColumnName(i + 1);
            

            ColumnDefinition 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);
    }

    private static List getPrimaryKeys(Connection connection, ResultSetMetaData resultSetMetaData, ColumnDefinitionProvider columnDefinitionProvider) throws SQLException {
        List primaryKeys = new ArrayList();

        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;
        }

        String catalogName = resultSetMetaData.getCatalogName(1);
        String schemaName = resultSetMetaData.getSchemaName(1);
        String tableName = resultSetMetaData.getTableName(1);
        
        try {
            ResultSet set = connection.getMetaData().getPrimaryKeys(catalogName, schemaName, tableName);
            try {
                while (set.next()) {
                    primaryKeys.add(set.getString("COLUMN_NAME"));
                }
            } finally {
                set.close();
            }
        } catch (SQLSyntaxErrorException e) {
            // ignore likely mysql view issues
        }
        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);
            }
        }
    }

    public boolean hasNoUpdatableFields() {
        for(ColumnMeta cm : getColumnMetas()) {
            if (!cm.isKey()) return false;
        }
        return true;
    }


    public StringBuilder appendProtectedField(StringBuilder sb, String value) {
        return appendProtectedField(sb, value, this.databaseMeta);
    }


    public void appendTableName(StringBuilder sb) {
        sb.append(table);
    }

    public static StringBuilder appendProtectedField(StringBuilder sb, String value, DatabaseMeta databaseMeta) {
        char c = '"';
        if (databaseMeta.isMysql()) {
            c = '`';
        }
        return sb.append(c).append(value).append(c);
    }

    public static String toProtectedFullyQualifiedName(String schema, String table, DatabaseMeta databaseMeta) {
        StringBuilder sb = new StringBuilder();
        
        if (schema != null && schema.length() > 0) {
            appendProtectedField(sb, schema, databaseMeta);
            sb.append(".");
        }

        appendProtectedField(sb, table, databaseMeta);

        return sb.toString();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy