| /* |
| * 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; |
| } |
| } |