提交 840bfed4 authored 作者: thomasmueller's avatar thomasmueller

Merge branch 'master' of https://github.com/h2database/h2database

......@@ -258,13 +258,14 @@ ALTER TABLE TEST RENAME CONSTRAINT FOO TO BAR
"Commands (DDL)","ALTER TABLE ALTER COLUMN","
ALTER TABLE [ IF EXISTS ] tableName ALTER COLUMN columnName
{ { dataType [ DEFAULT expression ] [ [ NOT ] NULL ] [ AUTO_INCREMENT | IDENTITY ] }
{ { dataType [ VISIBLE | INVISIBLE ] [ DEFAULT expression ] [ [ NOT ] NULL ] [ AUTO_INCREMENT | IDENTITY ] }
| { RENAME TO name }
| { RESTART WITH long }
| { SELECTIVITY int }
| { SET DEFAULT expression }
| { SET NULL }
| { SET NOT NULL } }
| { SET NOT NULL }
| { SET { VISIBLE | INVISIBLE } } }
","
Changes the data type of a column, rename a column,
change the identity value, or change the selectivity.
......@@ -287,6 +288,9 @@ Single column indexes on this column are dropped.
SET NOT NULL sets a column to not allow NULL. Rows may not contains NULL in this column.
SET INVISIBLE makes the column hidden, i.e. it will not appear in SELECT * results.
SET VISIBLE has the reverse effect.
This command commits an open transaction in this connection.
","
ALTER TABLE TEST ALTER COLUMN NAME CLOB;
......@@ -296,6 +300,8 @@ ALTER TABLE TEST ALTER COLUMN NAME SELECTIVITY 100;
ALTER TABLE TEST ALTER COLUMN NAME SET DEFAULT '';
ALTER TABLE TEST ALTER COLUMN NAME SET NOT NULL;
ALTER TABLE TEST ALTER COLUMN NAME SET NULL;
ALTER TABLE TEST ALTER COLUMN NAME SET VISIBLE;
ALTER TABLE TEST ALTER COLUMN NAME SET INVISIBLE;
"
"Commands (DDL)","ALTER TABLE DROP COLUMN","
......@@ -1759,6 +1765,7 @@ AES
"Other Grammar","Column Definition","
columnName dataType
[ VISIBLE | INVISIBLE ]
[ { DEFAULT expression | AS computedColumnExpression } ] [ [ NOT ] NULL ]
[ { AUTO_INCREMENT | IDENTITY } [ ( startInt [, incrementInt ] ) ] ]
[ SELECTIVITY selectivity ] [ COMMENT expression ]
......@@ -1771,12 +1778,16 @@ Identity and auto-increment columns are columns with a sequence as the
default. The column declared as the identity columns is implicitly the
primary key column of this table (unlike auto-increment columns).
The invisible column will not be displayed as a result of SELECT * query.
Otherwise, it works as normal column.
The options PRIMARY KEY, UNIQUE, and CHECK are not supported for ALTER statements.
Check constraints can reference columns of the table,
and they can reference objects that exist while the statement is executed.
Conditions are only checked when a row is added or modified
in the table where the constraint exists.
","
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255) DEFAULT '');
CREATE TABLE TEST(ID BIGINT IDENTITY);
......
......@@ -85,6 +85,8 @@ Advanced
Database Upgrade</a><br />
<a href="#java_objects_serialization">
Java Objects Serialization</a><br />
<a href="#custom_data_types_handler_api">
Custom Data Types Handler API</a><br />
<a href="#limits_limitations">
Limits and Limitations</a><br />
<a href="#glossary_links">
......@@ -1691,6 +1693,29 @@ Please note that this SQL statement can only be executed before any tables are d
</ul>
</p>
<h2 id="custom_data_types_handler_api">Custom Data Types Handler API</h2>
<p>
It is possible to extend the type system of the database by providing your own implementation
of minimal required API basically consisting of type identification and conversion routines.
</p>
<p>
In order to enable this feature, set the system property <code>h2.customDataTypesHandler</code> (default: null) to the fully qualified name of the class providing <a href="../javadoc/org/h2/api/CustomDataTypesHandler.html">CustomDataTypesHandler</a> interface implementation. <br>
The instance of that class will be created by H2 and used to:
<ul>
<li>resolve the names and identifiers of extrinsic data types.
</li>
<li>convert values of extrinsic data types to and from values of built-in types.
</li>
<li>provide order of the data types.
</li>
</ul>
</p>
<p>This is a system-level setting, i.e. affects all the databases.</p>
<p><b>Note: </b>Please keep in mind that this feature may not possibly provide the same ABI stability level as other features as it exposes many of the H2 internals. You may be required to update your code occasionally due to internal changes in H2 if you are going to use this feature.
</p>
<h2 id="limits_limitations">Limits and Limitations</h2>
<p>
This database has the following known limitations:
......
......@@ -21,6 +21,10 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Added API for handling custom data types (System property "h2.customDataTypesHandler", API org.h2.api.CustomDataTypesHandler).
</li>
<li>Added support for invisible columns.
</li>
</ul>
<h2>Version 1.4.194 (2017-03-10)</h2>
......
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.api;
import org.h2.store.DataHandler;
import org.h2.value.DataType;
import org.h2.value.Value;
/**
* Custom data type handler
* Provides means to plug-in custom data types support
*
* Please keep in mind that this feature may not possibly
* provide the same ABI stability level as other features
* as it exposes many of the H2 internals. You may be
* required to update your code occasionally due to internal
* changes in H2 if you are going to use this feature
*/
public interface CustomDataTypesHandler {
/**
* Get custom data type given its name
*
* @param name data type name
* @return custom data type
*/
DataType getDataTypeByName(String name);
/**
* Get custom data type given its integer id
*
* @param type identifier of a data type
* @return custom data type
*/
DataType getDataTypeById(int type);
/**
* Get order for custom data type given its integer id
*
* @param type identifier of a data type
* @return order associated with custom data type
*/
int getDataTypeOrder(int type);
/**
* Convert the provided source value into value of given target data type
* Shall implement conversions to and from custom data types.
*
* @param source source value
* @param targetType identifier of target data type
* @return converted value
*/
Value convert(Value source, int targetType);
/**
* Get custom data type class name given its integer id
*
* @param type identifier of a data type
* @return class name
*/
String getDataTypeClassName(int type);
/**
* Get custom data type identifier given corresponding Java class
* @param cls Java class object
* @return type identifier
*/
int getTypeIdFromClass(Class<?> cls);
/**
* Get {@link org.h2.value.Value} object
* corresponding to given data type identifier and data.
*
* @param type custom data type identifier
* @param data underlying data type value
* @param dataHandler data handler object
* @return Value object
*/
Value getValue(int type, Object data, DataHandler dataHandler);
/**
* Converts {@link org.h2.value.Value} object
* to the specified class.
*
* @param value
* @param cls
* @return result
*/
Object getObject(Value value, Class<?> cls);
/**
* Checks if type supports add operation
*
* @param type custom data type identifier
* @return True, if custom data type supports add operation
*/
boolean supportsAdd(int type);
/**
* Get compatible type identifier that would not overflow
* after many add operations.
*
* @param type identifier of a type
* @return resulting type identifier
*/
int getAddProofType(int type);
}
......@@ -461,6 +461,11 @@ public interface CommandInterface {
*/
int EXPLAIN_ANALYZE = 86;
/**
* The type of a ALTER TABLE ALTER COLUMN SET INVISIBLE statement.
*/
int ALTER_TABLE_ALTER_COLUMN_VISIBILITY = 87;
/**
* Get command type.
*
......
......@@ -3993,6 +3993,11 @@ public class Parser {
} else {
column = parseColumnWithType(columnName);
}
if (readIf("INVISIBLE")) {
column.setVisible(false);
} else if (readIf("VISIBLE")) {
column.setVisible(true);
}
if (readIf("NOT")) {
read("NULL");
column.setNullable(false);
......@@ -5718,6 +5723,14 @@ public class Parser {
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT);
command.setDefaultExpression(defaultExpression);
return command;
} else if (readIf("INVISIBLE")) {
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_VISIBILITY);
command.setVisible(false);
return command;
} else if (readIf("VISIBLE")) {
command.setType(CommandInterface.ALTER_TABLE_ALTER_COLUMN_VISIBILITY);
command.setVisible(true);
return command;
}
} else if (readIf("RESTART")) {
readIf("WITH");
......
......@@ -44,6 +44,8 @@ import org.h2.util.New;
* ALTER TABLE ALTER COLUMN SET DEFAULT,
* ALTER TABLE ALTER COLUMN SET NOT NULL,
* ALTER TABLE ALTER COLUMN SET NULL,
* ALTER TABLE ALTER COLUMN SET VISIBLE,
* ALTER TABLE ALTER COLUMN SET INVISIBLE,
* ALTER TABLE DROP COLUMN
*/
public class AlterTableAlterColumn extends SchemaCommand {
......@@ -60,6 +62,7 @@ public class AlterTableAlterColumn extends SchemaCommand {
private boolean ifNotExists;
private ArrayList<Column> columnsToAdd;
private ArrayList<Column> columnsToRemove;
private boolean newVisibility;
public AlterTableAlterColumn(Session session, Schema schema) {
super(session, schema);
......@@ -156,9 +159,13 @@ public class AlterTableAlterColumn extends SchemaCommand {
} else if (!oldColumn.isNullable() && newColumn.isNullable()) {
checkNullable(table);
}
if (oldColumn.getVisible() ^ newColumn.getVisible()) {
oldColumn.setVisible(newColumn.getVisible());
}
convertAutoIncrementColumn(table, newColumn);
copyData(table);
}
table.setModified();
break;
}
case CommandInterface.ALTER_TABLE_ADD_COLUMN: {
......@@ -192,6 +199,12 @@ public class AlterTableAlterColumn extends SchemaCommand {
db.updateMeta(session, table);
break;
}
case CommandInterface.ALTER_TABLE_ALTER_COLUMN_VISIBILITY: {
oldColumn.setVisible(newVisibility);
table.setModified();
db.updateMeta(session, table);
break;
}
default:
DbException.throwInternalError("type=" + type);
}
......@@ -550,4 +563,8 @@ public class AlterTableAlterColumn extends SchemaCommand {
public void setColumnsToRemove(ArrayList<Column> columnsToRemove) {
this.columnsToRemove = columnsToRemove;
}
public void setVisible(boolean visible) {
this.newVisibility = visible;
}
}
......@@ -731,6 +731,9 @@ public class Select extends Query {
String alias = filter.getTableAlias();
Column[] columns = t.getColumns();
for (Column c : columns) {
if (!c.getVisible()) {
continue;
}
if (filter.isNaturalJoinColumn(c)) {
continue;
}
......
......@@ -522,6 +522,16 @@ public class SysProperties {
public static final String JAVA_OBJECT_SERIALIZER =
Utils.getProperty("h2.javaObjectSerializer", null);
/**
* System property <code>h2.customDataTypesHandler</code>
* (default: null).<br />
* The CustomDataTypesHandler class name that is used
* to provide support for user defined custom data types.
* It must be the same on client and server to work correctly.
*/
public static final String CUSTOM_DATA_TYPES_HANDLER =
Utils.getProperty("h2.customDataTypesHandler", null);
private static final String H2_BASE_DIR = "h2.baseDir";
private SysProperties() {
......
......@@ -22,6 +22,7 @@ import org.h2.mvstore.type.DataType;
import org.h2.result.SortOrder;
import org.h2.store.DataHandler;
import org.h2.tools.SimpleResultSet;
import org.h2.util.JdbcUtils;
import org.h2.value.CompareMode;
import org.h2.value.Value;
import org.h2.value.ValueArray;
......@@ -67,6 +68,7 @@ public class ValueDataType implements DataType {
private static final int STRING_0_31 = 68;
private static final int BYTES_0_31 = 100;
private static final int SPATIAL_KEY_2D = 132;
private static final int CUSTOM_DATA_TYPE = 133;
final DataHandler handler;
final CompareMode compareMode;
......@@ -428,6 +430,14 @@ public class ValueDataType implements DataType {
break;
}
default:
if (JdbcUtils.customDataTypesHandler != null) {
byte[] b = v.getBytesNoCopy();
buff.put((byte)CUSTOM_DATA_TYPE).
putVarInt(type).
putVarInt(b.length).
put(b);
break;
}
DbException.throwInternalError("type=" + v.getType());
}
}
......@@ -592,6 +602,16 @@ public class ValueDataType implements DataType {
}
case SPATIAL_KEY_2D:
return getSpatialDataType().read(buff);
case CUSTOM_DATA_TYPE: {
if (JdbcUtils.customDataTypesHandler != null) {
int customType = readVarInt(buff);
int len = readVarInt(buff);
byte[] b = DataUtils.newBytes(len);
buff.get(b, 0, len);
return JdbcUtils.customDataTypesHandler.convert(ValueBytes.getNoCopy(b), customType);
}
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "No CustomDataTypesHandler has been set up");
}
default:
if (type >= INT_0_15 && type < INT_0_15 + 16) {
return ValueInt.get(type - INT_0_15);
......
......@@ -98,13 +98,14 @@ ALTER TABLE [ IF EXISTS ] tableName RENAME oldConstraintName TO newConstraintNam
Renames a constraint."
"Commands (DDL)","ALTER TABLE ALTER COLUMN","
ALTER TABLE [ IF EXISTS ] tableName ALTER COLUMN columnName
{ { dataType [ DEFAULT expression ] [ [ NOT ] NULL ] [ AUTO_INCREMENT | IDENTITY ] }
{ { dataType [ VISIBLE | INVISIBLE ] [ DEFAULT expression ] [ [ NOT ] NULL ] [ AUTO_INCREMENT | IDENTITY ] }
| { RENAME TO name }
| { RESTART WITH long }
| { SELECTIVITY int }
| { SET DEFAULT expression }
| { SET NULL }
| { SET NOT NULL } }
| { SET NOT NULL }
| { SET { VISIBLE | INVISIBLE } } }
","
Changes the data type of a column, rename a column,
change the identity value, or change the selectivity."
......@@ -555,6 +556,7 @@ AES
Only the algorithm AES (""AES-128"") is supported currently."
"Other Grammar","Column Definition","
columnName dataType
[ VISIBLE | INVISIBLE ]
[ { DEFAULT expression | AS computedColumnExpression } ] [ [ NOT ] NULL ]
[ { AUTO_INCREMENT | IDENTITY } [ ( startInt [, incrementInt ] ) ] ]
[ SELECTIVITY selectivity ] [ COMMENT expression ]
......
......@@ -86,6 +86,7 @@ public class Column {
private SingleColumnResolver resolver;
private String comment;
private boolean primaryKey;
private boolean visible = true;
public Column(String name, int type) {
this(name, type, -1, -1, -1);
......@@ -257,6 +258,14 @@ public class Column {
nullable = b;
}
public boolean getVisible() {
return visible;
}
public void setVisible(boolean b) {
visible = b;
}
/**
* Validate the value, convert it if required, and update the sequence value
* if required. If the value is null, the default value (NULL if no default
......@@ -436,6 +445,11 @@ public class Column {
default:
}
}
if (!visible) {
buff.append(" INVISIBLE ");
}
if (defaultExpression != null) {
String sql = defaultExpression.getSQL();
if (sql != null) {
......@@ -748,6 +762,7 @@ public class Column {
isComputed = source.isComputed;
selectivity = source.selectivity;
primaryKey = source.primaryKey;
visible = source.visible;
}
}
......@@ -21,6 +21,7 @@ import java.util.HashSet;
import java.util.Properties;
import javax.naming.Context;
import javax.sql.DataSource;
import org.h2.api.CustomDataTypesHandler;
import org.h2.api.ErrorCode;
import org.h2.api.JavaObjectSerializer;
import org.h2.engine.SysProperties;
......@@ -38,6 +39,11 @@ public class JdbcUtils {
*/
public static JavaObjectSerializer serializer;
/**
* Custom data types handler to use.
*/
public static CustomDataTypesHandler customDataTypesHandler;
private static final String[] DRIVERS = {
"h2:", "org.h2.Driver",
"Cache:", "com.intersys.jdbc.CacheDriver",
......@@ -117,6 +123,15 @@ public class JdbcUtils {
throw DbException.convert(e);
}
}
String customTypeHandlerClass = SysProperties.CUSTOM_DATA_TYPES_HANDLER;
if (customTypeHandlerClass != null) {
try {
customDataTypesHandler = (CustomDataTypesHandler) loadUserClass(customTypeHandlerClass).newInstance();
} catch (Exception e) {
throw DbException.convert(e);
}
}
}
/**
......
......@@ -682,6 +682,11 @@ public class DataType {
return ValueGeometry.getFromGeometry(x);
}
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getValue(type,
rs.getObject(columnIndex),
session.getDataHandler());
}
throw DbException.throwInternalError("type="+type);
}
return v;
......@@ -764,6 +769,9 @@ public class DataType {
case Value.GEOMETRY:
return GEOMETRY_CLASS_NAME;
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getDataTypeClassName(type);
}
throw DbException.throwInternalError("type="+type);
}
}
......@@ -779,6 +787,9 @@ public class DataType {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?");
}
DataType dt = TYPES_BY_VALUE_TYPE.get(type);
if (dt == null && JdbcUtils.customDataTypesHandler != null) {
dt = JdbcUtils.customDataTypesHandler.getDataTypeById(type);
}
if (dt == null) {
dt = TYPES_BY_VALUE_TYPE.get(Value.NULL);
}
......@@ -971,6 +982,9 @@ public class DataType {
} else if (LocalDateTimeUtils.isOffsetDateTime(x)) {
return Value.TIMESTAMP_TZ;
} else {
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getTypeIdFromClass(x);
}
return Value.JAVA_OBJECT;
}
}
......@@ -1094,6 +1108,9 @@ public class DataType {
} else if (LocalDateTimeUtils.isOffsetDateTime(x.getClass())) {
return LocalDateTimeUtils.offsetDateTimeToValue(x);
} else {
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getValue(type, x, session.getDataHandler());
}
return ValueJavaObject.getNoCopy(x, null, session.getDataHandler());
}
}
......@@ -1132,7 +1149,11 @@ public class DataType {
* @return the data type object
*/
public static DataType getTypeByName(String s) {
return TYPES_BY_NAME.get(s);
DataType result = TYPES_BY_NAME.get(s);
if (result == null && JdbcUtils.customDataTypesHandler != null) {
result = JdbcUtils.customDataTypesHandler.getDataTypeByName(s);
}
return result;
}
/**
......@@ -1178,7 +1199,29 @@ public class DataType {
case Value.LONG:
case Value.SHORT:
return true;
case Value.BOOLEAN:
case Value.TIME:
case Value.DATE:
case Value.TIMESTAMP:
case Value.TIMESTAMP_TZ:
case Value.BYTES:
case Value.UUID:
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
case Value.BLOB:
case Value.CLOB:
case Value.NULL:
case Value.JAVA_OBJECT:
case Value.UNKNOWN:
case Value.ARRAY:
case Value.RESULT_SET:
case Value.GEOMETRY:
return false;
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.supportsAdd(type);
}
return false;
}
}
......@@ -1202,7 +1245,31 @@ public class DataType {
return Value.DECIMAL;
case Value.SHORT:
return Value.LONG;
case Value.BOOLEAN:
case Value.DECIMAL:
case Value.TIME:
case Value.DATE:
case Value.TIMESTAMP:
case Value.TIMESTAMP_TZ:
case Value.BYTES:
case Value.UUID:
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
case Value.BLOB:
case Value.CLOB:
case Value.DOUBLE:
case Value.NULL:
case Value.JAVA_OBJECT:
case Value.UNKNOWN:
case Value.ARRAY:
case Value.RESULT_SET:
case Value.GEOMETRY:
return type;
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getAddProofType(type);
}
return type;
}
}
......@@ -1253,12 +1320,44 @@ public class DataType {
} else if (paramClass == Array.class) {
return new JdbcArray(conn, v, 0);
}
if (v.getType() == Value.JAVA_OBJECT) {
switch (v.getType()) {
case Value.JAVA_OBJECT: {
Object o = SysProperties.serializeJavaObject ? JdbcUtils.deserialize(v.getBytes(),
conn.getSession().getDataHandler()) : v.getObject();
if (paramClass.isAssignableFrom(o.getClass())) {
return o;
}
break;
}
case Value.BOOLEAN:
case Value.BYTE:
case Value.SHORT:
case Value.INT:
case Value.LONG:
case Value.DECIMAL:
case Value.TIME:
case Value.DATE:
case Value.TIMESTAMP:
case Value.TIMESTAMP_TZ:
case Value.BYTES:
case Value.UUID:
case Value.STRING:
case Value.STRING_IGNORECASE:
case Value.STRING_FIXED:
case Value.BLOB:
case Value.CLOB:
case Value.DOUBLE:
case Value.FLOAT:
case Value.NULL:
case Value.UNKNOWN:
case Value.ARRAY:
case Value.RESULT_SET:
case Value.GEOMETRY:
break;
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getObject(v, paramClass);
}
}
throw DbException.getUnsupportedException("converting to class " + paramClass.getName());
}
......
......@@ -530,6 +530,10 @@ public class Transfer {
}
break;
default:
if (JdbcUtils.customDataTypesHandler != null) {
writeBytes(v.getBytesNoCopy());
break;
}
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "type=" + type);
}
}
......@@ -706,6 +710,9 @@ public class Transfer {
}
return ValueGeometry.get(readString());
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.convert(ValueBytes.getNoCopy(readBytes()), type);
}
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "type=" + type);
}
}
......
......@@ -274,56 +274,59 @@ public abstract class Value {
static int getOrder(int type) {
switch (type) {
case UNKNOWN:
return 1;
return 1_000;
case NULL:
return 2;
return 2_000;
case STRING:
return 10;
return 10_000;
case CLOB:
return 11;
return 11_000;
case STRING_FIXED:
return 12;
return 12_000;
case STRING_IGNORECASE:
return 13;
return 13_000;
case BOOLEAN:
return 20;
return 20_000;
case BYTE:
return 21;
return 21_000;
case SHORT:
return 22;
return 22_000;
case INT:
return 23;
return 23_000;
case LONG:
return 24;
return 24_000;
case DECIMAL:
return 25;
return 25_000;
case FLOAT:
return 26;
return 26_000;
case DOUBLE:
return 27;
return 27_000;
case TIME:
return 30;
return 30_000;
case DATE:
return 31;
return 31_000;
case TIMESTAMP:
return 32;
return 32_000;
case TIMESTAMP_TZ:
return 34;
return 34_000;
case BYTES:
return 40;
return 40_000;
case BLOB:
return 41;
return 41_000;
case JAVA_OBJECT:
return 42;
return 42_000;
case UUID:
return 43;
return 43_000;
case GEOMETRY:
return 44;
return 44_000;
case ARRAY:
return 50;
return 50_000;
case RESULT_SET:
return 51;
return 51_000;
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getDataTypeOrder(type);
}
throw DbException.throwInternalError("type:"+type);
}
}
......@@ -967,6 +970,9 @@ public abstract class Value {
case GEOMETRY:
return ValueGeometry.get(s);
default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.convert(this, targetType);
}
throw DbException.throwInternalError("type=" + targetType);
}
} catch (NumberFormatException e) {
......
......@@ -91,6 +91,7 @@ import org.h2.test.jdbc.TestCallableStatement;
import org.h2.test.jdbc.TestCancel;
import org.h2.test.jdbc.TestConcurrentConnectionUsage;
import org.h2.test.jdbc.TestConnection;
import org.h2.test.jdbc.TestCustomDataTypesHandler;
import org.h2.test.jdbc.TestDatabaseEventListener;
import org.h2.test.jdbc.TestDriver;
import org.h2.test.jdbc.TestJavaObject;
......@@ -772,6 +773,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestTransactionIsolation());
addTest(new TestUpdatableResultSet());
addTest(new TestZloty());
addTest(new TestCustomDataTypesHandler());
// jdbcx
addTest(new TestConnectionPool());
......
......@@ -4915,6 +4915,22 @@ SELECT group_concat(name) FROM TEST group by id;
drop table test;
> ok
create table test(a int primary key, b int invisible, c int);
> ok
select * from test;
> A C
> - -
> rows: 0
select a, b, c from test;
> A B C
> - - -
> rows: 0
drop table test;
> ok
--- script drop ---------------------------------------------------------------------------------------------
create memory table test (id int primary key, im_ie varchar(10));
> ok
......@@ -6183,6 +6199,49 @@ SELECT * FROM TEST;
DROP TABLE TEST;
> ok
create table test(id int, name varchar invisible);
> ok
select * from test;
> ID
> --
> rows: 0
alter table test alter column name set visible;
> ok
select * from test;
> ID NAME
> -- ----
> rows: 0
alter table test add modify_date timestamp invisible before name;
> ok
select * from test;
> ID NAME
> -- ----
> rows: 0
alter table test alter column modify_date timestamp visible;
> ok
select * from test;
> ID MODIFY_DATE NAME
> -- ----------- ----
> rows: 0
alter table test alter column modify_date set invisible;
> ok
select * from test;
> ID NAME
> -- ----
> rows: 0
drop table test;
> ok
--- autoIncrement ----------------------------------------------------------------------------------------------
CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR);
> ok
......
......@@ -815,6 +815,7 @@ public class TestFileSystem extends TestBase {
final int size = getSize(10, 50);
f.write(ByteBuffer.allocate(size * 64 * 1024));
Random random = new Random(1);
System.gc();
Task task = new Task() {
@Override
public void call() throws Exception {
......@@ -864,6 +865,7 @@ public class TestFileSystem extends TestBase {
ra.close();
file.delete();
FileUtils.delete(s);
System.gc();
}
}
......
......@@ -931,6 +931,7 @@ public class Build extends BuildBase {
ret = execJava(args(
"-ea",
"-Xmx128m",
"-XX:MaxDirectMemorySize=2g",
"-cp", cp,
"org.h2.test.TestAll", "fast"));
} else {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论