mirror of https://github.com/apache/openjpa.git
OPENJPA-983: FirebirdDictionary improvements
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@763992 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
20b3559bbe
commit
62aabafc53
|
@ -18,44 +18,460 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.jdbc.sql;
|
package org.apache.openjpa.jdbc.sql;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
|
import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
|
||||||
import org.apache.openjpa.jdbc.schema.Column;
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
|
import org.apache.openjpa.jdbc.schema.ForeignKey;
|
||||||
|
import org.apache.openjpa.jdbc.schema.Index;
|
||||||
|
import org.apache.openjpa.jdbc.schema.Sequence;
|
||||||
|
import org.apache.openjpa.jdbc.schema.Unique;
|
||||||
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.util.UnsupportedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dictionary for Firebird.
|
* Dictionary for Firebird. Supports Firebird versions 1.5, 2.0 and 2.1.
|
||||||
*/
|
*/
|
||||||
public class FirebirdDictionary
|
public class FirebirdDictionary
|
||||||
extends InterbaseDictionary {
|
extends DBDictionary {
|
||||||
|
|
||||||
|
public int firebirdVersion = 0;
|
||||||
|
public int indexedVarcharMaxSizeFB15 = 252;
|
||||||
|
public String rangeSyntax = null;
|
||||||
|
protected long maxRowNumberInRange = 16000000000L;
|
||||||
|
|
||||||
|
protected String alterSequenceSQLFB15 = "SET GENERATOR {0} TO {1}";
|
||||||
|
protected String alterSequenceSQLFB20 =
|
||||||
|
"ALTER SEQUENCE {0} RESTART WITH {1}";
|
||||||
|
protected String createSequenceSQLFB15 = "CREATE GENERATOR {0}";
|
||||||
|
protected String createSequenceSQLFB20 = "CREATE SEQUENCE {0}";
|
||||||
|
protected String dropSequenceSQLFB15 = "DROP GENERATOR ";
|
||||||
|
protected String nextSequenceQueryFB15 =
|
||||||
|
"SELECT GEN_ID({0}, 1) FROM RDB$DATABASE";
|
||||||
|
protected String nextSequenceQueryFB20 =
|
||||||
|
"SELECT NEXT VALUE FOR {0} FROM RDB$DATABASE";
|
||||||
|
|
||||||
|
protected String alterSequenceSQL = alterSequenceSQLFB20;
|
||||||
|
protected String createSequenceSQL = createSequenceSQLFB20;
|
||||||
|
|
||||||
|
public static final int FB_VERSION_15 = 15;
|
||||||
|
public static final int FB_VERSION_20 = 20;
|
||||||
|
public static final int FB_VERSION_21 = 21;
|
||||||
|
|
||||||
|
public static final String RANGE_SYNTAX_FIRST_SKIP = "firstskip";
|
||||||
|
public static final String RANGE_SYNTAX_ROWS = "rows";
|
||||||
|
|
||||||
|
private static final Localizer _loc =
|
||||||
|
Localizer.forPackage(FirebirdDictionary.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public FirebirdDictionary() {
|
public FirebirdDictionary() {
|
||||||
platform = "Firebird";
|
platform = "Firebird";
|
||||||
|
validationSQL = "SELECT 1 FROM RDB$DATABASE";
|
||||||
|
supportsDeferredConstraints = false;
|
||||||
|
|
||||||
// Firebird 1.5+ locking statement
|
useGetStringForClobs = true;
|
||||||
|
useSetStringForClobs = true;
|
||||||
|
useGetBytesForBlobs = true;
|
||||||
|
useSetBytesForBlobs = true;
|
||||||
|
|
||||||
|
maxTableNameLength = 31;
|
||||||
|
maxColumnNameLength = 31;
|
||||||
|
maxConstraintNameLength = 31;
|
||||||
|
maxIndexNameLength = 31;
|
||||||
|
|
||||||
|
supportsSelectStartIndex = true;
|
||||||
|
supportsSelectEndIndex = true;
|
||||||
|
|
||||||
|
supportsMultipleNontransactionalResultSets = false;
|
||||||
|
|
||||||
|
nextSequenceQuery = nextSequenceQueryFB20;
|
||||||
|
sequenceSQL =
|
||||||
|
"SELECT NULL AS SEQUENCE_SCHEMA, RDB$GENERATOR_NAME "
|
||||||
|
+ "AS SEQUENCE_NAME FROM RDB$GENERATORS "
|
||||||
|
+ "WHERE (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0) ";
|
||||||
|
sequenceNameSQL = "AND RDB$GENERATOR_NAME = ?";
|
||||||
|
|
||||||
|
// A rough sum of reserved words in Firebird 1.0 - 2.1.
|
||||||
|
reservedWordSet.addAll(Arrays.asList(new String[] { "ACTIVE", "ADMIN",
|
||||||
|
"AFTER", "ASCENDING", "AUTO", "AUTODDL", "BASED", "BASENAME",
|
||||||
|
"BASE_NAME", "BEFORE", "BIGINT", "BLOB", "BLOBEDIT", "BUFFER",
|
||||||
|
"CACHE", "CHECK_POINT_LEN", "CHECK_POINT_LENGTH", "COMPILETIME",
|
||||||
|
"COMPUTED", "CLOSE", "CONDITIONAL", "CONTAINING", "CSTRING",
|
||||||
|
"CURRENT_CONNECTION", "CURRENT_ROLE", "CURRENT_TRANSACTION",
|
||||||
|
"DATABASE", "DB_KEY", "DEBUG", "DESCENDING", "DO", "ECHO", "EDIT",
|
||||||
|
"ENTRY_POINT", "EVENT", "EXIT", "EXTERN", "FILE", "FILTER",
|
||||||
|
"FREE_IT", "FUNCTION", "GDSCODE", "GENERATOR", "GEN_ID", "GLOBAL",
|
||||||
|
"GOTO", "GROUP_COMMIT_WAIT", "GROUP_COMMIT_WAIT_TIME", "HELP",
|
||||||
|
"IF", "INACTIVE", "INDEX", "INIT", "INPUT_TYPE", "ISQL",
|
||||||
|
"LC_MESSAGES", "LC_TYPE", "LEV", "LOGFILE", "LOG_BUFFER_SIZE",
|
||||||
|
"LOG_BUF_SIZE", "LONG", "MANUAL", "MAXIMUM", "MAXIMUM_SEGMENT",
|
||||||
|
"MAX_SEGMENT", "MERGE", "MESSAGE", "MINUTE", "MODULE_NAME",
|
||||||
|
"NOAUTO", "NUM_LOG_BUFS", "NUM_LOG_BUFFERS", "OUTPUT_TYPE",
|
||||||
|
"OVERFLOW", "PAGE", "PAGELENGTH", "PAGES", "PAGE_SIZE",
|
||||||
|
"PARAMETER", "PASSWORD", "PLAN", "POST_EVENT", "PROCEDURE",
|
||||||
|
"PROTECTED", "QUIT", "RAW_PARTITIONS", "RDB$DB_KEY",
|
||||||
|
"RECORD_VERSION", "RECREATE", "RELEASE", "RESERV", "RESERVING",
|
||||||
|
"RETAIN", "RETURN", "RETURNING_VALUES", "RETURNS", "ROLE",
|
||||||
|
"RUNTIME", "SAVEPOINT", "SEGMENT", "SHADOW", "SHARED", "SHELL",
|
||||||
|
"SHOW", "SINGULAR", "SNAPSHOT", "SORT", "SQLWARNING", "STABILITY",
|
||||||
|
"START", "STARTING", "STARTS", "STATEMENT", "STATIC", "STATISTICS",
|
||||||
|
"SUB_TYPE", "SUSPEND", "TERMINATOR", "TRIGGER", "VARIABLE",
|
||||||
|
"VERSION", "WAIT", "WEEKDAY", "WHILE" }));
|
||||||
|
|
||||||
|
binaryTypeName = "BLOB";
|
||||||
|
bitTypeName = "SMALLINT";
|
||||||
|
charTypeName = "CHAR(1)";
|
||||||
|
clobTypeName = "BLOB SUB_TYPE 1";
|
||||||
|
doubleTypeName = "DOUBLE PRECISION";
|
||||||
|
floatTypeName = "DOUBLE PRECISION";
|
||||||
|
longVarbinaryTypeName = "BLOB";
|
||||||
|
longVarcharTypeName = "BLOB SUB_TYPE 1";
|
||||||
|
realTypeName = "FLOAT";
|
||||||
|
smallintTypeName = "SMALLINT";
|
||||||
|
tinyintTypeName = "SMALLINT";
|
||||||
|
varbinaryTypeName = "BLOB";
|
||||||
|
|
||||||
|
supportsLockingWithDistinctClause = false;
|
||||||
supportsLockingWithMultipleTables = false;
|
supportsLockingWithMultipleTables = false;
|
||||||
|
supportsLockingWithOuterJoin = false;
|
||||||
|
supportsLockingWithInnerJoin = false;
|
||||||
forUpdateClause = "FOR UPDATE WITH LOCK";
|
forUpdateClause = "FOR UPDATE WITH LOCK";
|
||||||
|
supportsQueryTimeout = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine Firebird version and configure itself accordingly.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void connectedConfiguration(Connection conn) throws SQLException {
|
||||||
|
super.connectedConfiguration(conn);
|
||||||
|
firebirdVersion = determineFirebirdVersion(conn);
|
||||||
|
determineRangeSyntax();
|
||||||
|
|
||||||
|
if (firebirdVersion == FB_VERSION_21)
|
||||||
|
selectWordSet.add("WITH");
|
||||||
|
if (!(firebirdVersion == FB_VERSION_21)) {
|
||||||
|
crossJoinClause = "JOIN";
|
||||||
|
requiresConditionForCrossJoin = true;
|
||||||
|
}
|
||||||
|
if (firebirdVersion == FB_VERSION_15) {
|
||||||
|
stringLengthFunction = "STRLEN({0})";
|
||||||
|
trimLeadingFunction = "LTRIM({0})";
|
||||||
|
trimTrailingFunction = "RTRIM({0})";
|
||||||
|
trimBothFunction = "LTRIM(RTRIM({0}))";
|
||||||
|
alterSequenceSQL = alterSequenceSQLFB15;
|
||||||
|
createSequenceSQL = createSequenceSQLFB15;
|
||||||
|
nextSequenceQuery = nextSequenceQueryFB15;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use either <code>FIRST <p> SKIP <q></code> or
|
||||||
|
* <code>ROWS <m> TO <n></code> syntax. If <code>ROWS</code>
|
||||||
|
* variant is used and <code>end</code> equals {@link Long#MAX_VALUE}, a
|
||||||
|
* constant is used as <code><n></code> value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void appendSelectRange(SQLBuffer buf, long start, long end,
|
||||||
|
boolean subselect) {
|
||||||
|
if (RANGE_SYNTAX_FIRST_SKIP.equals(rangeSyntax)) {
|
||||||
|
if (end != Long.MAX_VALUE)
|
||||||
|
buf.append(" FIRST ").appendValue(end - start);
|
||||||
|
if (start != 0)
|
||||||
|
buf.append(" SKIP ").appendValue(start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.append(" ROWS ");
|
||||||
|
if (start == 0) {
|
||||||
|
buf.appendValue(end);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.appendValue(start + 1).append(" TO ");
|
||||||
|
if (end == Long.MAX_VALUE)
|
||||||
|
buf.appendValue(maxRowNumberInRange);
|
||||||
|
else
|
||||||
|
buf.appendValue(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine Firebird version either by using JDBC 3 methods or, if they
|
||||||
|
* are not available, by parsing the value returned by
|
||||||
|
* {@linkplain DatabaseMetaData#getDatabaseProductVersion()}. User can
|
||||||
|
* override Firebird version.
|
||||||
|
*/
|
||||||
|
protected int determineFirebirdVersion(Connection con)
|
||||||
|
throws SQLException {
|
||||||
|
// Let user override firebirdVersion.
|
||||||
|
if (firebirdVersion != 0)
|
||||||
|
return firebirdVersion;
|
||||||
|
|
||||||
|
DatabaseMetaData metaData = con.getMetaData();
|
||||||
|
int maj = 0;
|
||||||
|
int min = 0;
|
||||||
|
if (isJDBC3) {
|
||||||
|
maj = metaData.getDatabaseMajorVersion();
|
||||||
|
min = metaData.getDatabaseMinorVersion();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
// The product version looks like
|
||||||
|
// "LI-V2.1.1.17910 Firebird 2.1,LI-V2.1.1.17910 Firebird
|
||||||
|
// 2.1/tcp (hostname)/P10" or
|
||||||
|
// "WI-V1.5.5.4926 Firebird 1.52WI-V1.5.5.4926 Firebird 1.5/tcp
|
||||||
|
// (hostname)/P10"
|
||||||
|
String productVersion = metaData.getDatabaseProductVersion();
|
||||||
|
Pattern p = Pattern.compile(".*-V(\\d)\\.(\\d)\\..*",
|
||||||
|
Pattern.CASE_INSENSITIVE);
|
||||||
|
Matcher m = p.matcher(productVersion);
|
||||||
|
m.matches();
|
||||||
|
String majString = m.group(1);
|
||||||
|
String minString = m.group(2);
|
||||||
|
maj = Integer.parseInt(majString);
|
||||||
|
min = Integer.parseInt(minString);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// We don't understand the version format.
|
||||||
|
if (log.isWarnEnabled())
|
||||||
|
log.warn(e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (maj < 2)
|
||||||
|
return FB_VERSION_15;
|
||||||
|
if (maj == 2 && min == 0)
|
||||||
|
return FB_VERSION_20;
|
||||||
|
return FB_VERSION_21;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine range syntax to be used depending on Firebird version.
|
||||||
|
* User can override range syntax.
|
||||||
|
*/
|
||||||
|
protected void determineRangeSyntax() {
|
||||||
|
// Let user override rangeSyntax.
|
||||||
|
if (rangeSyntax == null)
|
||||||
|
rangeSyntax =
|
||||||
|
(firebirdVersion == FB_VERSION_15) ? RANGE_SYNTAX_FIRST_SKIP
|
||||||
|
: RANGE_SYNTAX_ROWS;
|
||||||
|
|
||||||
|
if (RANGE_SYNTAX_FIRST_SKIP.equals(rangeSyntax))
|
||||||
|
rangePosition = RANGE_PRE_DISTINCT;
|
||||||
|
else
|
||||||
|
rangePosition = RANGE_POST_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <code><value> AS <type></code>.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public String getPlaceholderValueString(Column col) {
|
public String getPlaceholderValueString(Column col) {
|
||||||
return super.getPlaceholderValueString(col)
|
return super.getPlaceholderValueString(col) + " AS "
|
||||||
+ " AS " + getTypeName(col);
|
+ getTypeName(col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <code>%</code> if <code>tableName</code> is <code>null</code>,
|
||||||
|
* otherwise delegate to super implementation.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getTableNameForMetadata(String tableName) {
|
||||||
|
return (tableName == null) ? "%" : super
|
||||||
|
.getTableNameForMetadata(tableName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return <code>%</code> if <code>columnName</code> is <code>null</code>,
|
||||||
|
* otherwise delegate to super implementation.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getColumnNameForMetadata(String columnName) {
|
||||||
|
return (columnName == null) ? "%" : super
|
||||||
|
.getColumnNameForMetadata(columnName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return
|
||||||
|
* <code>ALTER TABLE <table name> DROP <col name></code>.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String[] getDropColumnSQL(Column column) {
|
||||||
|
return new String[] { "ALTER TABLE "
|
||||||
|
+ getFullName(column.getTable(), false) + " DROP " + column };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return either
|
||||||
|
* <code>CREATE SEQUENCE <sequence name></code> or
|
||||||
|
* <code>CREATE GENERATOR <sequence name></code>.
|
||||||
|
* If initial value of sequence is set, return also
|
||||||
|
* an appropriate <code>ALTER</code> statement.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String[] getCreateSequenceSQL(Sequence seq) {
|
||||||
|
String seqName =
|
||||||
|
checkNameLength(getFullName(seq), maxTableNameLength,
|
||||||
|
"long-seq-name");
|
||||||
|
String createSeq =
|
||||||
|
MessageFormat.format(createSequenceSQL, new Object[] { seqName });
|
||||||
|
if (seq.getInitialValue() == 0)
|
||||||
|
return new String[] { createSeq };
|
||||||
|
|
||||||
|
// Use String.valueOf to get rid of possible number formatting.
|
||||||
|
String alterSeq =
|
||||||
|
MessageFormat.format(alterSequenceSQL, new Object[] { seqName,
|
||||||
|
String.valueOf(seq.getInitialValue()) });
|
||||||
|
return new String[] { createSeq, alterSeq };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return Firebird-specific statement to select the list of sequences.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getSequencesSQL(String schemaName, String sequenceName) {
|
||||||
|
StringBuilder buf = new StringBuilder(sequenceSQL);
|
||||||
|
if (sequenceName != null)
|
||||||
|
buf.append(sequenceNameSQL);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call super implementation and trim sequence name. This is because of
|
||||||
|
* trailing spaces problem: <code>RDB$GENERATORS.RDB$GENERATOR_NAME</code>
|
||||||
|
* is <code>CHAR(31)</code> and using <code>RTRIM</code> UDF function on
|
||||||
|
* Firebird 1.5 surprisingly returns a string right-padded with spaces up
|
||||||
|
* to the length of 255.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Sequence newSequence(ResultSet sequenceMeta) throws SQLException {
|
||||||
|
Sequence seq = super.newSequence(sequenceMeta);
|
||||||
|
seq.setName(seq.getName().trim());
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Firebird 1.5 return
|
||||||
|
* <code>DROP GENERATOR <sequence name></code>.
|
||||||
|
* On Firebird 2.0 and later delegate to the super implementation.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String[] getDropSequenceSQL(Sequence seq) {
|
||||||
|
if (firebirdVersion == FB_VERSION_15)
|
||||||
|
return new String[] { dropSequenceSQLFB15 + getFullName(seq) };
|
||||||
|
return super.getDropSequenceSQL(seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throw {@link UnsupportedException}. Firebird in version earlier than 2.1
|
||||||
|
* has no suitable function. Firebird 2.1 has the <code>POSITION</code>
|
||||||
|
* function but using it here results in errors like "data type unknown" or
|
||||||
|
* "expression evaluation not supported".
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
|
||||||
|
FilterValue start) {
|
||||||
|
throw new UnsupportedException(_loc.get("function-not-supported",
|
||||||
|
getClass(), "LOCATE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use
|
||||||
|
* <code>SUBSTRING(<col name> FROM <m> FOR <n>)</code>.
|
||||||
|
* Parameters are inlined because neither parameter binding nor expressions
|
||||||
|
* are accepted by Firebird here. As a result, an
|
||||||
|
* {@link UnsupportedException} is thrown when something else than a
|
||||||
|
* constant is used in <code>start</code> or <code>end</code>.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
|
public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
|
||||||
FilterValue end) {
|
FilterValue end) {
|
||||||
// SUBSTRING in Firebird is of the form:
|
buf.append(substringFunctionName).append("(");
|
||||||
// SELECT SUBSTRING(SOME_COLUMN FROM 1 FOR 5)
|
|
||||||
buf.append("SUBSTRING(");
|
|
||||||
str.appendTo(buf);
|
str.appendTo(buf);
|
||||||
buf.append(" FROM ");
|
buf.append(" FROM ");
|
||||||
start.appendTo(buf);
|
if (start.getValue() instanceof Number) {
|
||||||
buf.append(" + 1");
|
long startLong = toLong(start);
|
||||||
|
buf.append(Long.toString(startLong + 1));
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedException(_loc.get("function-not-supported",
|
||||||
|
getClass(), substringFunctionName + " with non-constants"));
|
||||||
|
}
|
||||||
if (end != null) {
|
if (end != null) {
|
||||||
buf.append(" FOR ");
|
buf.append(" FOR ");
|
||||||
end.appendTo(buf);
|
if (start.getValue() instanceof Number
|
||||||
buf.append(" - (");
|
&& end.getValue() instanceof Number) {
|
||||||
start.appendTo(buf);
|
long startLong = toLong(start);
|
||||||
buf.append(")");
|
long endLong = toLong(end);
|
||||||
|
buf.append(Long.toString(endLong - startLong));
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedException(_loc.get(
|
||||||
|
"function-not-supported", getClass(), substringFunctionName
|
||||||
|
+ " with non-constants"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buf.append(")");
|
buf.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On Firebird 1.5 reduce the size of indexed <code>VARCHAR</code> column
|
||||||
|
* to 252 or a value specified by user. 252 is the maximum Firebird 1.5 can
|
||||||
|
* handle for one-column indexes. On Firebird 2.0 and later delegate to the
|
||||||
|
* super implementation.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String appendSize(Column col, String typeName) {
|
||||||
|
if (firebirdVersion != FB_VERSION_15)
|
||||||
|
return super.appendSize(col, typeName);
|
||||||
|
|
||||||
|
if (col.getType() == Types.VARCHAR
|
||||||
|
&& col.getSize() > indexedVarcharMaxSizeFB15
|
||||||
|
&& col.getTable() != null) {
|
||||||
|
|
||||||
|
if (col.isPrimaryKey()) {
|
||||||
|
col.setSize(indexedVarcharMaxSizeFB15);
|
||||||
|
return super.appendSize(col, typeName);
|
||||||
|
}
|
||||||
|
Index[] indexes = col.getTable().getIndexes();
|
||||||
|
for (Index index : indexes) {
|
||||||
|
if (index.containsColumn(col)) {
|
||||||
|
col.setSize(indexedVarcharMaxSizeFB15);
|
||||||
|
return super.appendSize(col, typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unique[] uniques = col.getTable().getUniques();
|
||||||
|
for (Unique unique : uniques) {
|
||||||
|
if (unique.containsColumn(col)) {
|
||||||
|
col.setSize(indexedVarcharMaxSizeFB15);
|
||||||
|
return super.appendSize(col, typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ForeignKey[] foreignKeys = col.getTable().getForeignKeys();
|
||||||
|
for (ForeignKey foreignKey : foreignKeys) {
|
||||||
|
if (foreignKey.containsColumn(col)) {
|
||||||
|
col.setSize(indexedVarcharMaxSizeFB15);
|
||||||
|
return super.appendSize(col, typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.appendSize(col, typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use error code as SQL state returned by Firebird is ambiguous.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Boolean matchErrorState(int subtype, Set<String> errorStates,
|
||||||
|
SQLException ex) {
|
||||||
|
int errorCode = ex.getErrorCode();
|
||||||
|
return errorStates.contains(String.valueOf(errorCode)) ? Boolean.FALSE
|
||||||
|
: null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,9 +137,9 @@
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
|
||||||
<dictionary class="org.apache.openjpa.jdbc.sql.FirebirdDictionary">
|
<dictionary class="org.apache.openjpa.jdbc.sql.FirebirdDictionary">
|
||||||
<lock></lock>
|
<lock>335544336</lock>
|
||||||
<referential-integrity></referential-integrity>
|
<referential-integrity></referential-integrity>
|
||||||
<object-exists></object-exists>
|
<object-exists>335544665</object-exists>
|
||||||
<object-not-found></object-not-found>
|
<object-not-found></object-not-found>
|
||||||
<optimistic></optimistic>
|
<optimistic></optimistic>
|
||||||
<query></query>
|
<query></query>
|
||||||
|
|
|
@ -3148,6 +3148,86 @@ overridden. It is used only when the schema is generated using the
|
||||||
in alphabetical order -->
|
in alphabetical order -->
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
<section id="ref_guide_dbsetup_dbsupport_firebird">
|
||||||
|
<title>
|
||||||
|
FirebirdDictionary Properties
|
||||||
|
</title>
|
||||||
|
<indexterm zone="ref_guide_dbsetup_dbsupport_firebird">
|
||||||
|
<primary>
|
||||||
|
Firebird
|
||||||
|
</primary>
|
||||||
|
<seealso>
|
||||||
|
DBDictionary
|
||||||
|
</seealso>
|
||||||
|
</indexterm>
|
||||||
|
<para>
|
||||||
|
The <literal>firebird</literal> dictionary understands the following additional
|
||||||
|
properties:
|
||||||
|
</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem id="FirebirdDictionary.FirebirdVersion">
|
||||||
|
<para>
|
||||||
|
<indexterm>
|
||||||
|
<primary>
|
||||||
|
Firebird
|
||||||
|
</primary>
|
||||||
|
<secondary>
|
||||||
|
FirebirdVersion
|
||||||
|
</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<literal>FirebirdVersion</literal>: The database version OpenJPA connects to.
|
||||||
|
This property affects the SQL statements executed by OpenJPA.
|
||||||
|
Available values are: 15, 20 and 21
|
||||||
|
- they indicate Firebird versions 1.5, 2.0 and 2.1 respectively.
|
||||||
|
If not set, the value will be auto-detected.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem id="FirebirdDictionary.IndexedVarcharMaxSizeFB15">
|
||||||
|
<para>
|
||||||
|
<indexterm>
|
||||||
|
<primary>
|
||||||
|
Firebird
|
||||||
|
</primary>
|
||||||
|
<secondary>
|
||||||
|
IndexedVarcharMaxSizeFB15
|
||||||
|
</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<literal>IndexedVarcharMaxSizeFB15</literal>: Firebird 1.5 imposes
|
||||||
|
tight limits on index size. In particular, an indexed
|
||||||
|
<literal>VARCHAR</literal> column size cannot exceed 252.
|
||||||
|
When <link linkend="ref_guide_mapping_mappingtool">schema is created</link>,
|
||||||
|
OpenJPA will use this property to reduce the size
|
||||||
|
of indexed <literal>VARCHAR</literal> columns.
|
||||||
|
Defaults to 252 but you might want to decrease this value if multi-column
|
||||||
|
indexes are used. If the Firebird version is 2.0 or later or
|
||||||
|
schema creation is not used, this property does not matter.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem id="FirebirdDictionary.RangeSyntax">
|
||||||
|
<para>
|
||||||
|
<indexterm>
|
||||||
|
<primary>
|
||||||
|
Firebird
|
||||||
|
</primary>
|
||||||
|
<secondary>
|
||||||
|
RangeSyntax
|
||||||
|
</secondary>
|
||||||
|
</indexterm>
|
||||||
|
<literal>RangeSyntax</literal>: Firebird 2.0 and later support two
|
||||||
|
ways of handling queries that select a range of data:
|
||||||
|
<literal>"FIRST <p> SKIP <q>"</literal> and
|
||||||
|
<literal>"ROWS <m> TO <n>"</literal>. Earlier versions support only
|
||||||
|
<literal>"FIRST <p> SKIP <q>"</literal> syntax.
|
||||||
|
This property determines the syntax to be used.
|
||||||
|
Available values are:
|
||||||
|
<literal>"firstskip"</literal> and <literal>"rows"</literal>.
|
||||||
|
Defaults to using <literal>"ROWS <m> TO <n>"</literal> if the
|
||||||
|
Firebird version is 2.0 or later, and
|
||||||
|
<literal>"FIRST <p> SKIP <q>"</literal> otherwise.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</section>
|
||||||
<section id="ref_guide_dbsetup_dbsupport_mysql">
|
<section id="ref_guide_dbsetup_dbsupport_mysql">
|
||||||
<title>
|
<title>
|
||||||
MySQLDictionary Properties
|
MySQLDictionary Properties
|
||||||
|
|
|
@ -126,13 +126,13 @@ by OpenJPA.
|
||||||
Firebird
|
Firebird
|
||||||
</entry>
|
</entry>
|
||||||
<entry colname="dbversion">
|
<entry colname="dbversion">
|
||||||
1.5
|
1.5, 2.0, 2.1
|
||||||
</entry>
|
</entry>
|
||||||
<entry colname="drivname">
|
<entry colname="drivname">
|
||||||
JayBird JCA/JDBC driver
|
JayBird JCA/JDBC driver
|
||||||
</entry>
|
</entry>
|
||||||
<entry colname="drivversion">
|
<entry colname="drivversion">
|
||||||
1.0.1
|
2.1.6
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
|
@ -553,7 +553,7 @@ will fail unless the <literal>SimulateLocking</literal> property is set for the
|
||||||
</title>
|
</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
openjpa.ConnectionDriverName: org.firebirdsql.jdbc.FBDriver
|
openjpa.ConnectionDriverName: org.firebirdsql.jdbc.FBDriver
|
||||||
openjpa.ConnectionURL: jdbc:firebirdsql://SERVER_NAME:SERVER_PORT/DB_PATH
|
openjpa.ConnectionURL: jdbc:firebirdsql:SERVER_NAME/3050:DB_PATH_OR_ALIAS
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</example>
|
</example>
|
||||||
<section id="dbsupport_firebird_issues">
|
<section id="dbsupport_firebird_issues">
|
||||||
|
@ -568,8 +568,13 @@ Firebird does not support auto-increment columns.
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Firebird does not support the <literal>LOWER</literal>, <literal>SUBSTRING
|
In order to use many of JPQL functions with Firebird 1.5, Interbase UDFs
|
||||||
</literal>, or <literal>INSTR</literal> SQL functions.
|
have to be available in the database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<literal>LOCATE</literal> JPQL function is not supported.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
Loading…
Reference in New Issue