http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetCachedStmt.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetCachedStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetCachedStmt.java deleted file mode 100644 index f63cf3e..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetCachedStmt.java +++ /dev/null @@ -1,92 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import com.cloudera.impala.catalog.HdfsTable; -import com.cloudera.impala.catalog.HdfsPartition; -import com.cloudera.impala.catalog.Table; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.thrift.TAlterTableParams; -import com.cloudera.impala.thrift.TAlterTableSetCachedParams; -import com.cloudera.impala.thrift.TAlterTableType; -import com.google.common.base.Preconditions; - -/** - * Represents an ALTER TABLE [PARTITION partitionSpec] SET [UNCACHED|CACHED 'pool']. - */ -public class AlterTableSetCachedStmt extends AlterTableSetStmt { - private final HdfsCachingOp cacheOp_; - - public AlterTableSetCachedStmt(TableName tableName, - PartitionSpec partitionSpec, HdfsCachingOp cacheOp) { - super(tableName, partitionSpec); - Preconditions.checkNotNull(cacheOp); - cacheOp_ = cacheOp; - } - - @Override - public TAlterTableParams toThrift() { - TAlterTableParams params = super.toThrift(); - params.setAlter_type(TAlterTableType.SET_CACHED); - TAlterTableSetCachedParams cachingParams = - new TAlterTableSetCachedParams(); - if (getPartitionSpec() != null) { - cachingParams.setPartition_spec(getPartitionSpec().toThrift()); - } - cachingParams.setCache_op(cacheOp_.toThrift()); - params.setSet_cached_params(cachingParams); - return params; - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - super.analyze(analyzer); - cacheOp_.analyze(analyzer); - - Table table = getTargetTable(); - Preconditions.checkNotNull(table); - if (!(table instanceof HdfsTable)) { - throw new AnalysisException("ALTER TABLE SET [CACHED|UNCACHED] must target an " + - "HDFS table: " + table.getFullName()); - } - - if (cacheOp_.shouldCache()) { - boolean isCacheable; - PartitionSpec partSpec = getPartitionSpec(); - HdfsTable hdfsTable = (HdfsTable)table; - StringBuilder nameSb = new StringBuilder(); - if (partSpec != null) { - HdfsPartition part = hdfsTable.getPartition(partSpec.getPartitionSpecKeyValues()); - if (part == null) { - throw new AnalysisException("Partition spec does not exist: " + - partSpec.toSql()); - } - isCacheable = part.isCacheable(); - nameSb.append("Partition (" + part.getPartitionName() + ")"); - } else { - isCacheable = hdfsTable.isCacheable(); - nameSb.append("Table ").append(table.getFullName()); - } - if (!isCacheable) { - throw new AnalysisException(nameSb.toString() + " cannot be cached. Please " + - "check if the table or partitions are on a filesystem which supports " + - "caching."); - } - } - } -}
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetColumnStats.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetColumnStats.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetColumnStats.java deleted file mode 100644 index e9c9a14..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetColumnStats.java +++ /dev/null @@ -1,158 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import java.util.HashMap; -import java.util.Map; - -import com.cloudera.impala.catalog.Column; -import com.cloudera.impala.catalog.ColumnStats; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.thrift.TAlterTableParams; -import com.cloudera.impala.thrift.TAlterTableType; -import com.cloudera.impala.thrift.TAlterTableUpdateStatsParams; -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; - -/** -* Represents an ALTER TABLE [<dbName>.]<tableName> SET COLUMN STATS <colName> -* ('statsKey'='val','statsKey2',='val2') statement. -* -* The keys as well as the values are specified as string literals to be consistent -* with the existing DDL for setting TBLPROPERTIES/SERDEPROPERTIES, in particular, -* setting the 'numRows' table/partition property. -* -* Stats key comparisons are case-insensitive. -*/ -public class AlterTableSetColumnStats extends AlterTableStmt { - private final String colName_; - private final HashMap<String, String> statsMap_; - - // Complete column stats reflecting this alteration. Existing stats values - // are preserved. Result of analysis. - private ColumnStats colStats_; - - public AlterTableSetColumnStats(TableName tableName, String colName, - HashMap<String, String> statsMap) { - super(tableName); - colName_ = colName; - statsMap_ = statsMap; - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - super.analyze(analyzer); - - Column col = getTargetTable().getColumn(colName_); - if (col == null) { - throw new AnalysisException( - String.format("Column '%s' does not exist in table: %s", - colName_, getTargetTable().getFullName())); - } - // Cannot update stats on partition columns because the HMS has no entries - // for them, and the stats can be computed directly from the metadata. - if (col.getPosition() < getTargetTable().getNumClusteringCols()) { - throw new AnalysisException( - "Updating the stats of a partition column is not allowed: " + colName_); - } - // Cannot update the stats if they are not supported for the column's type. - if (!ColumnStats.isSupportedColType(col.getType())) { - throw new AnalysisException(String.format( - "Statistics for column '%s' are not supported because " + - "it has type '%s'.", col.getName(), col.getType().toSql())); - } - - // Copy the existing stats and then change the values according to the - // stats map of this stmt. The existing stats are first copied to preserve - // those stats values that are not changed by this stmt because all stats - // values are updated when altering the stats in the HMS. - colStats_ = col.getStats().clone(); - for (Map.Entry<String, String> entry: statsMap_.entrySet()) { - ColumnStats.StatsKey statsKey = ColumnStats.StatsKey.fromString(entry.getKey()); - if (statsKey == null) { - throw new AnalysisException(String.format( - "Invalid column stats key: %s\nValid keys are: %s", - entry.getKey(), Joiner.on(',').join(ColumnStats.StatsKey.values()))); - } - setStatsValue(statsKey, entry.getValue(), col, colStats_); - } - } - - /** - * Updates the given column stats based on statsKey and statsValue. - * Throws an AnalysisException if the statsValue is invalid or not applicable to the - * column (e.g., trying to update the avg/max size of a fixed-length column). - */ - private void setStatsValue(ColumnStats.StatsKey statsKey, String statsValue, - Column col, ColumnStats stats) throws AnalysisException { - // Updating max/avg size is only allowed for variable length columns. - if (col.getType().isFixedLengthType() - && (statsKey == ColumnStats.StatsKey.AVG_SIZE - || statsKey == ColumnStats.StatsKey.MAX_SIZE)) { - throw new AnalysisException(String.format( - "Cannot update the '%s' stats of column '%s' with type '%s'.\n" + - "Changing '%s' is only allowed for variable-length columns.", - statsKey, col.getName(), col.getType().toSql(), statsKey)); - } - - if (statsKey == ColumnStats.StatsKey.NUM_DISTINCT_VALUES || - statsKey == ColumnStats.StatsKey.NUM_NULLS || - statsKey == ColumnStats.StatsKey.MAX_SIZE) { - Long statsVal = null; - try { - statsVal = Long.parseLong(statsValue); - } catch (Exception e) { - } - if (statsVal == null || statsVal < -1) { - throw new AnalysisException(String.format( - "Invalid stats value '%s' for column stats key: %s\n" + - "Expected a positive integer or -1 for unknown.", - statsValue, statsKey)); - } - stats.update(statsKey, statsVal); - } else if (statsKey == ColumnStats.StatsKey.AVG_SIZE) { - Float statsVal = null; - try { - statsVal = Float.parseFloat(statsValue); - } catch (Exception e) { - } - if (statsVal == null || (statsVal < 0 && statsVal != -1) || - statsVal.isNaN() || statsVal.isInfinite()) { - throw new AnalysisException(String.format( - "Invalid stats value '%s' for column stats key: %s\n" + - "Expected a positive floating-point number or -1 for unknown.", - statsValue, statsKey)); - } - stats.update(statsKey, statsVal); - } else { - Preconditions.checkState(false, "Unhandled StatsKey value: " + statsKey); - } - } - - @Override - public TAlterTableParams toThrift() { - TAlterTableParams params = super.toThrift(); - params.setAlter_type(TAlterTableType.UPDATE_STATS); - TAlterTableUpdateStatsParams updateStatsParams = - new TAlterTableUpdateStatsParams(); - updateStatsParams.setTable_name(getTargetTable().getTableName().toThrift()); - updateStatsParams.putToColumn_stats(colName_.toString(), colStats_.toThrift()); - params.setUpdate_stats_params(updateStatsParams); - return params; - } -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetFileFormatStmt.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetFileFormatStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetFileFormatStmt.java deleted file mode 100644 index 7e18aa6..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetFileFormatStmt.java +++ /dev/null @@ -1,57 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.thrift.TAlterTableParams; -import com.cloudera.impala.thrift.TAlterTableSetFileFormatParams; -import com.cloudera.impala.thrift.TAlterTableType; -import com.cloudera.impala.thrift.THdfsFileFormat; - -/** - * Represents an ALTER TABLE [PARTITION partitionSpec] SET FILEFORMAT statement. - */ -public class AlterTableSetFileFormatStmt extends AlterTableSetStmt { - private final THdfsFileFormat fileFormat_; - - public AlterTableSetFileFormatStmt(TableName tableName, - PartitionSpec partitionSpec, THdfsFileFormat fileFormat) { - super(tableName, partitionSpec); - this.fileFormat_ = fileFormat; - } - - public THdfsFileFormat getFileFormat() { return fileFormat_; } - - @Override - public TAlterTableParams toThrift() { - TAlterTableParams params = super.toThrift(); - params.setAlter_type(TAlterTableType.SET_FILE_FORMAT); - TAlterTableSetFileFormatParams fileFormatParams = - new TAlterTableSetFileFormatParams(fileFormat_); - if (getPartitionSpec() != null) { - fileFormatParams.setPartition_spec(getPartitionSpec().toThrift()); - } - params.setSet_file_format_params(fileFormatParams); - return params; - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - super.analyze(analyzer); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetLocationStmt.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetLocationStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetLocationStmt.java deleted file mode 100644 index fcc9b53..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetLocationStmt.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import com.cloudera.impala.authorization.Privilege; -import com.cloudera.impala.catalog.HdfsPartition; -import com.cloudera.impala.catalog.HdfsTable; -import com.cloudera.impala.catalog.Table; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.thrift.TAlterTableParams; -import com.cloudera.impala.thrift.TAlterTableSetLocationParams; -import com.cloudera.impala.thrift.TAlterTableType; -import com.google.common.base.Preconditions; -import org.apache.hadoop.fs.permission.FsAction; - -/** - * Represents an ALTER TABLE [PARTITION partitionSpec] SET LOCATION statement. - */ -public class AlterTableSetLocationStmt extends AlterTableSetStmt { - private final HdfsUri location_; - - public AlterTableSetLocationStmt(TableName tableName, - PartitionSpec partitionSpec, HdfsUri location) { - super(tableName, partitionSpec); - Preconditions.checkNotNull(location); - this.location_ = location; - } - - public HdfsUri getLocation() { return location_; } - - @Override - public TAlterTableParams toThrift() { - TAlterTableParams params = super.toThrift(); - params.setAlter_type(TAlterTableType.SET_LOCATION); - TAlterTableSetLocationParams locationParams = - new TAlterTableSetLocationParams(location_.toString()); - if (getPartitionSpec() != null) { - locationParams.setPartition_spec(getPartitionSpec().toThrift()); - } - params.setSet_location_params(locationParams); - return params; - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - super.analyze(analyzer); - location_.analyze(analyzer, Privilege.ALL, FsAction.READ_WRITE); - - Table table = getTargetTable(); - Preconditions.checkNotNull(table); - if (table instanceof HdfsTable) { - HdfsTable hdfsTable = (HdfsTable) table; - if (getPartitionSpec() != null) { - // Targeting a partition rather than a table. - PartitionSpec partitionSpec = getPartitionSpec(); - HdfsPartition partition = hdfsTable.getPartition( - partitionSpec.getPartitionSpecKeyValues()); - Preconditions.checkNotNull(partition); - if (partition.isMarkedCached()) { - throw new AnalysisException(String.format("Target partition is cached, " + - "please uncache before changing the location using: ALTER TABLE %s %s " + - "SET UNCACHED", table.getFullName(), partitionSpec.toSql())); - } - } else if (hdfsTable.isMarkedCached()) { - throw new AnalysisException(String.format("Target table is cached, please " + - "uncache before changing the location using: ALTER TABLE %s SET UNCACHED", - table.getFullName())); - } - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetStmt.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetStmt.java deleted file mode 100644 index 2857211..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetStmt.java +++ /dev/null @@ -1,58 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import com.cloudera.impala.authorization.Privilege; -import com.cloudera.impala.catalog.HBaseTable; -import com.cloudera.impala.catalog.Table; -import com.cloudera.impala.common.AnalysisException; - -/** - * Base class for all ALTER TABLE ... SET statements - */ -public class AlterTableSetStmt extends AlterTableStmt { - protected final PartitionSpec partitionSpec_; - - public AlterTableSetStmt(TableName tableName, PartitionSpec partitionSpec) { - super(tableName); - partitionSpec_ = partitionSpec; - if (partitionSpec_ != null) partitionSpec_.setTableName(tableName); - } - - public PartitionSpec getPartitionSpec() { return partitionSpec_; } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - super.analyze(analyzer); - Table t = getTargetTable(); - // TODO: Support ALTER TABLE SET on HBase tables. Requires validating changes - // to the SERDEPROPERTIES and TBLPROPERTIES to ensure the table metadata does not - // become invalid. - if (t instanceof HBaseTable) { - throw new AnalysisException("ALTER TABLE SET not currently supported on " + - "HBase tables."); - } - - // Altering the table rather than the partition. - if (partitionSpec_ == null) return; - - partitionSpec_.setPartitionShouldExist(); - partitionSpec_.setPrivilegeRequirement(Privilege.ALTER); - partitionSpec_.analyze(analyzer); - } -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetTblProperties.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetTblProperties.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetTblProperties.java deleted file mode 100644 index da92267..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableSetTblProperties.java +++ /dev/null @@ -1,150 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.avro.SchemaParseException; -import org.apache.hadoop.hive.serde2.avro.AvroSerdeUtils; - -import com.cloudera.impala.catalog.HdfsFileFormat; -import com.cloudera.impala.catalog.HdfsTable; -import com.cloudera.impala.catalog.Table; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.thrift.*; -import com.cloudera.impala.util.AvroSchemaParser; -import com.cloudera.impala.util.AvroSchemaUtils; -import com.cloudera.impala.util.MetaStoreUtil; - -import com.google.common.base.Preconditions; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; - -/** -* Represents an ALTER TABLE SET [PARTITION ('k1'='a', 'k2'='b'...)] -* TBLPROPERTIES|SERDEPROPERTIES ('p1'='v1', ...) statement. -*/ -public class AlterTableSetTblProperties extends AlterTableSetStmt { - private final TTablePropertyType targetProperty_; - private final HashMap<String, String> tblProperties_; - - public AlterTableSetTblProperties(TableName tableName, PartitionSpec partitionSpec, - TTablePropertyType targetProperty, HashMap<String, String> tblProperties) { - super(tableName, partitionSpec); - Preconditions.checkNotNull(tblProperties); - Preconditions.checkNotNull(targetProperty); - targetProperty_ = targetProperty; - tblProperties_ = tblProperties; - CreateTableStmt.unescapeProperties(tblProperties_); - } - - public HashMap<String, String> getTblProperties() { return tblProperties_; } - - @Override - public TAlterTableParams toThrift() { - TAlterTableParams params = super.toThrift(); - params.setAlter_type(TAlterTableType.SET_TBL_PROPERTIES); - TAlterTableSetTblPropertiesParams tblPropertyParams = - new TAlterTableSetTblPropertiesParams(); - tblPropertyParams.setTarget(targetProperty_); - tblPropertyParams.setProperties(tblProperties_); - if (partitionSpec_ != null) { - tblPropertyParams.setPartition_spec(partitionSpec_.toThrift()); - } - params.setSet_tbl_properties_params(tblPropertyParams); - return params; - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - super.analyze(analyzer); - - MetaStoreUtil.checkShortPropertyMap("Property", tblProperties_); - - // Check avro schema when it is set in avro.schema.url or avro.schema.literal to - // avoid potential metadata corruption (see IMPALA-2042). - // If both properties are set then only check avro.schema.literal and ignore - // avro.schema.url. - if (tblProperties_.containsKey( - AvroSerdeUtils.AvroTableProperties.SCHEMA_LITERAL.getPropName()) || - tblProperties_.containsKey( - AvroSerdeUtils.AvroTableProperties.SCHEMA_URL.getPropName())) { - analyzeAvroSchema(analyzer); - } - - // Analyze 'skip.header.line.format' property. - analyzeSkipHeaderLineCount(getTargetTable(), tblProperties_); - } - - /** - * Check that Avro schema provided in avro.schema.url or avro.schema.literal is valid - * Json and contains only supported Impala types. If both properties are set, then - * avro.schema.url is ignored. - */ - private void analyzeAvroSchema(Analyzer analyzer) - throws AnalysisException { - List<Map<String, String>> schemaSearchLocations = Lists.newArrayList(); - schemaSearchLocations.add(tblProperties_); - - String avroSchema = AvroSchemaUtils.getAvroSchema(schemaSearchLocations); - avroSchema = Strings.nullToEmpty(avroSchema); - if (avroSchema.isEmpty()) { - throw new AnalysisException("Avro schema is null or empty: " + - table_.getFullName()); - } - - // Check if the schema is valid and is supported by Impala - try { - AvroSchemaParser.parse(avroSchema); - } catch (SchemaParseException e) { - throw new AnalysisException(String.format( - "Error parsing Avro schema for table '%s': %s", table_.getFullName(), - e.getMessage())); - } - } - - /** - * Analyze the 'skip.header.line.count' property to make sure it is set to a valid - * value. It is looked up in 'tblProperties', which must not be null. - */ - public static void analyzeSkipHeaderLineCount(Map<String, String> tblProperties) - throws AnalysisException { - analyzeSkipHeaderLineCount(null, tblProperties); - } - - /** - * Analyze the 'skip.header.line.count' property to make sure it is set to a valid - * value. It is looked up in 'tblProperties', which must not be null. If 'table' is not - * null, then the method ensures that 'skip.header.line.count' is supported for its - * table type. If it is null, then this check is omitted. - */ - public static void analyzeSkipHeaderLineCount(Table table, - Map<String, String> tblProperties) throws AnalysisException { - if (tblProperties.containsKey(HdfsTable.TBL_PROP_SKIP_HEADER_LINE_COUNT)) { - if (table != null && !(table instanceof HdfsTable)) { - throw new AnalysisException(String.format("Table property " + - "'skip.header.line.count' is only supported for HDFS tables.")); - } - StringBuilder error = new StringBuilder(); - HdfsTable.parseSkipHeaderLineCount(tblProperties, error); - if (error.length() > 0) throw new AnalysisException(error.toString()); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterTableStmt.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterTableStmt.java deleted file mode 100644 index aebd009..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterTableStmt.java +++ /dev/null @@ -1,91 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import com.cloudera.impala.authorization.Privilege; -import com.cloudera.impala.catalog.DataSourceTable; -import com.cloudera.impala.catalog.KuduTable; -import com.cloudera.impala.catalog.Table; -import com.cloudera.impala.catalog.View; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.thrift.TAlterTableParams; -import com.cloudera.impala.thrift.TTableName; -import com.google.common.base.Preconditions; - -/** - * Base class for all ALTER TABLE statements. - */ -public abstract class AlterTableStmt extends StatementBase { - protected final TableName tableName_; - - // Set during analysis. - protected Table table_; - - protected AlterTableStmt(TableName tableName) { - Preconditions.checkState(tableName != null && !tableName.isEmpty()); - tableName_ = tableName; - table_ = null; - } - - public String getTbl() { return tableName_.getTbl(); } - - /** - * Can only be called after analysis, returns the parent database name of the target - * table for this ALTER TABLE statement. - */ - public String getDb() { - return getTargetTable().getDb().getName(); - } - - /** - * Can only be called after analysis, returns the Table object of the target of this - * ALTER TABLE statement. - */ - protected Table getTargetTable() { - Preconditions.checkNotNull(table_); - return table_; - } - - public TAlterTableParams toThrift() { - TAlterTableParams params = new TAlterTableParams(); - params.setTable_name(new TTableName(getDb(), getTbl())); - return params; - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - table_ = analyzer.getTable(tableName_, Privilege.ALTER); - if (table_ instanceof KuduTable - && !(this instanceof AlterTableSetTblProperties) - && !(this instanceof AlterTableSetColumnStats) - && !(this instanceof AlterTableOrViewRenameStmt)) { - throw new AnalysisException(String.format( - "ALTER TABLE not allowed on Kudu table: %s", table_.getFullName())); - } - if (table_ instanceof View) { - throw new AnalysisException(String.format( - "ALTER TABLE not allowed on a view: %s", table_.getFullName())); - } - if (table_ instanceof DataSourceTable - && !(this instanceof AlterTableSetColumnStats)) { - throw new AnalysisException(String.format( - "ALTER TABLE not allowed on a table produced by a data source: %s", - table_.getFullName())); - } - } -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AlterViewStmt.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AlterViewStmt.java b/fe/src/main/java/com/cloudera/impala/analysis/AlterViewStmt.java deleted file mode 100644 index 640b3a1..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AlterViewStmt.java +++ /dev/null @@ -1,71 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import com.cloudera.impala.authorization.Privilege; -import com.cloudera.impala.catalog.Table; -import com.cloudera.impala.catalog.View; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.common.RuntimeEnv; - -import com.google.common.base.Preconditions; - -/** - * Represents an ALTER VIEW AS statement. - */ -public class AlterViewStmt extends CreateOrAlterViewStmtBase { - - public AlterViewStmt(TableName tableName, QueryStmt viewDefStmt) { - super(false, tableName, null, null, viewDefStmt); - } - - @Override - public void analyze(Analyzer analyzer) throws AnalysisException { - // Enforce Hive column labels for view compatibility. - analyzer.setUseHiveColLabels(true); - viewDefStmt_.analyze(analyzer); - - Preconditions.checkState(tableName_ != null && !tableName_.isEmpty()); - dbName_ = analyzer.getTargetDbName(tableName_); - owner_ = analyzer.getUser().getName(); - - Table table = analyzer.getTable(tableName_, Privilege.ALTER); - Preconditions.checkNotNull(table); - if (!(table instanceof View)) { - throw new AnalysisException(String.format( - "ALTER VIEW not allowed on a table: %s.%s", dbName_, getTbl())); - } - - createColumnAndViewDefs(analyzer); - if (RuntimeEnv.INSTANCE.computeLineage() || RuntimeEnv.INSTANCE.isTestEnv()) { - computeLineageGraph(analyzer); - } - } - - @Override - public String toSql() { - StringBuilder sb = new StringBuilder(); - sb.append("ALTER VIEW "); - if (tableName_.getDb() != null) { - sb.append(tableName_.getDb() + "."); - } - sb.append(tableName_.getTbl()); - sb.append(" AS " + viewDefStmt_.toSql()); - return sb.toString(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b544f019/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java ---------------------------------------------------------------------- diff --git a/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java b/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java deleted file mode 100644 index 006474d..0000000 --- a/fe/src/main/java/com/cloudera/impala/analysis/AnalysisContext.java +++ /dev/null @@ -1,544 +0,0 @@ -// 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 com.cloudera.impala.analysis; - -import java.io.StringReader; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.cloudera.impala.authorization.AuthorizationChecker; -import com.cloudera.impala.authorization.AuthorizationConfig; -import com.cloudera.impala.authorization.AuthorizeableColumn; -import com.cloudera.impala.authorization.AuthorizeableTable; -import com.cloudera.impala.authorization.Privilege; -import com.cloudera.impala.authorization.PrivilegeRequest; -import com.cloudera.impala.catalog.AuthorizationException; -import com.cloudera.impala.catalog.Db; -import com.cloudera.impala.catalog.ImpaladCatalog; -import com.cloudera.impala.common.AnalysisException; -import com.cloudera.impala.common.InternalException; -import com.cloudera.impala.common.Pair; -import com.cloudera.impala.thrift.TAccessEvent; -import com.cloudera.impala.thrift.TLineageGraph; -import com.cloudera.impala.thrift.TQueryCtx; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -/** - * Wrapper class for parser and analyzer. - */ -public class AnalysisContext { - private final static Logger LOG = LoggerFactory.getLogger(AnalysisContext.class); - private final ImpaladCatalog catalog_; - private final TQueryCtx queryCtx_; - private final AuthorizationConfig authzConfig_; - - // Set in analyze() - private AnalysisResult analysisResult_; - - public AnalysisContext(ImpaladCatalog catalog, TQueryCtx queryCtx, - AuthorizationConfig authzConfig) { - catalog_ = catalog; - queryCtx_ = queryCtx; - authzConfig_ = authzConfig; - } - - static public class AnalysisResult { - private StatementBase stmt_; - private Analyzer analyzer_; - private CreateTableStmt tmpCreateTableStmt_; - - public boolean isAlterTableStmt() { return stmt_ instanceof AlterTableStmt; } - public boolean isAlterViewStmt() { return stmt_ instanceof AlterViewStmt; } - public boolean isComputeStatsStmt() { return stmt_ instanceof ComputeStatsStmt; } - public boolean isQueryStmt() { return stmt_ instanceof QueryStmt; } - public boolean isInsertStmt() { return stmt_ instanceof InsertStmt; } - public boolean isDropDbStmt() { return stmt_ instanceof DropDbStmt; } - public boolean isDropTableOrViewStmt() { - return stmt_ instanceof DropTableOrViewStmt; - } - public boolean isDropFunctionStmt() { return stmt_ instanceof DropFunctionStmt; } - public boolean isDropDataSrcStmt() { return stmt_ instanceof DropDataSrcStmt; } - public boolean isDropStatsStmt() { return stmt_ instanceof DropStatsStmt; } - public boolean isCreateTableLikeStmt() { - return stmt_ instanceof CreateTableLikeStmt; - } - public boolean isCreateViewStmt() { return stmt_ instanceof CreateViewStmt; } - public boolean isCreateTableAsSelectStmt() { - return stmt_ instanceof CreateTableAsSelectStmt; - } - public boolean isCreateTableStmt() { return stmt_ instanceof CreateTableStmt; } - public boolean isCreateDbStmt() { return stmt_ instanceof CreateDbStmt; } - public boolean isCreateUdfStmt() { return stmt_ instanceof CreateUdfStmt; } - public boolean isCreateUdaStmt() { return stmt_ instanceof CreateUdaStmt; } - public boolean isCreateDataSrcStmt() { return stmt_ instanceof CreateDataSrcStmt; } - public boolean isLoadDataStmt() { return stmt_ instanceof LoadDataStmt; } - public boolean isUseStmt() { return stmt_ instanceof UseStmt; } - public boolean isSetStmt() { return stmt_ instanceof SetStmt; } - public boolean isShowTablesStmt() { return stmt_ instanceof ShowTablesStmt; } - public boolean isShowDbsStmt() { return stmt_ instanceof ShowDbsStmt; } - public boolean isShowDataSrcsStmt() { return stmt_ instanceof ShowDataSrcsStmt; } - public boolean isShowStatsStmt() { return stmt_ instanceof ShowStatsStmt; } - public boolean isShowFunctionsStmt() { return stmt_ instanceof ShowFunctionsStmt; } - public boolean isShowCreateTableStmt() { - return stmt_ instanceof ShowCreateTableStmt; - } - public boolean isShowCreateFunctionStmt() { - return stmt_ instanceof ShowCreateFunctionStmt; - } - public boolean isShowFilesStmt() { return stmt_ instanceof ShowFilesStmt; } - public boolean isDescribeDbStmt() { return stmt_ instanceof DescribeDbStmt; } - public boolean isDescribeTableStmt() { return stmt_ instanceof DescribeTableStmt; } - public boolean isResetMetadataStmt() { return stmt_ instanceof ResetMetadataStmt; } - public boolean isExplainStmt() { return stmt_.isExplain(); } - public boolean isShowRolesStmt() { return stmt_ instanceof ShowRolesStmt; } - public boolean isShowGrantRoleStmt() { return stmt_ instanceof ShowGrantRoleStmt; } - public boolean isCreateDropRoleStmt() { return stmt_ instanceof CreateDropRoleStmt; } - public boolean isGrantRevokeRoleStmt() { - return stmt_ instanceof GrantRevokeRoleStmt; - } - public boolean isGrantRevokePrivStmt() { - return stmt_ instanceof GrantRevokePrivStmt; - } - public boolean isTruncateStmt() { return stmt_ instanceof TruncateStmt; } - public boolean isUpdateStmt() { return stmt_ instanceof UpdateStmt; } - public UpdateStmt getUpdateStmt() { return (UpdateStmt) stmt_; } - public boolean isDeleteStmt() { return stmt_ instanceof DeleteStmt; } - public DeleteStmt getDeleteStmt() { return (DeleteStmt) stmt_; } - - public boolean isCatalogOp() { - return isUseStmt() || isViewMetadataStmt() || isDdlStmt(); - } - - private boolean isDdlStmt() { - return isCreateTableLikeStmt() || isCreateTableStmt() || - isCreateViewStmt() || isCreateDbStmt() || isDropDbStmt() || - isDropTableOrViewStmt() || isResetMetadataStmt() || isAlterTableStmt() || - isAlterViewStmt() || isComputeStatsStmt() || isCreateUdfStmt() || - isCreateUdaStmt() || isDropFunctionStmt() || isCreateTableAsSelectStmt() || - isCreateDataSrcStmt() || isDropDataSrcStmt() || isDropStatsStmt() || - isCreateDropRoleStmt() || isGrantRevokeStmt() || isTruncateStmt(); - } - - private boolean isViewMetadataStmt() { - return isShowFilesStmt() || isShowTablesStmt() || isShowDbsStmt() || - isShowFunctionsStmt() || isShowRolesStmt() || isShowGrantRoleStmt() || - isShowCreateTableStmt() || isShowDataSrcsStmt() || isShowStatsStmt() || - isDescribeTableStmt() || isDescribeDbStmt() || isShowCreateFunctionStmt(); - } - - private boolean isGrantRevokeStmt() { - return isGrantRevokeRoleStmt() || isGrantRevokePrivStmt(); - } - - public boolean isDmlStmt() { - return isInsertStmt(); - } - - public AlterTableStmt getAlterTableStmt() { - Preconditions.checkState(isAlterTableStmt()); - return (AlterTableStmt) stmt_; - } - - public AlterViewStmt getAlterViewStmt() { - Preconditions.checkState(isAlterViewStmt()); - return (AlterViewStmt) stmt_; - } - - public ComputeStatsStmt getComputeStatsStmt() { - Preconditions.checkState(isComputeStatsStmt()); - return (ComputeStatsStmt) stmt_; - } - - public CreateTableLikeStmt getCreateTableLikeStmt() { - Preconditions.checkState(isCreateTableLikeStmt()); - return (CreateTableLikeStmt) stmt_; - } - - public CreateViewStmt getCreateViewStmt() { - Preconditions.checkState(isCreateViewStmt()); - return (CreateViewStmt) stmt_; - } - - public CreateTableAsSelectStmt getCreateTableAsSelectStmt() { - Preconditions.checkState(isCreateTableAsSelectStmt()); - return (CreateTableAsSelectStmt) stmt_; - } - - public CreateTableStmt getCreateTableStmt() { - Preconditions.checkState(isCreateTableStmt()); - return (CreateTableStmt) stmt_; - } - - public CreateTableStmt getTmpCreateTableStmt() { - return tmpCreateTableStmt_; - } - - public CreateDbStmt getCreateDbStmt() { - Preconditions.checkState(isCreateDbStmt()); - return (CreateDbStmt) stmt_; - } - - public CreateUdfStmt getCreateUdfStmt() { - Preconditions.checkState(isCreateUdfStmt()); - return (CreateUdfStmt) stmt_; - } - - public CreateUdaStmt getCreateUdaStmt() { - Preconditions.checkState(isCreateUdfStmt()); - return (CreateUdaStmt) stmt_; - } - - public DropDbStmt getDropDbStmt() { - Preconditions.checkState(isDropDbStmt()); - return (DropDbStmt) stmt_; - } - - public DropTableOrViewStmt getDropTableOrViewStmt() { - Preconditions.checkState(isDropTableOrViewStmt()); - return (DropTableOrViewStmt) stmt_; - } - - public TruncateStmt getTruncateStmt() { - Preconditions.checkState(isTruncateStmt()); - return (TruncateStmt) stmt_; - } - - public DropFunctionStmt getDropFunctionStmt() { - Preconditions.checkState(isDropFunctionStmt()); - return (DropFunctionStmt) stmt_; - } - - public LoadDataStmt getLoadDataStmt() { - Preconditions.checkState(isLoadDataStmt()); - return (LoadDataStmt) stmt_; - } - - public QueryStmt getQueryStmt() { - Preconditions.checkState(isQueryStmt()); - return (QueryStmt) stmt_; - } - - public InsertStmt getInsertStmt() { - if (isCreateTableAsSelectStmt()) { - return getCreateTableAsSelectStmt().getInsertStmt(); - } else { - Preconditions.checkState(isInsertStmt()); - return (InsertStmt) stmt_; - } - } - - public UseStmt getUseStmt() { - Preconditions.checkState(isUseStmt()); - return (UseStmt) stmt_; - } - - public SetStmt getSetStmt() { - Preconditions.checkState(isSetStmt()); - return (SetStmt) stmt_; - } - - public ShowTablesStmt getShowTablesStmt() { - Preconditions.checkState(isShowTablesStmt()); - return (ShowTablesStmt) stmt_; - } - - public ShowDbsStmt getShowDbsStmt() { - Preconditions.checkState(isShowDbsStmt()); - return (ShowDbsStmt) stmt_; - } - - public ShowDataSrcsStmt getShowDataSrcsStmt() { - Preconditions.checkState(isShowDataSrcsStmt()); - return (ShowDataSrcsStmt) stmt_; - } - - public ShowStatsStmt getShowStatsStmt() { - Preconditions.checkState(isShowStatsStmt()); - return (ShowStatsStmt) stmt_; - } - - public ShowFunctionsStmt getShowFunctionsStmt() { - Preconditions.checkState(isShowFunctionsStmt()); - return (ShowFunctionsStmt) stmt_; - } - - public ShowFilesStmt getShowFilesStmt() { - Preconditions.checkState(isShowFilesStmt()); - return (ShowFilesStmt) stmt_; - } - - public DescribeDbStmt getDescribeDbStmt() { - Preconditions.checkState(isDescribeDbStmt()); - return (DescribeDbStmt) stmt_; - } - - public DescribeTableStmt getDescribeTableStmt() { - Preconditions.checkState(isDescribeTableStmt()); - return (DescribeTableStmt) stmt_; - } - - public ShowCreateTableStmt getShowCreateTableStmt() { - Preconditions.checkState(isShowCreateTableStmt()); - return (ShowCreateTableStmt) stmt_; - } - - public ShowCreateFunctionStmt getShowCreateFunctionStmt() { - Preconditions.checkState(isShowCreateFunctionStmt()); - return (ShowCreateFunctionStmt) stmt_; - } - - public StatementBase getStmt() { return stmt_; } - public Analyzer getAnalyzer() { return analyzer_; } - public Set<TAccessEvent> getAccessEvents() { return analyzer_.getAccessEvents(); } - public boolean requiresRewrite() { - return analyzer_.containsSubquery() && !(stmt_ instanceof CreateViewStmt) - && !(stmt_ instanceof AlterViewStmt); - } - public TLineageGraph getThriftLineageGraph() { - return analyzer_.getThriftSerializedLineageGraph(); - } - } - - /** - * Parse and analyze 'stmt'. If 'stmt' is a nested query (i.e. query that - * contains subqueries), it is also rewritten by performing subquery unnesting. - * The transformed stmt is then re-analyzed in a new analysis context. - * - * The result of analysis can be retrieved by calling - * getAnalysisResult(). - * - * @throws AnalysisException - * On any other error, including parsing errors. Also thrown when any - * missing tables are detected as a result of running analysis. - */ - public void analyze(String stmt) throws AnalysisException { - Analyzer analyzer = new Analyzer(catalog_, queryCtx_, authzConfig_); - analyze(stmt, analyzer); - } - - /** - * Parse and analyze 'stmt' using a specified Analyzer. - */ - public void analyze(String stmt, Analyzer analyzer) throws AnalysisException { - SqlScanner input = new SqlScanner(new StringReader(stmt)); - SqlParser parser = new SqlParser(input); - try { - analysisResult_ = new AnalysisResult(); - analysisResult_.analyzer_ = analyzer; - if (analysisResult_.analyzer_ == null) { - analysisResult_.analyzer_ = new Analyzer(catalog_, queryCtx_, authzConfig_); - } - analysisResult_.stmt_ = (StatementBase) parser.parse().value; - if (analysisResult_.stmt_ == null) return; - - // For CTAS, we copy the create statement in case we have to create a new CTAS - // statement after a query rewrite. - if (analysisResult_.stmt_ instanceof CreateTableAsSelectStmt) { - analysisResult_.tmpCreateTableStmt_ = - ((CreateTableAsSelectStmt)analysisResult_.stmt_).getCreateStmt().clone(); - } - - analysisResult_.stmt_.analyze(analysisResult_.analyzer_); - boolean isExplain = analysisResult_.isExplainStmt(); - - // Check if we need to rewrite the statement. - if (analysisResult_.requiresRewrite()) { - StatementBase rewrittenStmt = StmtRewriter.rewrite(analysisResult_); - // Re-analyze the rewritten statement. - Preconditions.checkNotNull(rewrittenStmt); - analysisResult_ = new AnalysisResult(); - analysisResult_.analyzer_ = new Analyzer(catalog_, queryCtx_, authzConfig_); - analysisResult_.stmt_ = rewrittenStmt; - analysisResult_.stmt_.analyze(analysisResult_.analyzer_); - LOG.trace("rewrittenStmt: " + rewrittenStmt.toSql()); - if (isExplain) analysisResult_.stmt_.setIsExplain(); - Preconditions.checkState(!analysisResult_.requiresRewrite()); - } - } catch (AnalysisException e) { - // Don't wrap AnalysisExceptions in another AnalysisException - throw e; - } catch (Exception e) { - throw new AnalysisException(parser.getErrorMsg(stmt), e); - } - } - - /** - * Authorize an analyzed statement. - * analyze() must have already been called. Throws an AuthorizationException if the - * user doesn't have sufficient privileges to run this statement. - */ - public void authorize(AuthorizationChecker authzChecker) - throws AuthorizationException, InternalException { - Preconditions.checkNotNull(analysisResult_); - Analyzer analyzer = getAnalyzer(); - // Process statements for which column-level privilege requests may be registered - // except for DESCRIBE TABLE or REFRESH/INVALIDATE statements - if (analysisResult_.isQueryStmt() || analysisResult_.isInsertStmt() || - analysisResult_.isUpdateStmt() || analysisResult_.isDeleteStmt() || - analysisResult_.isCreateTableAsSelectStmt() || - analysisResult_.isCreateViewStmt() || analysisResult_.isAlterViewStmt()) { - // Map of table name to a list of privilege requests associated with that table. - // These include both table-level and column-level privilege requests. - Map<String, List<PrivilegeRequest>> tablePrivReqs = Maps.newHashMap(); - // Privilege requests that are not column or table-level. - List<PrivilegeRequest> otherPrivReqs = Lists.newArrayList(); - // Group the registered privilege requests based on the table they reference. - for (PrivilegeRequest privReq: analyzer.getPrivilegeReqs()) { - String tableName = privReq.getAuthorizeable().getFullTableName(); - if (tableName == null) { - otherPrivReqs.add(privReq); - } else { - List<PrivilegeRequest> requests = tablePrivReqs.get(tableName); - if (requests == null) { - requests = Lists.newArrayList(); - tablePrivReqs.put(tableName, requests); - } - // The table-level SELECT must be the first table-level request, and it - // must precede all column-level privilege requests. - Preconditions.checkState((requests.isEmpty() || - !(privReq.getAuthorizeable() instanceof AuthorizeableColumn)) || - (requests.get(0).getAuthorizeable() instanceof AuthorizeableTable && - requests.get(0).getPrivilege() == Privilege.SELECT)); - requests.add(privReq); - } - } - - // Check any non-table, non-column privilege requests first. - for (PrivilegeRequest request: otherPrivReqs) { - authorizePrivilegeRequest(authzChecker, request); - } - - // Authorize table accesses, one table at a time, by considering both table and - // column-level privilege requests. - for (Map.Entry<String, List<PrivilegeRequest>> entry: tablePrivReqs.entrySet()) { - authorizeTableAccess(authzChecker, entry.getValue()); - } - } else { - for (PrivilegeRequest privReq: analyzer.getPrivilegeReqs()) { - Preconditions.checkState( - !(privReq.getAuthorizeable() instanceof AuthorizeableColumn) || - analysisResult_.isDescribeTableStmt() || - analysisResult_.isResetMetadataStmt()); - authorizePrivilegeRequest(authzChecker, privReq); - } - } - - // Check any masked requests. - for (Pair<PrivilegeRequest, String> maskedReq: analyzer.getMaskedPrivilegeReqs()) { - if (!authzChecker.hasAccess(analyzer.getUser(), maskedReq.first)) { - throw new AuthorizationException(maskedReq.second); - } - } - } - - /** - * Authorize a privilege request. - * Throws an AuthorizationException if the user doesn't have sufficient privileges for - * this request. Also, checks if the request references a system database. - */ - private void authorizePrivilegeRequest(AuthorizationChecker authzChecker, - PrivilegeRequest request) throws AuthorizationException, InternalException { - Preconditions.checkNotNull(request); - String dbName = null; - if (request.getAuthorizeable() != null) { - dbName = request.getAuthorizeable().getDbName(); - } - // If this is a system database, some actions should always be allowed - // or disabled, regardless of what is in the auth policy. - if (dbName != null && checkSystemDbAccess(dbName, request.getPrivilege())) { - return; - } - authzChecker.checkAccess(getAnalyzer().getUser(), request); - } - - /** - * Authorize a list of privilege requests associated with a single table. - * It checks if the user has sufficient table-level privileges and if that is - * not the case, it falls back on checking column-level privileges, if any. This - * function requires 'SELECT' requests to be ordered by table and then by column - * privilege requests. Throws an AuthorizationException if the user doesn't have - * sufficient privileges. - */ - private void authorizeTableAccess(AuthorizationChecker authzChecker, - List<PrivilegeRequest> requests) - throws AuthorizationException, InternalException { - Preconditions.checkState(!requests.isEmpty()); - Analyzer analyzer = getAnalyzer(); - boolean hasTableSelectPriv = true; - boolean hasColumnSelectPriv = false; - for (PrivilegeRequest request: requests) { - if (request.getAuthorizeable() instanceof AuthorizeableTable) { - try { - authorizePrivilegeRequest(authzChecker, request); - } catch (AuthorizationException e) { - // Authorization fails if we fail to authorize any table-level request that is - // not a SELECT privilege (e.g. INSERT). - if (request.getPrivilege() != Privilege.SELECT) throw e; - hasTableSelectPriv = false; - } - } else { - Preconditions.checkState( - request.getAuthorizeable() instanceof AuthorizeableColumn); - if (hasTableSelectPriv) continue; - if (authzChecker.hasAccess(analyzer.getUser(), request)) { - hasColumnSelectPriv = true; - continue; - } - // Make sure we don't reveal any column names in the error message. - throw new AuthorizationException(String.format("User '%s' does not have " + - "privileges to execute '%s' on: %s", analyzer.getUser().getName(), - request.getPrivilege().toString(), - request.getAuthorizeable().getFullTableName())); - } - } - if (!hasTableSelectPriv && !hasColumnSelectPriv) { - throw new AuthorizationException(String.format("User '%s' does not have " + - "privileges to execute 'SELECT' on: %s", analyzer.getUser().getName(), - requests.get(0).getAuthorizeable().getFullTableName())); - } - } - - /** - * Throws an AuthorizationException if the dbName is a system db - * and the user is trying to modify it. - * Returns true if this is a system db and the action is allowed. - */ - private boolean checkSystemDbAccess(String dbName, Privilege privilege) - throws AuthorizationException { - Db db = catalog_.getDb(dbName); - if (db != null && db.isSystemDb()) { - switch (privilege) { - case VIEW_METADATA: - case ANY: - return true; - default: - throw new AuthorizationException("Cannot modify system database."); - } - } - return false; - } - - public AnalysisResult getAnalysisResult() { return analysisResult_; } - public Analyzer getAnalyzer() { return getAnalysisResult().getAnalyzer(); } -}
