Search in sources :

Example 16 with ColumnMeta

use of io.seata.rm.datasource.sql.struct.ColumnMeta in project seata by seata.

the class MysqlTableMetaCache method resultSetMetaToSchema.

private TableMeta resultSetMetaToSchema(ResultSetMetaData rsmd, DatabaseMetaData dbmd) throws SQLException {
    // always "" for mysql
    String schemaName = rsmd.getSchemaName(1);
    String catalogName = rsmd.getCatalogName(1);
    /*
         * use ResultSetMetaData to get the pure table name
         * can avoid the problem below
         *
         * select * from account_tbl
         * select * from account_TBL
         * select * from `account_tbl`
         * select * from account.account_tbl
         */
    String tableName = rsmd.getTableName(1);
    TableMeta tm = new TableMeta();
    tm.setTableName(tableName);
    try (ResultSet rsColumns = dbmd.getColumns(catalogName, schemaName, tableName, "%");
        ResultSet rsIndex = dbmd.getIndexInfo(catalogName, schemaName, tableName, false, true)) {
        while (rsColumns.next()) {
            ColumnMeta col = new ColumnMeta();
            col.setTableCat(rsColumns.getString("TABLE_CAT"));
            col.setTableSchemaName(rsColumns.getString("TABLE_SCHEM"));
            col.setTableName(rsColumns.getString("TABLE_NAME"));
            col.setColumnName(rsColumns.getString("COLUMN_NAME"));
            col.setDataType(rsColumns.getInt("DATA_TYPE"));
            col.setDataTypeName(rsColumns.getString("TYPE_NAME"));
            col.setColumnSize(rsColumns.getInt("COLUMN_SIZE"));
            col.setDecimalDigits(rsColumns.getInt("DECIMAL_DIGITS"));
            col.setNumPrecRadix(rsColumns.getInt("NUM_PREC_RADIX"));
            col.setNullAble(rsColumns.getInt("NULLABLE"));
            col.setRemarks(rsColumns.getString("REMARKS"));
            col.setColumnDef(rsColumns.getString("COLUMN_DEF"));
            col.setSqlDataType(rsColumns.getInt("SQL_DATA_TYPE"));
            col.setSqlDatetimeSub(rsColumns.getInt("SQL_DATETIME_SUB"));
            col.setCharOctetLength(rsColumns.getInt("CHAR_OCTET_LENGTH"));
            col.setOrdinalPosition(rsColumns.getInt("ORDINAL_POSITION"));
            col.setIsNullAble(rsColumns.getString("IS_NULLABLE"));
            col.setIsAutoincrement(rsColumns.getString("IS_AUTOINCREMENT"));
            tm.getAllColumns().put(col.getColumnName(), col);
        }
        while (rsIndex.next()) {
            String indexName = rsIndex.getString("INDEX_NAME");
            String colName = rsIndex.getString("COLUMN_NAME");
            ColumnMeta col = tm.getAllColumns().get(colName);
            if (tm.getAllIndexes().containsKey(indexName)) {
                IndexMeta index = tm.getAllIndexes().get(indexName);
                index.getValues().add(col);
            } else {
                IndexMeta index = new IndexMeta();
                index.setIndexName(indexName);
                index.setNonUnique(rsIndex.getBoolean("NON_UNIQUE"));
                index.setIndexQualifier(rsIndex.getString("INDEX_QUALIFIER"));
                index.setIndexName(rsIndex.getString("INDEX_NAME"));
                index.setType(rsIndex.getShort("TYPE"));
                index.setOrdinalPosition(rsIndex.getShort("ORDINAL_POSITION"));
                index.setAscOrDesc(rsIndex.getString("ASC_OR_DESC"));
                index.setCardinality(rsIndex.getInt("CARDINALITY"));
                index.getValues().add(col);
                if ("PRIMARY".equalsIgnoreCase(indexName)) {
                    index.setIndextype(IndexType.PRIMARY);
                } else if (!index.isNonUnique()) {
                    index.setIndextype(IndexType.UNIQUE);
                } else {
                    index.setIndextype(IndexType.NORMAL);
                }
                tm.getAllIndexes().put(indexName, index);
            }
        }
        if (tm.getAllIndexes().isEmpty()) {
            throw new ShouldNeverHappenException("Could not found any index in the table: " + tableName);
        }
    }
    return tm;
}
Also used : ColumnMeta(io.seata.rm.datasource.sql.struct.ColumnMeta) ResultSet(java.sql.ResultSet) ShouldNeverHappenException(io.seata.common.exception.ShouldNeverHappenException) IndexMeta(io.seata.rm.datasource.sql.struct.IndexMeta) TableMeta(io.seata.rm.datasource.sql.struct.TableMeta)

Example 17 with ColumnMeta

use of io.seata.rm.datasource.sql.struct.ColumnMeta in project seata by seata.

the class MySQLInsertExecutor method getPkValuesByAuto.

/**
 * the modify for test
 */
public Map<String, List<Object>> getPkValuesByAuto() throws SQLException {
    // PK is just auto generated
    Map<String, List<Object>> pkValuesMap = new HashMap<>(8);
    Map<String, ColumnMeta> pkMetaMap = getTableMeta().getPrimaryKeyMap();
    String autoColumnName = null;
    for (Map.Entry<String, ColumnMeta> entry : pkMetaMap.entrySet()) {
        if (entry.getValue().isAutoincrement()) {
            autoColumnName = entry.getKey();
            break;
        }
    }
    if (StringUtils.isBlank(autoColumnName)) {
        throw new ShouldNeverHappenException();
    }
    ResultSet genKeys;
    try {
        genKeys = statementProxy.getGeneratedKeys();
    } catch (SQLException e) {
        // Statement.executeUpdate() or Connection.prepareStatement().
        if (ERR_SQL_STATE.equalsIgnoreCase(e.getSQLState())) {
            LOGGER.error("Fail to get auto-generated keys, use 'SELECT LAST_INSERT_ID()' instead. Be cautious, " + "statement could be polluted. Recommend you set the statement to return generated keys.");
            int updateCount = statementProxy.getUpdateCount();
            ResultSet firstId = genKeys = statementProxy.getTargetStatement().executeQuery("SELECT LAST_INSERT_ID()");
            // do auto increment base LAST_INSERT_ID and variable `auto_increment_increment`
            if (updateCount > 1 && canAutoIncrement(pkMetaMap)) {
                firstId.next();
                return autoGeneratePks(new BigDecimal(firstId.getString(1)), autoColumnName, updateCount);
            }
        } else {
            throw e;
        }
    }
    List<Object> pkValues = new ArrayList<>();
    while (genKeys.next()) {
        Object v = genKeys.getObject(1);
        pkValues.add(v);
    }
    try {
        genKeys.beforeFirst();
    } catch (SQLException e) {
        LOGGER.warn("Fail to reset ResultSet cursor. can not get primary key value");
    }
    pkValuesMap.put(autoColumnName, pkValues);
    return pkValuesMap;
}
Also used : HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) BigDecimal(java.math.BigDecimal) ColumnMeta(io.seata.rm.datasource.sql.struct.ColumnMeta) ShouldNeverHappenException(io.seata.common.exception.ShouldNeverHappenException) ResultSet(java.sql.ResultSet) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 18 with ColumnMeta

use of io.seata.rm.datasource.sql.struct.ColumnMeta in project seata by seata.

the class PostgresqlInsertExecutor method getPkValuesByDefault.

/**
 * get primary key values by default
 * @return
 * @throws SQLException
 */
@Override
public List<Object> getPkValuesByDefault() throws SQLException {
    // current version 1.2 only support postgresql.
    Map<String, ColumnMeta> pkMetaMap = getTableMeta().getPrimaryKeyMap();
    ColumnMeta pkMeta = pkMetaMap.values().iterator().next();
    String columnDef = pkMeta.getColumnDef();
    // sample: nextval('test_id_seq'::regclass)
    String seq = org.apache.commons.lang.StringUtils.substringBetween(columnDef, "'", "'");
    String function = org.apache.commons.lang.StringUtils.substringBetween(columnDef, "", "(");
    if (StringUtils.isBlank(seq)) {
        throw new ShouldNeverHappenException("get primary key value failed, cause columnDef is " + columnDef);
    }
    return getPkValuesBySequence(new SqlSequenceExpr("'" + seq + "'", function));
}
Also used : ColumnMeta(io.seata.rm.datasource.sql.struct.ColumnMeta) ShouldNeverHappenException(io.seata.common.exception.ShouldNeverHappenException) SqlSequenceExpr(io.seata.sqlparser.struct.SqlSequenceExpr)

Aggregations

ColumnMeta (io.seata.rm.datasource.sql.struct.ColumnMeta)18 ResultSet (java.sql.ResultSet)10 HashMap (java.util.HashMap)9 Test (org.junit.jupiter.api.Test)9 ArrayList (java.util.ArrayList)7 List (java.util.List)7 Mockito.anyString (org.mockito.Mockito.anyString)7 ShouldNeverHappenException (io.seata.common.exception.ShouldNeverHappenException)5 MockResultSet (io.seata.rm.datasource.mock.MockResultSet)5 PreparedStatement (java.sql.PreparedStatement)5 TableMeta (io.seata.rm.datasource.sql.struct.TableMeta)4 SQLException (java.sql.SQLException)4 IndexMeta (io.seata.rm.datasource.sql.struct.IndexMeta)3 Map (java.util.Map)2 PreparedStatementProxy (io.seata.rm.datasource.PreparedStatementProxy)1 StatementProxy (io.seata.rm.datasource.StatementProxy)1 OracleInsertExecutor (io.seata.rm.datasource.exec.oracle.OracleInsertExecutor)1 SQLInsertRecognizer (io.seata.sqlparser.SQLInsertRecognizer)1 SqlSequenceExpr (io.seata.sqlparser.struct.SqlSequenceExpr)1 BigDecimal (java.math.BigDecimal)1