blob: 0fe77a910142e51fd20b5c2bee06c7a7b22d423a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.jdbc.sql;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.PrimaryKey;
/**
* Dictionary for Visual FoxPro via DataDirect SequeLink
* and DataDirect ODBC FoxPro driver. This will not
* work with any other combination of JDBC/ODBC server and ODBC driver.
* FoxPro has the following limitations:
* <ul>
* <li>Primary Keys and indexes cannot be created via JDBC</li>
* <li>Only has fixed-length char fields: all strings must be
* trimmed in result sets</li>
* <li>Does not have sufficient support for foreign keys</li>
* <li>ODBC driver cannot handle certain Aggregate functions.</li>
* <li>Locking is extremeley unreliable. Multiple clients
* accessing single datastore may result in concurrency
* data validity errors.</li>
* </ul>
*/
public class FoxProDictionary
extends DBDictionary {
public FoxProDictionary() {
platform = "Visual FoxPro";
joinSyntax = SYNTAX_TRADITIONAL;
supportsForeignKeys = false;
supportsDeferredConstraints = false;
maxTableNameLength = 30;
maxColumnNameLength = 30;
maxIndexNameLength = 8;
maxConstraintNameLength = 8;
binaryTypeName = "GENERAL";
blobTypeName = "GENERAL";
longVarbinaryTypeName = "GENERAL";
clobTypeName = "MEMO";
longVarcharTypeName = "MEMO";
dateTypeName = "TIMESTAMP";
timeTypeName = "TIMESTAMP";
varcharTypeName = "CHARACTER{0}";
bigintTypeName = "DOUBLE";
numericTypeName = "INTEGER";
smallintTypeName = "INTEGER";
bitTypeName = "NUMERIC(1)";
integerTypeName = "INTEGER";
tinyintTypeName = "INTEGER";
decimalTypeName = "DOUBLE";
doubleTypeName = "DOUBLE";
realTypeName = "DOUBLE";
floatTypeName = "NUMERIC(19,16)";
// the max character literal length is actually 254, but for primary
// keys, it is 240; default to that length so users can add PKs later
characterColumnSize = 240;
// OpenJPA-2045: NAME has been removed from common reserved words to
// only specific dictionaries
reservedWordSet.add("NAME");
}
@Override
public String getString(ResultSet rs, int column)
throws SQLException {
// foxpro doesn't auto-truncate values.
String str = rs.getString(column);
if (str != null)
str = str.trim();
return str;
}
@Override
public void setNull(PreparedStatement stmnt, int idx, int colType,
Column col)
throws SQLException {
// ensure that blob/clob is handled with safe methods.
switch (colType) {
case Types.BLOB:
stmnt.setBytes(idx, null);
break;
case Types.CLOB:
stmnt.setString(idx, null);
break;
default:
super.setNull(stmnt, idx, colType, col);
}
}
@Override
protected String appendSize(Column col, String typeName) {
// foxpro does not like unsized column declarations.
if (col.getSize() == 0) {
if ("CHARACTER".equals(typeName))
col.setSize(240);
else if ("NUMERIC".equals(typeName))
col.setSize(19);
}
return super.appendSize(col, typeName);
}
@Override
protected String getPrimaryKeyConstraintSQL(PrimaryKey pk) {
// this foxpro driver combination does not support primary keys
return null;
}
@Override
public String[] getCreateIndexSQL(Index index) {
// foxpro JDBC access does not allow the creation of indexes
return new String[0];
}
@Override
public Column[] getColumns(DatabaseMetaData meta, String catalog,
String schemaName, String tableName, String columnName, Connection conn)
throws SQLException {
return getColumns(meta, DBIdentifier.newCatalog(catalog), DBIdentifier.newSchema(schemaName),
DBIdentifier.newTable(tableName), DBIdentifier.newColumn(columnName), conn);
}
@Override
public Column[] getColumns(DatabaseMetaData meta, DBIdentifier catalog,
DBIdentifier schemaName, DBIdentifier tableName, DBIdentifier columnName, Connection conn)
throws SQLException {
try {
Column[] cols = super.getColumns(meta, catalog, schemaName,
tableName, columnName, conn);
for (int i = 0; cols != null && i < cols.length; i++) {
// foxpro returns an odd type "11" code for DATETIME fields
if (cols[i].getType() == 11)
cols[i].setType(Types.TIMESTAMP);
// MEMO maps to LONGVARCHAR during reverse analysis
else if ("MEMO".equals(cols[i].getTypeIdentifier().getName()))
cols[i].setType(Types.CLOB);
}
return cols;
} catch (SQLException se) {
// foxpro throws an exception if the table specified in the
// column list is not found
if (se.getErrorCode() == 562)
return null;
throw se;
}
}
@Override
public PrimaryKey[] getPrimaryKeys(DatabaseMetaData meta, String catalog,
String schemaName, String tableName, Connection conn)
throws SQLException {
// this combination does not reliably return PK information
return null;
}
@Override
public PrimaryKey[] getPrimaryKeys(DatabaseMetaData meta, DBIdentifier catalog,
DBIdentifier schemaName, DBIdentifier tableName, Connection conn)
throws SQLException {
// this combination does not reliably return PK information
return null;
}
}