| /* |
| * 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.calcite.sql.dialect; |
| |
| import org.apache.calcite.avatica.util.Casing; |
| import org.apache.calcite.avatica.util.TimeUnitRange; |
| import org.apache.calcite.rel.type.RelDataType; |
| import org.apache.calcite.rel.type.RelDataTypeSystem; |
| import org.apache.calcite.rel.type.RelDataTypeSystemImpl; |
| import org.apache.calcite.sql.SqlCall; |
| import org.apache.calcite.sql.SqlDataTypeSpec; |
| import org.apache.calcite.sql.SqlDialect; |
| import org.apache.calcite.sql.SqlLiteral; |
| import org.apache.calcite.sql.SqlNode; |
| import org.apache.calcite.sql.SqlUserDefinedTypeNameSpec; |
| import org.apache.calcite.sql.SqlWriter; |
| import org.apache.calcite.sql.fun.SqlFloorFunction; |
| import org.apache.calcite.sql.parser.SqlParserPos; |
| import org.apache.calcite.sql.type.SqlTypeName; |
| |
| /** |
| * A <code>SqlDialect</code> implementation for the PostgreSQL database. |
| */ |
| public class PostgresqlSqlDialect extends SqlDialect { |
| /** PostgreSQL type system. */ |
| private static final RelDataTypeSystem POSTGRESQL_TYPE_SYSTEM = |
| new RelDataTypeSystemImpl() { |
| @Override public int getMaxPrecision(SqlTypeName typeName) { |
| switch (typeName) { |
| case VARCHAR: |
| // From htup_details.h in postgresql: |
| // MaxAttrSize is a somewhat arbitrary upper limit on the declared size of |
| // data fields of char(n) and similar types. It need not have anything |
| // directly to do with the *actual* upper limit of varlena values, which |
| // is currently 1Gb (see TOAST structures in postgres.h). I've set it |
| // at 10Mb which seems like a reasonable number --- tgl 8/6/00. */ |
| return 10 * 1024 * 1024; |
| default: |
| return super.getMaxPrecision(typeName); |
| } |
| } |
| }; |
| |
| public static final SqlDialect.Context DEFAULT_CONTEXT = SqlDialect.EMPTY_CONTEXT |
| .withDatabaseProduct(SqlDialect.DatabaseProduct.POSTGRESQL) |
| .withIdentifierQuoteString("\"") |
| .withUnquotedCasing(Casing.TO_LOWER) |
| .withDataTypeSystem(POSTGRESQL_TYPE_SYSTEM); |
| |
| public static final SqlDialect DEFAULT = new PostgresqlSqlDialect(DEFAULT_CONTEXT); |
| |
| /** Creates a PostgresqlSqlDialect. */ |
| public PostgresqlSqlDialect(Context context) { |
| super(context); |
| } |
| |
| @Override public boolean supportsCharSet() { |
| return false; |
| } |
| |
| @Override public SqlNode getCastSpec(RelDataType type) { |
| String castSpec; |
| switch (type.getSqlTypeName()) { |
| case TINYINT: |
| // Postgres has no tinyint (1 byte), so instead cast to smallint (2 bytes) |
| castSpec = "_smallint"; |
| break; |
| case DOUBLE: |
| // Postgres has a double type but it is named differently |
| castSpec = "_double precision"; |
| break; |
| default: |
| return super.getCastSpec(type); |
| } |
| |
| return new SqlDataTypeSpec( |
| new SqlUserDefinedTypeNameSpec(castSpec, SqlParserPos.ZERO), |
| SqlParserPos.ZERO); |
| } |
| |
| @Override public boolean requiresAliasForFromItems() { |
| return true; |
| } |
| |
| @Override public boolean supportsNestedAggregations() { |
| return false; |
| } |
| |
| @Override public void unparseCall(SqlWriter writer, SqlCall call, |
| int leftPrec, int rightPrec) { |
| switch (call.getKind()) { |
| case FLOOR: |
| if (call.operandCount() != 2) { |
| super.unparseCall(writer, call, leftPrec, rightPrec); |
| return; |
| } |
| |
| final SqlLiteral timeUnitNode = call.operand(1); |
| final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); |
| |
| SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, timeUnit.name(), |
| timeUnitNode.getParserPosition()); |
| SqlFloorFunction.unparseDatetimeFunction(writer, call2, "DATE_TRUNC", false); |
| break; |
| |
| default: |
| super.unparseCall(writer, call, leftPrec, rightPrec); |
| } |
| } |
| } |
| |
| // End PostgresqlSqlDialect.java |