提交 d69d5052 authored 作者: Sergey Kalashnikov's avatar Sergey Kalashnikov 提交者: Sergi Vladykin

Custom data types handler (#462)

* Custom data types handler

* Updated doc, changelog, dictionary. Fixed review comment.

* Extended the custom types handler interface

* Fixed test

* Fixed review comments

* Added note on ABI stability of the feature to docs
上级 237dda41
...@@ -85,6 +85,8 @@ Advanced ...@@ -85,6 +85,8 @@ Advanced
Database Upgrade</a><br /> Database Upgrade</a><br />
<a href="#java_objects_serialization"> <a href="#java_objects_serialization">
Java Objects Serialization</a><br /> Java Objects Serialization</a><br />
<a href="#custom_data_types_handler_api">
Custom Data Types Handler API</a><br />
<a href="#limits_limitations"> <a href="#limits_limitations">
Limits and Limitations</a><br /> Limits and Limitations</a><br />
<a href="#glossary_links"> <a href="#glossary_links">
...@@ -1691,6 +1693,29 @@ Please note that this SQL statement can only be executed before any tables are d ...@@ -1691,6 +1693,29 @@ Please note that this SQL statement can only be executed before any tables are d
</ul> </ul>
</p> </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> <h2 id="limits_limitations">Limits and Limitations</h2>
<p> <p>
This database has the following known limitations: This database has the following known limitations:
......
...@@ -21,6 +21,8 @@ Change Log ...@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul> <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>Added support for invisible columns.
</li> </li>
</ul> </ul>
......
/*
* 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);
}
...@@ -522,6 +522,16 @@ public class SysProperties { ...@@ -522,6 +522,16 @@ public class SysProperties {
public static final String JAVA_OBJECT_SERIALIZER = public static final String JAVA_OBJECT_SERIALIZER =
Utils.getProperty("h2.javaObjectSerializer", null); 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 static final String H2_BASE_DIR = "h2.baseDir";
private SysProperties() { private SysProperties() {
......
...@@ -22,6 +22,7 @@ import org.h2.mvstore.type.DataType; ...@@ -22,6 +22,7 @@ import org.h2.mvstore.type.DataType;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.JdbcUtils;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -67,6 +68,7 @@ public class ValueDataType implements DataType { ...@@ -67,6 +68,7 @@ public class ValueDataType implements DataType {
private static final int STRING_0_31 = 68; private static final int STRING_0_31 = 68;
private static final int BYTES_0_31 = 100; private static final int BYTES_0_31 = 100;
private static final int SPATIAL_KEY_2D = 132; private static final int SPATIAL_KEY_2D = 132;
private static final int CUSTOM_DATA_TYPE = 133;
final DataHandler handler; final DataHandler handler;
final CompareMode compareMode; final CompareMode compareMode;
...@@ -428,6 +430,14 @@ public class ValueDataType implements DataType { ...@@ -428,6 +430,14 @@ public class ValueDataType implements DataType {
break; break;
} }
default: 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()); DbException.throwInternalError("type=" + v.getType());
} }
} }
...@@ -592,6 +602,16 @@ public class ValueDataType implements DataType { ...@@ -592,6 +602,16 @@ public class ValueDataType implements DataType {
} }
case SPATIAL_KEY_2D: case SPATIAL_KEY_2D:
return getSpatialDataType().read(buff); 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: default:
if (type >= INT_0_15 && type < INT_0_15 + 16) { if (type >= INT_0_15 && type < INT_0_15 + 16) {
return ValueInt.get(type - INT_0_15); return ValueInt.get(type - INT_0_15);
......
...@@ -21,6 +21,7 @@ import java.util.HashSet; ...@@ -21,6 +21,7 @@ import java.util.HashSet;
import java.util.Properties; import java.util.Properties;
import javax.naming.Context; import javax.naming.Context;
import javax.sql.DataSource; import javax.sql.DataSource;
import org.h2.api.CustomDataTypesHandler;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.JavaObjectSerializer; import org.h2.api.JavaObjectSerializer;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
...@@ -38,6 +39,11 @@ public class JdbcUtils { ...@@ -38,6 +39,11 @@ public class JdbcUtils {
*/ */
public static JavaObjectSerializer serializer; public static JavaObjectSerializer serializer;
/**
* Custom data types handler to use.
*/
public static CustomDataTypesHandler customDataTypesHandler;
private static final String[] DRIVERS = { private static final String[] DRIVERS = {
"h2:", "org.h2.Driver", "h2:", "org.h2.Driver",
"Cache:", "com.intersys.jdbc.CacheDriver", "Cache:", "com.intersys.jdbc.CacheDriver",
...@@ -117,6 +123,15 @@ public class JdbcUtils { ...@@ -117,6 +123,15 @@ public class JdbcUtils {
throw DbException.convert(e); 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 { ...@@ -682,6 +682,11 @@ public class DataType {
return ValueGeometry.getFromGeometry(x); return ValueGeometry.getFromGeometry(x);
} }
default: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getValue(type,
rs.getObject(columnIndex),
session.getDataHandler());
}
throw DbException.throwInternalError("type="+type); throw DbException.throwInternalError("type="+type);
} }
return v; return v;
...@@ -764,6 +769,9 @@ public class DataType { ...@@ -764,6 +769,9 @@ public class DataType {
case Value.GEOMETRY: case Value.GEOMETRY:
return GEOMETRY_CLASS_NAME; return GEOMETRY_CLASS_NAME;
default: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getDataTypeClassName(type);
}
throw DbException.throwInternalError("type="+type); throw DbException.throwInternalError("type="+type);
} }
} }
...@@ -779,6 +787,9 @@ public class DataType { ...@@ -779,6 +787,9 @@ public class DataType {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?"); throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?");
} }
DataType dt = TYPES_BY_VALUE_TYPE.get(type); DataType dt = TYPES_BY_VALUE_TYPE.get(type);
if (dt == null && JdbcUtils.customDataTypesHandler != null) {
dt = JdbcUtils.customDataTypesHandler.getDataTypeById(type);
}
if (dt == null) { if (dt == null) {
dt = TYPES_BY_VALUE_TYPE.get(Value.NULL); dt = TYPES_BY_VALUE_TYPE.get(Value.NULL);
} }
...@@ -971,6 +982,9 @@ public class DataType { ...@@ -971,6 +982,9 @@ public class DataType {
} else if (LocalDateTimeUtils.isOffsetDateTime(x)) { } else if (LocalDateTimeUtils.isOffsetDateTime(x)) {
return Value.TIMESTAMP_TZ; return Value.TIMESTAMP_TZ;
} else { } else {
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getTypeIdFromClass(x);
}
return Value.JAVA_OBJECT; return Value.JAVA_OBJECT;
} }
} }
...@@ -1094,6 +1108,9 @@ public class DataType { ...@@ -1094,6 +1108,9 @@ public class DataType {
} else if (LocalDateTimeUtils.isOffsetDateTime(x.getClass())) { } else if (LocalDateTimeUtils.isOffsetDateTime(x.getClass())) {
return LocalDateTimeUtils.offsetDateTimeToValue(x); return LocalDateTimeUtils.offsetDateTimeToValue(x);
} else { } else {
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getValue(type, x, session.getDataHandler());
}
return ValueJavaObject.getNoCopy(x, null, session.getDataHandler()); return ValueJavaObject.getNoCopy(x, null, session.getDataHandler());
} }
} }
...@@ -1132,7 +1149,11 @@ public class DataType { ...@@ -1132,7 +1149,11 @@ public class DataType {
* @return the data type object * @return the data type object
*/ */
public static DataType getTypeByName(String s) { 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 { ...@@ -1178,7 +1199,29 @@ public class DataType {
case Value.LONG: case Value.LONG:
case Value.SHORT: case Value.SHORT:
return true; 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: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.supportsAdd(type);
}
return false; return false;
} }
} }
...@@ -1202,7 +1245,31 @@ public class DataType { ...@@ -1202,7 +1245,31 @@ public class DataType {
return Value.DECIMAL; return Value.DECIMAL;
case Value.SHORT: case Value.SHORT:
return Value.LONG; 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: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getAddProofType(type);
}
return type; return type;
} }
} }
...@@ -1253,12 +1320,44 @@ public class DataType { ...@@ -1253,12 +1320,44 @@ public class DataType {
} else if (paramClass == Array.class) { } else if (paramClass == Array.class) {
return new JdbcArray(conn, v, 0); 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(), Object o = SysProperties.serializeJavaObject ? JdbcUtils.deserialize(v.getBytes(),
conn.getSession().getDataHandler()) : v.getObject(); conn.getSession().getDataHandler()) : v.getObject();
if (paramClass.isAssignableFrom(o.getClass())) { if (paramClass.isAssignableFrom(o.getClass())) {
return o; 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()); throw DbException.getUnsupportedException("converting to class " + paramClass.getName());
} }
......
...@@ -530,6 +530,10 @@ public class Transfer { ...@@ -530,6 +530,10 @@ public class Transfer {
} }
break; break;
default: default:
if (JdbcUtils.customDataTypesHandler != null) {
writeBytes(v.getBytesNoCopy());
break;
}
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "type=" + type); throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "type=" + type);
} }
} }
...@@ -706,6 +710,9 @@ public class Transfer { ...@@ -706,6 +710,9 @@ public class Transfer {
} }
return ValueGeometry.get(readString()); return ValueGeometry.get(readString());
default: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.convert(ValueBytes.getNoCopy(readBytes()), type);
}
throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "type=" + type); throw DbException.get(ErrorCode.CONNECTION_BROKEN_1, "type=" + type);
} }
} }
......
...@@ -274,56 +274,59 @@ public abstract class Value { ...@@ -274,56 +274,59 @@ public abstract class Value {
static int getOrder(int type) { static int getOrder(int type) {
switch (type) { switch (type) {
case UNKNOWN: case UNKNOWN:
return 1; return 1_000;
case NULL: case NULL:
return 2; return 2_000;
case STRING: case STRING:
return 10; return 10_000;
case CLOB: case CLOB:
return 11; return 11_000;
case STRING_FIXED: case STRING_FIXED:
return 12; return 12_000;
case STRING_IGNORECASE: case STRING_IGNORECASE:
return 13; return 13_000;
case BOOLEAN: case BOOLEAN:
return 20; return 20_000;
case BYTE: case BYTE:
return 21; return 21_000;
case SHORT: case SHORT:
return 22; return 22_000;
case INT: case INT:
return 23; return 23_000;
case LONG: case LONG:
return 24; return 24_000;
case DECIMAL: case DECIMAL:
return 25; return 25_000;
case FLOAT: case FLOAT:
return 26; return 26_000;
case DOUBLE: case DOUBLE:
return 27; return 27_000;
case TIME: case TIME:
return 30; return 30_000;
case DATE: case DATE:
return 31; return 31_000;
case TIMESTAMP: case TIMESTAMP:
return 32; return 32_000;
case TIMESTAMP_TZ: case TIMESTAMP_TZ:
return 34; return 34_000;
case BYTES: case BYTES:
return 40; return 40_000;
case BLOB: case BLOB:
return 41; return 41_000;
case JAVA_OBJECT: case JAVA_OBJECT:
return 42; return 42_000;
case UUID: case UUID:
return 43; return 43_000;
case GEOMETRY: case GEOMETRY:
return 44; return 44_000;
case ARRAY: case ARRAY:
return 50; return 50_000;
case RESULT_SET: case RESULT_SET:
return 51; return 51_000;
default: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.getDataTypeOrder(type);
}
throw DbException.throwInternalError("type:"+type); throw DbException.throwInternalError("type:"+type);
} }
} }
...@@ -967,6 +970,9 @@ public abstract class Value { ...@@ -967,6 +970,9 @@ public abstract class Value {
case GEOMETRY: case GEOMETRY:
return ValueGeometry.get(s); return ValueGeometry.get(s);
default: default:
if (JdbcUtils.customDataTypesHandler != null) {
return JdbcUtils.customDataTypesHandler.convert(this, targetType);
}
throw DbException.throwInternalError("type=" + targetType); throw DbException.throwInternalError("type=" + targetType);
} }
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
......
...@@ -91,6 +91,7 @@ import org.h2.test.jdbc.TestCallableStatement; ...@@ -91,6 +91,7 @@ import org.h2.test.jdbc.TestCallableStatement;
import org.h2.test.jdbc.TestCancel; import org.h2.test.jdbc.TestCancel;
import org.h2.test.jdbc.TestConcurrentConnectionUsage; import org.h2.test.jdbc.TestConcurrentConnectionUsage;
import org.h2.test.jdbc.TestConnection; import org.h2.test.jdbc.TestConnection;
import org.h2.test.jdbc.TestCustomDataTypesHandler;
import org.h2.test.jdbc.TestDatabaseEventListener; import org.h2.test.jdbc.TestDatabaseEventListener;
import org.h2.test.jdbc.TestDriver; import org.h2.test.jdbc.TestDriver;
import org.h2.test.jdbc.TestJavaObject; import org.h2.test.jdbc.TestJavaObject;
...@@ -772,6 +773,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -772,6 +773,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestTransactionIsolation()); addTest(new TestTransactionIsolation());
addTest(new TestUpdatableResultSet()); addTest(new TestUpdatableResultSet());
addTest(new TestZloty()); addTest(new TestZloty());
addTest(new TestCustomDataTypesHandler());
// jdbcx // jdbcx
addTest(new TestConnectionPool()); addTest(new TestConnectionPool());
......
aacute aaload aastore abalance abba abbreviate abbreviated abbreviates aacute aaload aastore abalance abba abbreviate abbreviated abbreviates
abbreviation ability able abnormal abnormally abort aborted about above abs abbreviation abi ability able abnormal abnormally abort aborted about above abs
absence absent absolute absolutely abstract abstraction abstractions abstracts absence absent absolute absolutely abstract abstraction abstractions abstracts
aca accept acceptable acceptance accepted accepting accepts access accessadmin aca accept acceptable acceptance accepted accepting accepts access accessadmin
accessed accesses accessible accessing accesskey accessor accidentally accessed accesses accessible accessing accesskey accessor accidentally
...@@ -97,7 +97,7 @@ classifications classloader classloaders classname classpath clause clauses claz ...@@ -97,7 +97,7 @@ classifications classloader classloaders classname classpath clause clauses claz
clean cleaned cleaner cleaning cleanup clear cleared clearer clearing clearly clean cleaned cleaner cleaning cleanup clear cleared clearer clearing clearly
clears cleartext click clicked clicking client clients clinton clip clipboard clears cleartext click clicked clicking client clients clinton clip clipboard
clob clobs clock clocks clone cloneable cloned closable close closeable closed clob clobs clock clocks clone cloneable cloned closable close closeable closed
closely closer closes closest closing cloud clubs clue clunky cluster clustered closely closer closes closest closing cloud cls clubs clue clunky cluster clustered
clustering cmd cms cnf cnrs cnt coalesce code codebase codebook coded codegen clustering cmd cms cnf cnrs cnt coalesce code codebase codebook coded codegen
codehaus codes coding codist coffee cognitect col cold coldrick coll codehaus codes coding codist coffee cognitect col cold coldrick coll
collaborative collapse collate collateral collation collations collator collators collaborative collapse collate collateral collation collations collator collators
...@@ -234,12 +234,12 @@ exfsys exhausted exhibit exist existed existence existing exists exit exited ...@@ -234,12 +234,12 @@ exfsys exhausted exhibit exist existed existence existing exists exit exited
exits exp expand expanded expands expansion expect expected expecting expedites exits exp expand expanded expands expansion expect expected expecting expedites
expense expenses expensive experience experimental experiments experts expiration expense expenses expensive experience experimental experiments experts expiration
expired expires explain explanation explicit explicitconstructorcall explicitly expired expires explain explanation explicit explicitconstructorcall explicitly
exploit explorer exponent exponential export exported exports expose exposed expr exploit explorer exponent exponential export exported exports expose exposed exposes
express expressed expression expressions expressly exps ext extend extendable expr express expressed expression expressions expressly exps ext extend extendable
extended extending extends extensible extension extensions extensively extent extended extending extends extensible extension extensions extensively extent
extern external externally extra extract extracted extracting extracts extras extern external externally extra extract extracted extracting extracts extras
extreme extremely extremes eye fabien fabric facade face facilitate facility fact extreme extremely extremes extrinsic eye fabien fabric facade face facilitate facility
factor factorial factories factory factual fadd fail failed failing fails failure fact factor factorial factories factory factual fadd fail failed failing fails failure
failures fair fake fall fallback falls faload false familiar families family faq failures fair fake fall fallback falls faload false familiar families family faq
far fashion fashioned fast faster fastest fastore fat fatal faulhaber fault far fashion fashioned fast faster fastest fastore fat fatal faulhaber fault
favicon favorite fbj fcmpg fcmpl fconst fdiv feature features feb februar favicon favorite fbj fcmpg fcmpl fconst fdiv feature features feb februar
...@@ -252,7 +252,7 @@ firebird firebirdsql fired firefox firewall first firstname fish fit fitness fit ...@@ -252,7 +252,7 @@ firebird firebirdsql fired firefox firewall first firstname fish fit fitness fit
fitting five fix fixed fixes fixing fkcolumn fktable flag flags flash flashback fitting five fix fixed fixes fixing fkcolumn fktable flag flags flash flashback
flat fle fletcher flexibility flexible flexive flip flipped fload float floating flat fle fletcher flexibility flexible flexive flip flipped fload float floating
flooding floor florent flow flower flows fluent fluid flush flushed flushes flooding floor florent flow flower flows fluent fluid flush flushed flushes
flushing flux fly flyway fmb fmc fml fmrn fmul fmxx fmxxx fneg focus focusable flushing flux fly flyway fmb fmc fml fmrn fmt fmul fmxx fmxxx fneg focus focusable
fog fogh folder follow followed following follows font fontes foo footer footers fog fogh folder follow followed following follows font fontes foo footer footers
footprint for forall forbidden force forced forcefully forces forcing foreign footprint for forall forbidden force forced forcefully forces forcing foreign
forever forge forget forgetting forgot forgotten fork form formal format forever forge forget forgetting forgot forgotten fork form formal format
...@@ -297,12 +297,12 @@ however hprof href hsql hsqldb htime htm html http httpdocs https huang hub huff ...@@ -297,12 +297,12 @@ however hprof href hsql hsqldb htime htm html http httpdocs https huang hub huff
huffman huge human hundred hundreds hurt hyc hyde hyperbolic hyperlink hypersonic huffman huge human hundred hundreds hurt hyc hyde hyperbolic hyperlink hypersonic
hyt iacute iadd iaload iand iastore ibm iced iceland iciql icirc icmpeq icmpge hyt iacute iadd iaload iand iastore ibm iced iceland iciql icirc icmpeq icmpge
icmpgt icmple icmplt icmpne ico icon iconified icons iconst icu ide idea ideal icmpgt icmple icmplt icmpne ico icon iconified icons iconst icu ide idea ideal
ideas identical identified identifier identifiers identify identifying identities ideas identical identification identified identifier identifiers identify identifying
identity idiomatic idiv idle ids idx idxname iee ieee iexcl iface ifeq ifexists identities identity idiomatic idiv idle ids idx idxname iee ieee iexcl iface ifeq
ifge ifgt ifle iflt ifne ifnonnull ifnull iframe ifx ignore ignorecase ignored ifexists ifge ifgt ifle iflt ifne ifnonnull ifnull iframe ifx ignore ignorecase ignored
ignoredriverprivileges ignorelist ignores ignoring igrave iinc ikura ikvm ikvmc ignoredriverprivileges ignorelist ignores ignoring igrave iinc ikura ikvm ikvmc
illegal iload image imageio images img iml immediately immutable imola imp impact illegal iload image imageio images imaginary img iml immediately immutable imola imp
imperial impersonate impl imple implement implementation implementations impact imperial impersonate impl imple implement implementation implementations
implemented implementing implements implication implicit implicitly implied implemented implementing implements implication implicit implicitly implied
implies import important imported importing imports impose imposes impossible implies import important imported importing imports impose imposes impossible
improperly improve improved improvement improvements improves improving imul improperly improve improved improvement improvements improves improving imul
...@@ -329,11 +329,11 @@ instead institutes instr instruction instructions instrument instrumentation ...@@ -329,11 +329,11 @@ instead institutes instr instruction instructions instrument instrumentation
instrumented int intact integer integers integrate integrated integration instrumented int intact integer integers integrate integrated integration
integrity intellectual intelli intended intentional inter interaction interactive integrity intellectual intelli intended intentional inter interaction interactive
intercepted interest interested interesting interface interfaces interleave intercepted interest interested interesting interface interfaces interleave
interleaved interleaving intermediate intern internal internally international interleaved interleaving intermediate intern internal internally internals
internationalization internet interpolation interpret interpreted interpreter international internationalization internet interpolation interpret interpreted
interpreting interprets interrupt interrupted interrupting interruption intersect interpreter interpreting interprets interrupt interrupted interrupting interruption
intersecting intersection intersects intersys interval intervals into intra intersect intersecting intersection intersects intersys interval intervals into
introduce introduced introduction inttypes inv inval invalid invalidate intra introduce introduced introduction inttypes inv inval invalid invalidate
invalidated invectorate invented invention inventor inversed invert inverting invalidated invectorate invented invention inventor inversed invert inverting
invisible invocation invoice invoiceid invoke invokeinterface invoker invisible invocation invoice invoiceid invoke invokeinterface invoker
invokespecial invokestatic invokevirtual involve involved involves ior iota ipt invokespecial invokestatic invokevirtual involve involved involves ior iota ipt
...@@ -363,8 +363,8 @@ lawsuits lax layer layers layout lazily lazy lcase lceil lck lcmp lconst ldap ...@@ -363,8 +363,8 @@ lawsuits lax layer layers layout lazily lazy lcase lceil lck lcmp lconst ldap
ldbc ldc ldiv ldquo lea leach lead leading leads leaf leak leaked leaks leaning ldbc ldc ldiv ldquo lea leach lead leading leads leaf leak leaked leaks leaning
leap learning least leave leaves leaving lee left leftmost leftover legacy legal leap learning least leave leaves leaving lee left leftmost leftover legacy legal
legend lehmann lempel len length lengths lenient leod less lesser let lets letter legend lehmann lempel len length lengths lenient leod less lesser let lets letter
letters level levels lfloor lgpl liability liable lib liberal libraries library letters level levels lexicographical lfloor lgpl liability liable lib liberal libraries
licensable license licensed licensees licenses licensing lies life lifespan library licensable license licensed licensees licenses licensing lies life lifespan
lifetime liftweb light lightweight like likely lim limit limitation limitations lifetime liftweb light lightweight like likely lim limit limitation limitations
limited limiting limits line linear linearly linefeed lines linestring lineup limited limiting limits line linear linearly linefeed lines linestring lineup
link linkage linked links linq lint linux liq liqui lir lirs lisboa list listed link linkage linked links linq lint linux liq liqui lir lirs lisboa list listed
...@@ -431,9 +431,9 @@ november now nowait nowrap npl nsi nsis nsub ntext ntfs nth ntilde nucleus nul ...@@ -431,9 +431,9 @@ november now nowait nowrap npl nsi nsis nsub ntext ntfs nth ntilde nucleus nul
null nullable nullid nullif nulls nullsoft num number numbering numbers numeral null nullable nullid nullif nulls nullsoft num number numbering numbers numeral
numerals numeric numerical nuxeo nvarchar nvl oacute obey obj object objects numerals numeric numerical nuxeo nvarchar nvl oacute obey obj object objects
obligation obligations observer obsolete obtain obtained obtains obviously obligation obligations observer obsolete obtain obtained obtains obviously
occupied occupies occupy occur occurred occurrence occurrences occurs ocirc octal occasionally occupied occupies occupy occur occurred occurrence occurrences occurs
octet october octype odbc odbcad odd odg off offending offer offered offering ocirc octal octet october octype odbc odbcad odd odg off offending offer offered
offers office official offline offset offsets often ogc ograve ohloh oid okay offering offers office official offline offset offsets often ogc ograve ohloh oid okay
okra olap olapsys old older oldest oline oliver olivier omega omicron omissions okra olap olapsys old older oldest oline oliver olivier omega omicron omissions
omitted omitting once onchange onclick one ones onfocus ongoing onkeydown onkeyup omitted omitting once onchange onclick one ones onfocus ongoing onkeydown onkeyup
online onload only onmousedown onmousemove onmouseout onmouseover onmouseup online onload only onmousedown onmousemove onmouseout onmouseover onmouseup
...@@ -554,7 +554,7 @@ ridvan rife right rightmost rights rijndael ring rioyxlgt risk risks risky rlm ...@@ -554,7 +554,7 @@ ridvan rife right rightmost rights rijndael ring rioyxlgt risk risks risky rlm
rmd rmdir rmerr rmi rmiregistry rnd rnfr rnto road roadmap roads robert roc rogue rmd rmdir rmerr rmi rmiregistry rnd rnfr rnto road roadmap roads robert roc rogue
rojas role roles roll rollback rollbacks rolled rolling rollover rolls roman room rojas role roles roll rollback rollbacks rolled rolling rollover rolls roman room
root roots rot rotate round rounded rounding roundmagic rounds routine routinely root roots rot rotate round rounded rounding roundmagic rounds routine routinely
row rowcount rowid rowlock rownum rows rowscn rowsize roy royalty rpad rpm rsa routines row rowcount rowid rowlock rownum rows rowscn rowsize roy royalty rpad rpm rsa
rsaquo rsquo rss rtree rtrim ruby ruebezahl rule rules run rund rundll runnable rsaquo rsquo rss rtree rtrim ruby ruebezahl rule rules run rund rundll runnable
runner runners running runs runscript runtime rwd rws sabine safari safe safely runner runners running runs runscript runtime rwd rws sabine safari safe safely
safes safety said sainsbury salary sale sales saload salt salz sam same safes safety said sainsbury salary sale sales saload salt salz sam same
...@@ -602,8 +602,8 @@ specification specified specifies specify specifying specs speed speeds speedup ...@@ -602,8 +602,8 @@ specification specified specifies specify specifying specs speed speeds speedup
spell spellcheck spellchecker spelled spelling spends spent sphere spi spiced spell spellcheck spellchecker spelled spelling spends spent sphere spi spiced
spin spliced split splits splitting sponsored spot spots spr spread spring spin spliced split splits splitting sponsored spot spots spr spread spring
springframework springfuse sql sqlexpress sqli sqlite sqlj sqlnulls sqlserver springframework springfuse sql sqlexpress sqli sqlite sqlj sqlnulls sqlserver
sqlstate sqlxml sqrt square squill squirrel src srcs srid ssd ssl stabilize sqlstate sqlxml sqrt square squill squirrel src srcs srid ssd ssl stability
stable stack stackable stacked stage stages stamp standalone standard stabilize stable stack stackable stacked stage stages stamp standalone standard
standardized standards standby standing stands star staring start started starter standardized standards standby standing stands star staring start started starter
starting starts startup starvation starves stat state stated statement statements starting starts startup starvation starves stat state stated statement statements
states static stating station statistic statistical statisticlog statistics stats states static stating station statistic statistical statisticlog statistics stats
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论