/*
* 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.kylin.rest.controller;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.kylin.common.util.StringUtil;
import org.apache.kylin.metadata.model.TableDesc;
import org.apache.kylin.rest.exception.InternalErrorException;
import org.apache.kylin.rest.exception.NotFoundException;
import org.apache.kylin.rest.request.CardinalityRequest;
import org.apache.kylin.rest.request.HiveTableRequest;
import org.apache.kylin.rest.service.TableService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.common.collect.Sets;
/**
* @author xduo
*/
@Controller
@RequestMapping(value = "/tables")
public class TableController extends BasicController {
private static final Logger logger = LoggerFactory.getLogger(TableController.class);
@Autowired
private TableService tableService;
/**
* Get available table list of the project
*
* @return Table metadata array
* @throws IOException
*/
@RequestMapping(value = "", method = { RequestMethod.GET })
@ResponseBody
public List<TableDesc> getTableDesc(@RequestParam(value = "ext", required = false) boolean withExt, @RequestParam(value = "project", required = true) String project) throws IOException {
try {
return tableService.getTableDescByProject(project, withExt);
} catch (IOException e) {
logger.error("Failed to get Hive Tables", e);
throw new InternalErrorException(e.getLocalizedMessage());
}
}
/**
* Get available table list of the input database
*
* @return Table metadata array
* @throws IOException
*/
@RequestMapping(value = "/{tableName:.+}", method = { RequestMethod.GET })
@ResponseBody
public TableDesc getTableDesc(@PathVariable String tableName) {
TableDesc table = tableService.getTableDescByName(tableName, false);
if (table == null)
throw new NotFoundException("Could not find Hive table: " + tableName);
return table;
}
@RequestMapping(value = "/{tables}/{project}", method = { RequestMethod.POST })
@ResponseBody
public Map<String, String[]> loadHiveTables(@PathVariable String tables, @PathVariable String project, @RequestBody HiveTableRequest request) throws IOException {
String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
Map<String, String[]> result = new HashMap<String, String[]>();
String[] tableNames = StringUtil.splitAndTrim(tables, ",");
try {
String[] loaded = tableService.loadHiveTablesToProject(tableNames, project);
result.put("result.loaded", loaded);
Set<String> allTables = new HashSet<String>();
for (String tableName : tableNames) {
allTables.add(tableService.normalizeHiveTableName(tableName));
}
for (String loadedTableName : loaded) {
allTables.remove(loadedTableName);
}
String[] unloaded = new String[allTables.size()];
allTables.toArray(unloaded);
result.put("result.unloaded", unloaded);
if (request.isCalculate()) {
tableService.calculateCardinalityIfNotPresent(loaded, submitter);
}
} catch (Throwable e) {
logger.error("Failed to load Hive Table", e);
throw new InternalErrorException(e.getLocalizedMessage());
}
return result;
}
@RequestMapping(value = "/{tables}/{project}", method = { RequestMethod.DELETE })
@ResponseBody
public Map<String, String[]> unLoadHiveTables(@PathVariable String tables, @PathVariable String project) {
Set<String> unLoadSuccess = Sets.newHashSet();
Set<String> unLoadFail = Sets.newHashSet();
Map<String, String[]> result = new HashMap<String, String[]>();
try {
for (String tableName : tables.split(",")) {
if (tableService.unLoadHiveTable(tableName, project)) {
unLoadSuccess.add(tableName);
} else {
unLoadFail.add(tableName);
}
}
} catch (Throwable e) {
logger.error("Failed to unload Hive Table", e);
throw new InternalErrorException(e.getLocalizedMessage());
}
result.put("result.unload.success", (String[]) unLoadSuccess.toArray(new String[unLoadSuccess.size()]));
result.put("result.unload.fail", (String[]) unLoadFail.toArray(new String[unLoadFail.size()]));
return result;
}
/**
* Regenerate table cardinality
*
* @return Table metadata array
* @throws IOException
*/
@RequestMapping(value = "/{tableNames}/cardinality", method = { RequestMethod.PUT })
@ResponseBody
public CardinalityRequest generateCardinality(@PathVariable String tableNames, @RequestBody CardinalityRequest request) throws IOException {
String submitter = SecurityContextHolder.getContext().getAuthentication().getName();
String[] tables = tableNames.split(",");
try {
for (String table : tables) {
tableService.calculateCardinality(table.trim().toUpperCase(), submitter);
}
} catch (IOException e) {
logger.error("Failed to calculate cardinality", e);
throw new InternalErrorException(e.getLocalizedMessage());
}
return request;
}
/**
* Show all databases in Hive
*
* @return Hive databases list
* @throws IOException
*/
@RequestMapping(value = "/hive", method = { RequestMethod.GET })
@ResponseBody
private List<String> showHiveDatabases() throws IOException {
try {
return tableService.getHiveDbNames();
} catch (Throwable e) {
logger.error(e.getLocalizedMessage(), e);
throw new InternalErrorException(e.getLocalizedMessage());
}
}
/**
* Show all tables in a Hive database
*
* @return Hive table list
* @throws IOException
*/
@RequestMapping(value = "/hive/{database}", method = { RequestMethod.GET })
@ResponseBody
private List<String> showHiveTables(@PathVariable String database) throws IOException {
try {
return tableService.getHiveTableNames(database);
} catch (Throwable e) {
logger.error(e.getLocalizedMessage(), e);
throw new InternalErrorException(e.getLocalizedMessage());
}
}
}