001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2011-2013 Pentaho and others
008// All Rights Reserved.
009*/
010package mondrian.spi.impl;
011
012import mondrian.olap.Util;
013
014import java.sql.*;
015import java.sql.Date;
016import java.util.*;
017
018/**
019 * Implementation of {@link mondrian.spi.Dialect} for the Hive database.
020 *
021 * @author Hongwei Fu
022 * @since Jan 10, 2011
023 */
024public class HiveDialect extends JdbcDialectImpl {
025    private static final int MAX_COLUMN_NAME_LENGTH = 128;
026
027    public static final JdbcDialectFactory FACTORY =
028        new JdbcDialectFactory(
029            HiveDialect.class,
030            DatabaseProduct.HIVE)
031        {
032            protected boolean acceptsConnection(Connection connection) {
033                return super.acceptsConnection(connection)
034                    && !isDatabase(DatabaseProduct.IMPALA, connection);
035            }
036        };
037
038    /**
039     * Creates a HiveDialect.
040     *
041     * @param connection Connection
042     *
043     * @throws SQLException on error
044     */
045    public HiveDialect(Connection connection) throws SQLException {
046        super(connection);
047    }
048
049    protected String deduceIdentifierQuoteString(
050        DatabaseMetaData databaseMetaData)
051    {
052        try {
053            final String quoteIdentifierString =
054                databaseMetaData.getIdentifierQuoteString();
055            return "".equals(quoteIdentifierString)
056                // quoting not supported
057                ? null
058                : quoteIdentifierString;
059        } catch (SQLException e) {
060            // Not supported by HiveDatabaseMetaData; do nothing if catch an
061            // Exception
062            return "`";
063        }
064    }
065
066    protected Set<List<Integer>> deduceSupportedResultSetStyles(
067        DatabaseMetaData databaseMetaData)
068    {
069        // Hive don't support this, so just return an empty set.
070        return Collections.emptySet();
071    }
072
073    protected boolean deduceReadOnly(DatabaseMetaData databaseMetaData) {
074        try {
075            return databaseMetaData.isReadOnly();
076        } catch (SQLException e) {
077            // Hive is read only (as of release 0.7)
078            return true;
079        }
080    }
081
082    protected int deduceMaxColumnNameLength(DatabaseMetaData databaseMetaData) {
083        try {
084            return databaseMetaData.getMaxColumnNameLength();
085        } catch (SQLException e) {
086            return MAX_COLUMN_NAME_LENGTH;
087        }
088    }
089
090    public boolean allowsCompoundCountDistinct() {
091        return true;
092    }
093
094    public boolean requiresAliasForFromQuery() {
095        return true;
096    }
097
098    public boolean requiresOrderByAlias() {
099        return true;
100    }
101
102    public boolean requiresUnionOrderByExprToBeInSelectClause() {
103        return false;
104    }
105
106    public String generateInline(
107        List<String> columnNames,
108        List<String> columnTypes,
109        List<String[]> valueList)
110    {
111        return "select * from ("
112            + generateInlineGeneric(
113                columnNames, columnTypes, valueList, " from dual", false)
114            + ") x limit " + valueList.size();
115    }
116
117    protected void quoteDateLiteral(
118        StringBuilder buf,
119        String value,
120        Date date)
121    {
122        // Hive doesn't support Date type; treat date as a string '2008-01-23'
123        Util.singleQuoteString(value, buf);
124    }
125
126    @Override
127    protected String generateOrderByNulls(
128        String expr,
129        boolean ascending,
130        boolean collateNullsLast)
131    {
132        // In Hive, Null values are worth negative infinity.
133        if (collateNullsLast) {
134            if (ascending) {
135                return "ISNULL(" + expr + ") ASC, " + expr + " ASC";
136            } else {
137                return expr + " DESC";
138            }
139        } else {
140            if (ascending) {
141                return expr + " ASC";
142            } else {
143                return "ISNULL(" + expr + ") DESC, " + expr + " DESC";
144            }
145        }
146    }
147
148    public boolean allowsAs() {
149        return false;
150    }
151
152    public boolean allowsJoinOn() {
153        return false;
154    }
155}
156
157// End HiveDialect.java