/** * 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.metamodel.jdbc.dialects; import static org.apache.metamodel.jdbc.JdbcDataContext.DATABASE_PRODUCT_ORACLE; import org.apache.metamodel.jdbc.JdbcDataContext; import org.apache.metamodel.query.FilterItem; import org.apache.metamodel.schema.ColumnType; /** * Query rewriter for Oracle */ public class OracleQueryRewriter extends OffsetFetchQueryRewriter { public static final int FIRST_FETCH_SUPPORTING_VERSION = 12; public OracleQueryRewriter(JdbcDataContext dataContext) { super(dataContext, FIRST_FETCH_SUPPORTING_VERSION); } @Override public String rewriteColumnType(ColumnType columnType, Integer columnSize) { if (columnType == ColumnType.NUMBER || columnType == ColumnType.NUMERIC || columnType == ColumnType.DECIMAL) { // as one of the only relational databases out there, Oracle has a // NUMBER type. For this reason NUMBER would be replaced by the // super-type's logic, but we handle it specifically here. super.rewriteColumnTypeInternal("NUMBER", columnSize); } if (columnType == ColumnType.BOOLEAN || columnType == ColumnType.BIT) { // Oracle has no boolean type, but recommends NUMBER(3) or CHAR(1). // For consistency with most other databases who have either a // boolean or a bit, we use the number variant because it's return // values (0 or 1) can be converted the most easily back to a // boolean. return "NUMBER(3)"; } if (columnType == ColumnType.DOUBLE) { return "BINARY_DOUBLE"; } if (columnType == ColumnType.FLOAT) { return "BINARY_FLOAT"; } if (columnType == ColumnType.BINARY || columnType == ColumnType.VARBINARY) { return "RAW"; } // following conversions based on // http://docs.oracle.com/cd/B19306_01/gateways.102/b14270/apa.htm if (columnType == ColumnType.TINYINT) { return "NUMBER(3)"; } if (columnType == ColumnType.SMALLINT) { return "NUMBER(5)"; } if (columnType == ColumnType.INTEGER) { return "NUMBER(10)"; } if (columnType == ColumnType.BIGINT) { return "NUMBER(19)"; } // Oracle has no "time only" data type but 'date' also includes time if (columnType == ColumnType.TIME) { super.rewriteColumnType(ColumnType.DATE, columnSize); } return super.rewriteColumnType(columnType, columnSize); } @Override public String rewriteFilterItem(final FilterItem item) { if (item.getOperand() instanceof String && item.getOperand().equals("")) { // In Oracle empty strings are treated as null. Typical SQL constructs with an empty string do not work. return super.rewriteFilterItem(new FilterItem(item.getSelectItem(), item.getOperator(), null)); } else { return super.rewriteFilterItem(item); } } }