diff --git a/src/main/java/com/alibaba/druid/common/jdbc/ResultSetBase.java b/src/main/java/com/alibaba/druid/common/jdbc/ResultSetBase.java index 8f462d8f25..ccff396c44 100644 --- a/src/main/java/com/alibaba/druid/common/jdbc/ResultSetBase.java +++ b/src/main/java/com/alibaba/druid/common/jdbc/ResultSetBase.java @@ -302,7 +302,7 @@ public abstract class ResultSetBase implements ResultSet { return wasNull; } - public abstract Object getObjectInternal(int columnIndex); + public abstract Object getObjectInternal(int columnIndex) throws SQLException; @Override public Object getObject(int columnIndex) throws SQLException { diff --git a/src/main/java/com/alibaba/druid/common/jdbc/ResultSetMetaDataBase.java b/src/main/java/com/alibaba/druid/common/jdbc/ResultSetMetaDataBase.java index 9e0b77df3b..627fff312a 100644 --- a/src/main/java/com/alibaba/druid/common/jdbc/ResultSetMetaDataBase.java +++ b/src/main/java/com/alibaba/druid/common/jdbc/ResultSetMetaDataBase.java @@ -61,102 +61,106 @@ public class ResultSetMetaDataBase implements ResultSetMetaData { @Override public boolean isAutoIncrement(int column) throws SQLException { - return columns.get(column - 1).isAutoIncrement(); + return getColumn(column).isAutoIncrement(); } @Override public boolean isCaseSensitive(int column) throws SQLException { - return columns.get(column - 1).isCaseSensitive(); + return getColumn(column).isCaseSensitive(); } @Override public boolean isSearchable(int column) throws SQLException { - return columns.get(column - 1).isSearchable(); + return getColumn(column).isSearchable(); } @Override public boolean isCurrency(int column) throws SQLException { - return columns.get(column - 1).isCurrency(); + return getColumn(column).isCurrency(); } @Override public int isNullable(int column) throws SQLException { - return columns.get(column - 1).getNullable(); + return getColumn(column).getNullable(); } @Override public boolean isSigned(int column) throws SQLException { - return columns.get(column - 1).isSigned(); + return getColumn(column).isSigned(); } @Override public int getColumnDisplaySize(int column) throws SQLException { - return columns.get(column - 1).getColumnDisplaySize(); + return getColumn(column).getColumnDisplaySize(); } @Override public String getColumnLabel(int column) throws SQLException { - return columns.get(column - 1).getColumnLabel(); + return getColumn(column).getColumnLabel(); + } + + public ColumnMetaData getColumn(int column) { + return columns.get(column - 1); } @Override public String getColumnName(int column) throws SQLException { - return columns.get(column - 1).getColumnName(); + return getColumn(column).getColumnName(); } @Override public String getSchemaName(int column) throws SQLException { - return columns.get(column - 1).getSchemaName(); + return getColumn(column).getSchemaName(); } @Override public int getPrecision(int column) throws SQLException { - return columns.get(column - 1).getPrecision(); + return getColumn(column).getPrecision(); } @Override public int getScale(int column) throws SQLException { - return columns.get(column - 1).getScale(); + return getColumn(column).getScale(); } @Override public String getTableName(int column) throws SQLException { - return columns.get(column - 1).getTableName(); + return getColumn(column).getTableName(); } @Override public String getCatalogName(int column) throws SQLException { - return columns.get(column - 1).getCatalogName(); + return getColumn(column).getCatalogName(); } @Override public int getColumnType(int column) throws SQLException { - return columns.get(column - 1).getColumnType(); + return getColumn(column).getColumnType(); } @Override public String getColumnTypeName(int column) throws SQLException { - return columns.get(column - 1).getColumnTypeName(); + return getColumn(column).getColumnTypeName(); } @Override public boolean isReadOnly(int column) throws SQLException { - return columns.get(column - 1).isReadOnly(); + return getColumn(column).isReadOnly(); } @Override public boolean isWritable(int column) throws SQLException { - return columns.get(column - 1).isWritable(); + return getColumn(column).isWritable(); } @Override public boolean isDefinitelyWritable(int column) throws SQLException { - return columns.get(column - 1).isDefinitelyWritable(); + return getColumn(column).isDefinitelyWritable(); } @Override public String getColumnClassName(int column) throws SQLException { - return columns.get(column - 1).getColumnClassName(); + return getColumn(column).getColumnClassName(); } public static class ColumnMetaData { diff --git a/src/main/java/com/alibaba/druid/hbase/HBasePreparedStatement.java b/src/main/java/com/alibaba/druid/hbase/HBasePreparedStatement.java index 0d2e497b7a..4bac60bb77 100644 --- a/src/main/java/com/alibaba/druid/hbase/HBasePreparedStatement.java +++ b/src/main/java/com/alibaba/druid/hbase/HBasePreparedStatement.java @@ -3,9 +3,11 @@ package com.alibaba.druid.hbase; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Types; import java.util.List; import com.alibaba.druid.common.jdbc.PreparedStatementBase; +import com.alibaba.druid.common.jdbc.ResultSetMetaDataBase.ColumnMetaData; import com.alibaba.druid.hbase.exec.ExecutePlan; import com.alibaba.druid.hbase.exec.InsertExecutePlan; import com.alibaba.druid.hbase.exec.SingleTableQueryExecutePlan; @@ -17,6 +19,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.visitor.SQLEvalVisitor; @@ -75,6 +78,18 @@ public class HBasePreparedStatement extends PreparedStatementBase implements Pre singleTableQueryExecuetePlan.setTableName(tableName); splitCondition(singleTableQueryExecuetePlan.getConditions(), selectQueryBlock.getWhere()); + + HBaseResultSetMetaData resultMetaData = new HBaseResultSetMetaData(); + for (SQLSelectItem selectItem : selectQueryBlock.getSelectList()) { + ColumnMetaData columnMetaData = new ColumnMetaData(); + if (selectItem.getAlias() != null) { + columnMetaData.setColumnLabel(selectItem.getAlias()); + } + columnMetaData.setColumnName(SQLUtils.toSQLString(selectItem.getExpr(), dbType)); + columnMetaData.setColumnType(Types.BINARY); + resultMetaData.getColumns().add(columnMetaData); + } + singleTableQueryExecuetePlan.setResultMetaData(resultMetaData); this.executePlan = singleTableQueryExecuetePlan; } else if (sqlStmt instanceof SQLInsertStatement) { diff --git a/src/main/java/com/alibaba/druid/hbase/HBaseResultSet.java b/src/main/java/com/alibaba/druid/hbase/HBaseResultSet.java index f1790a9632..f24ea47207 100644 --- a/src/main/java/com/alibaba/druid/hbase/HBaseResultSet.java +++ b/src/main/java/com/alibaba/druid/hbase/HBaseResultSet.java @@ -2,9 +2,9 @@ package com.alibaba.druid.hbase; import java.io.IOException; import java.math.BigDecimal; -import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; +import java.sql.Types; import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.client.Result; @@ -12,6 +12,7 @@ import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.util.Bytes; import com.alibaba.druid.common.jdbc.ResultSetBase; +import com.alibaba.druid.common.jdbc.ResultSetMetaDataBase.ColumnMetaData; import com.alibaba.druid.util.JdbcUtils; public class HBaseResultSet extends ResultSetBase { @@ -22,6 +23,8 @@ public class HBaseResultSet extends ResultSetBase { private Result result; private byte[] family = Bytes.toBytes("d"); + private HBaseResultSetMetaData metaData; + public HBaseResultSet(HBaseStatementInterface statement, HTableInterface htable, ResultScanner scanner){ super(statement); this.statement = statement; @@ -45,54 +48,111 @@ public class HBaseResultSet extends ResultSetBase { } @Override - public ResultSetMetaData getMetaData() throws SQLException { - // TODO Auto-generated method stub - return null; + public HBaseResultSetMetaData getMetaData() throws SQLException { + return metaData; + } + + public void setMetaData(HBaseResultSetMetaData metaData) { + this.metaData = metaData; } @Override public boolean previous() throws SQLException { - // TODO Auto-generated method stub return false; } @Override public void updateObject(int columnIndex, Object x) throws SQLException { - // TODO Auto-generated method stub - } @Override - public Object getObjectInternal(int columnIndex) { - return null; + public Object getObjectInternal(int columnIndex) throws SQLException { + ColumnMetaData column = this.metaData.getColumn(columnIndex); + return getObjectInternal(column.getColumnName(), column.getColumnType()); + } + + public Object getObjectInternal(String columnName, int type) throws SQLException { + byte[] bytes = getBytes(columnName); + switch (type) { + case Types.TINYINT: + return bytes[0]; + case Types.SMALLINT: + return Bytes.toShort(bytes); + case Types.INTEGER: + return Bytes.toInt(bytes); + case Types.BIGINT: + return Bytes.toLong(bytes); + case Types.DECIMAL: + return Bytes.toBigDecimal(bytes); + case Types.BOOLEAN: + return Bytes.toBoolean(bytes); + case Types.VARCHAR: + case Types.CHAR: + case Types.NCHAR: + case Types.NVARCHAR: + return Bytes.toString(bytes); + case Types.DATE: + return new java.sql.Date(Bytes.toLong(bytes)); + case Types.TIMESTAMP: + return new java.sql.Timestamp(Bytes.toLong(bytes)); + case Types.NULL: + case Types.VARBINARY: + case Types.BINARY: + case Types.ROWID: + default: + return bytes; + } } + @Override + public String getString(int columnIndex) throws SQLException { + byte[] bytes = getBytes(columnIndex); + return Bytes.toString(bytes); + } + @Override public String getString(String columnName) throws SQLException { byte[] bytes = getBytes(columnName); return Bytes.toString(bytes); } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + ColumnMetaData column = this.metaData.getColumn(columnIndex); + return getBytes(column.getColumnName()); + } public byte[] getBytes(String columnName) throws SQLException { if ("@ROW".equals(columnName)) { return result.getRow(); } - + if ("id".equals(columnName)) { // TODO return result.getRow(); } byte[] qualifier = Bytes.toBytes(columnName); byte[] value = result.getValue(family, qualifier); - + this.wasNull = value == null; - + return value; } - + @Override public int getInt(String columnName) throws SQLException { byte[] bytes = getBytes(columnName); + + if (bytes == null) { + return 0; + } + + return Bytes.toInt(bytes); + } + + @Override + public int getInt(int columnIndex) throws SQLException { + byte[] bytes = getBytes(columnIndex); if (bytes == null) { return 0; @@ -100,10 +160,21 @@ public class HBaseResultSet extends ResultSetBase { return Bytes.toInt(bytes); } - + @Override public BigDecimal getBigDecimal(String columnName) throws SQLException { byte[] bytes = getBytes(columnName); + + if (bytes == null) { + return null; + } + + return Bytes.toBigDecimal(bytes); + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + byte[] bytes = getBytes(columnIndex); if (bytes == null) { return null; diff --git a/src/main/java/com/alibaba/druid/hbase/HBaseResultSetMetaData.java b/src/main/java/com/alibaba/druid/hbase/HBaseResultSetMetaData.java new file mode 100644 index 0000000000..d496be7c10 --- /dev/null +++ b/src/main/java/com/alibaba/druid/hbase/HBaseResultSetMetaData.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.hbase; + +import com.alibaba.druid.common.jdbc.ResultSetMetaDataBase; + + +public class HBaseResultSetMetaData extends ResultSetMetaDataBase { + +} diff --git a/src/main/java/com/alibaba/druid/hbase/exec/SingleTableQueryExecutePlan.java b/src/main/java/com/alibaba/druid/hbase/exec/SingleTableQueryExecutePlan.java index 65e13ff434..4088ee12c4 100644 --- a/src/main/java/com/alibaba/druid/hbase/exec/SingleTableQueryExecutePlan.java +++ b/src/main/java/com/alibaba/druid/hbase/exec/SingleTableQueryExecutePlan.java @@ -18,6 +18,7 @@ import org.apache.hadoop.hbase.util.Bytes; import com.alibaba.druid.hbase.HBaseConnection; import com.alibaba.druid.hbase.HBasePreparedStatement; import com.alibaba.druid.hbase.HBaseResultSet; +import com.alibaba.druid.hbase.HBaseResultSetMetaData; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; @@ -26,10 +27,12 @@ import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils; public class SingleTableQueryExecutePlan extends SingleTableExecutePlan { - private List columeNames = new ArrayList(); - private List conditions = new ArrayList(); + private List columeNames = new ArrayList(); + private List conditions = new ArrayList(); - private byte[] family = Bytes.toBytes("d"); + private byte[] family = Bytes.toBytes("d"); + + private HBaseResultSetMetaData resultMetaData; public List getConditions() { return conditions; @@ -47,6 +50,14 @@ public class SingleTableQueryExecutePlan extends SingleTableExecutePlan { return columeNames; } + public HBaseResultSetMetaData getResultMetaData() { + return resultMetaData; + } + + public void setResultMetaData(HBaseResultSetMetaData resultMetaData) { + this.resultMetaData = resultMetaData; + } + @Override public HBaseResultSet executeQuery(HBasePreparedStatement statement) throws SQLException { try { @@ -100,7 +111,10 @@ public class SingleTableQueryExecutePlan extends SingleTableExecutePlan { ResultScanner scanner = htable.getScanner(scan); - return new HBaseResultSet(statement, htable, scanner); + HBaseResultSet resultSet = new HBaseResultSet(statement, htable, scanner); + resultSet.setMetaData(resultMetaData); + + return resultSet; } catch (SQLException e) { throw e; } catch (Exception e) { diff --git a/src/test/java/com/alibaba/druid/bvt/mock/MockResultSetMetaDataTest.java b/src/test/java/com/alibaba/druid/bvt/mock/MockResultSetMetaDataTest.java index 1e302270bd..aa78e1c195 100644 --- a/src/test/java/com/alibaba/druid/bvt/mock/MockResultSetMetaDataTest.java +++ b/src/test/java/com/alibaba/druid/bvt/mock/MockResultSetMetaDataTest.java @@ -7,8 +7,8 @@ import junit.framework.TestCase; import org.junit.Assert; +import com.alibaba.druid.common.jdbc.ResultSetMetaDataBase.ColumnMetaData; import com.alibaba.druid.mock.MockResultSetMetaData; -import com.alibaba.druid.mock.MockResultSetMetaData.ColumnMetaData; public class MockResultSetMetaDataTest extends TestCase {