All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openjpa.jdbc.sql.DerbyDictionary Maven / Gradle / Ivy

There is a newer version: 4.0.0
Show newest version
/*
 * 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.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;

import javax.sql.DataSource;

import org.apache.openjpa.util.StoreException;

/**
 * Dictionary for Apache Derby (formerly Cloudscape).
 */
public class DerbyDictionary
    extends AbstractDB2Dictionary {

    /**
     * If true, we will shutdown the embedded database when closing
     * the DataSource.
     */
    public boolean shutdownOnClose = true;
    
    public DerbyDictionary() {
        platform = "Apache Derby";
        validationSQL = "VALUES(1)";
        stringLengthFunction = "LENGTH({0})";
        substringFunctionName = "SUBSTR";
        toUpperCaseFunction = "UPPER(CAST({0} AS VARCHAR(" + varcharCastLength + ")))";
        toLowerCaseFunction = "LOWER(CAST({0} AS VARCHAR(" + varcharCastLength + ")))";

        // Derby name length restriction has been relaxed 
        //http://www.archivum.info/[email protected]/2004-12/msg00270.html
        maxConstraintNameLength = 128;
        maxIndexNameLength = 128;
        maxColumnNameLength = 128;
        maxTableNameLength = 128;

        useGetBytesForBlobs = true;
        useSetBytesForBlobs = true;

        allowsAliasInBulkClause = false;
        supportsDeferredConstraints = false;
        supportsParameterInSelect = false;
        supportsSelectForUpdate = true;
        supportsDefaultDeleteAction = false;
        requiresCastForMathFunctions = true;
        requiresCastForComparisons = true;
        supportsSimpleCaseExpression = false;
        supportsNullUniqueColumn = false;
        
        supportsComments = true;

        fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
            "BIGINT", "INTEGER", "TEXT"
        }));
        reservedWordSet.addAll(Arrays.asList(new String[]{
            "BOOLEAN", "CALL", "ENDEXEC", "EXPLAIN", "FUNCTION",
            "GET_CURRENT_CONNECTION", "INOUT", "LONGINT", "LTRIM", "NONE",
            "NVARCHAR", "OFF", "OUT", "RTRIM", "SUBSTR", "XML", "XMLEXISTS",
            "XMLPARSE", "XMLSERIALIZE",
        }));

        // reservedWordSet subset that CANNOT be used as valid column names
        // (i.e., without surrounding them with double-quotes)
        invalidColumnWordSet.addAll(Arrays.asList(new String[] {
            "ADD", "ALL", "ALLOCATE", "ALTER", "AND", "ANY", "ARE", "AS", "ASC",
            "ASSERTION", "AT", "AUTHORIZATION", "AVG", "BEGIN", "BETWEEN", 
            "BIT", "BOOLEAN", "BOTH", "BY", "CALL", "CASCADE", "CASCADED", 
            "CASE", "CAST", "CHAR", "CHARACTER", "CHARACTER_LENGTH", "CHECK",
            "CLOSE", "COALESCE", "COLLATE", "COLLATION", "COLUMN", "COMMIT", "CONNECT",
            "CONNECTION", "CONSTRAINT", "CONSTRAINTS", "CONTINUE", "CONVERT",
            "CORRESPONDING", "CREATE", "CURRENT", "CURRENT_DATE", "CURRENT_ROLE",
            "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR",
            "DEALLOCATE", "DEC", "DECIMAL", "DECLARE", "DEFAULT", "DEFERRABLE",
            "DEFERRED", "DELETE", "DESC", "DESCRIBE", "DIAGNOSTICS", 
            "DISCONNECT", "DISTINCT", "DOUBLE", "DROP", "ELSE", "END", 
            "END-EXEC", "ESCAPE", "EXCEPT", "EXCEPTION", "EXEC", "EXECUTE",
            "EXISTS", "EXPLAIN", "EXTERNAL", "FALSE", "FETCH", "FIRST", "FLOAT",
            "FOR", "FOREIGN", "FOUND", "FROM", "FULL", "FUNCTION", "GET", 
            "GETCURRENTCONNECTION", "GLOBAL", "GO", "GOTO", "GRANT", "GROUP", "HAVING", "HOUR",
            "IDENTITY", "IMMEDIATE", "IN", "INDICATOR", "INITIALLY", "INNER",
            "INOUT", "INPUT", "INSENSITIVE", "INSERT", "INT", "INTEGER",
            "INTERSECT", "INTO", "IS", "ISOLATION", "JOIN", "KEY", "LAST",
            "LEADING", "LEFT", "LIKE", "LOWER", "LTRIM", "MATCH", "MAX", "MIN",
            "MINUTE", "NATIONAL", "NATURAL", "NCHAR", "NEXT", "NO", "NONE", "NOT", 
            "NULL", "NULLIF", "NUMERIC", "NVARCHAR", "OF", "ON", "ONLY", "OPEN",
            "OPTION", "OR", "ORDER", "OUT", "OUTER", "OUTPUT", "OVER", "OVERLAPS", 
            "PAD", "PARTIAL", "PREPARE", "PRESERVE", "PRIMARY", "PRIOR",
            "PRIVILEGES", "PROCEDURE", "PUBLIC", "READ", "REAL", "REFERENCES",
            "RELATIVE", "RESTRICT", "REVOKE", "RIGHT", "ROLLBACK", "ROWS",
            "ROW_NUMBER", "RTRIM", "SCHEMA", "SCROLL", "SECOND", "SELECT", "SESSION_USER",
            "SET", "SMALLINT", "SOME", "SPACE", "SQL", "SQLCODE", "SQLERROR",
            "SQLSTATE", "SUBSTR", "SUBSTRING", "SUM", "SYSTEM_USER", "TABLE",
            "TEMPORARY", "TIMEZONE_HOUR", "TIMEZONE_MINUTE", "TO", "TRAILING",
            "TRANSACTION", "TRANSLATE", "TRANSLATION", "TRIM", "TRUE", "UNION",
            "UNIQUE", "UNKNOWN", "UPDATE", "UPPER", "USER", "USING", "VALUES",
            "VARCHAR", "VARYING", "VIEW", "WHENEVER", "WHERE", "WITH", "WORK",
            "WRITE", "XML", "XMLEXISTS", "XMLPARSE", "XMLQUERY", "XMLSERIALIZE", "YEAR",
        }));
    }
    
    @Override
    public void connectedConfiguration(Connection conn) throws SQLException {
    	super.connectedConfiguration(conn);
    	if (versionEqualOrLaterThan(10, 5)) {
    		supportsSelectStartIndex = true;
    		supportsSelectEndIndex   = true;
    	}
    }

    /**
     * Appends a range to the given buffer.
     * 
* A range query is never appended to a subselct clause. *
* If this dictionary supports {@link DBDictionary#supportsSelectStartIndex offset} * and {@link DBDictionary#supportsSelectEndIndex limit} on queries then the * syntax is
     * [ OFFSET {start} ROWS ]
	 * [ FETCH NEXT {end-start} ROWS ONLY ]
     * 
* Otherwise, the offset is not used and the syntax is
     * [ FETCH FIRST {end} ROWS ONLY ]
     * 
* @param buf the SQL buffer to be appended * @param start starting offset. {@code 0} means offset is not used. * @param end number of rows to be fetched. {@code Long.MAX_VALUE} means no limit. * @param subselect flags if the buffer represents a SQL Subquery clause */ protected void appendSelectRange(SQLBuffer buf, long start, long end, boolean subselect) { // do not generate FETCH FIRST clause for subselect if (subselect) return; if (supportsSelectStartIndex && supportsSelectEndIndex) { if (isUsingOffset(start)) buf.append(" OFFSET ").append(Long.toString(start)).append(" ROWS "); if (isUsingLimit(end)) { long rowCount = end - start; buf.append(" FETCH NEXT ").append(Long.toString(rowCount)).append(" ROWS ONLY"); } } else if (isUsingLimit(end)) { buf.append(" FETCH FIRST ").append(Long.toString(end)).append(" ROWS ONLY"); } } public void closeDataSource(DataSource dataSource) { super.closeDataSource(dataSource); if (!shutdownOnClose) return; // as well as closing the DataSource, we also need to // shut down the instance if we are using an embedded database, which // can only be done by connecting to the same URL with the // ";shutdown=true" string appended to the end // see: http://db.apache.org/derby/docs/dev/devguide/tdevdvlp40464.html if (conf != null && conf.getConnectionDriverName() != null && conf.getConnectionDriverName().indexOf("EmbeddedDriver") != -1) { try { DriverManager.getConnection(conf.getConnectionURL() + ";shutdown=true"); } catch (SQLException e) { // we actually expect a SQLException to be thrown here: // Derby strangely uses that as a mechanism to report // a successful shutdown } } } @Override public boolean isFatalException(int subtype, SQLException ex) { int errorCode = ex.getErrorCode(); if ((subtype == StoreException.LOCK || subtype == StoreException.QUERY) && errorCode <= 30000) { return false; } return super.isFatalException(subtype, ex); } /** * Applies range calculation on the actual number of rows selected by a * {@code COUNT(*)} query. A range query may use either only the limit or * both offset and limit based on database dictionary support and * accordingly the number of rows in the result set needs to be modified. * * @param select * @param count * @return */ public int applyRange(Select select, int count) { long start = select.getStartIndex(); long end = select.getEndIndex(); if (supportsSelectStartIndex) { if (start > 0) count -= start; if (end != Long.MAX_VALUE) { long size = end - start; count = (int) Math.min(count, size); } } return count; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy