All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.drill.exec.client.DrillSqlLineApplication Maven / Gradle / Ivy

/*
 * 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.drill.exec.client;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import org.apache.drill.common.scanner.ClassPathScanner;
import org.apache.drill.common.util.DrillVersionInfo;
import org.apache.drill.shaded.guava.com.google.common.annotations.VisibleForTesting;
import org.jline.reader.impl.completer.StringsCompleter;
import sqlline.Application;
import sqlline.CommandHandler;
import sqlline.ConnectionMetadata;
import sqlline.OutputFormat;
import sqlline.PromptHandler;
import sqlline.ReflectiveCommandHandler;
import sqlline.SqlLine;
import sqlline.SqlLineOpts;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 

Drill SqlLine application configuration.

* *

Customizes SqlLine for Drill, i.e. overrides application info message, * known drivers, connection url examples, removes non applicable commands, sets SqlLine properties.

* *

Uses {@link #DRILL_SQLLINE_CONF} as base configuration, allows to override it using {@link #DRILL_SQLLINE_OVERRIDE_CONF}. * If configuration files are missing in the classpath, issues warning and proceeds with default SqlLine configuration.

*/ public class DrillSqlLineApplication extends Application { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillSqlLineApplication.class); private static final String DRILL_SQLLINE_CONF = "drill-sqlline.conf"; private static final String DRILL_SQLLINE_OVERRIDE_CONF = "drill-sqlline-override.conf"; private static final String INFO_MESSAGE_TEMPLATE_CONF = "drill.sqlline.info_message_template"; private static final String QUOTES_CONF = "drill.sqlline.quotes"; private static final String DRIVERS_CONF = "drill.sqlline.drivers"; private static final String CONNECTION_URL_EXAMPLES_CONF = "drill.sqlline.connection_url_examples"; private static final String COMMANDS_TO_EXCLUDE_CONF = "drill.sqlline.commands.exclude"; private static final String OPTS_CONF = "drill.sqlline.opts"; private static final String PROMPT_WITH_SCHEMA = "drill.sqlline.prompt.with_schema"; private final Config config; public DrillSqlLineApplication() { this(DRILL_SQLLINE_CONF, DRILL_SQLLINE_OVERRIDE_CONF); } @VisibleForTesting public DrillSqlLineApplication(String configName, String overrideConfigName) { this.config = overrideConfig(overrideConfigName, loadConfig(configName)); if (config.isEmpty()) { logger.warn("Was unable to find / load [{}]. Will use default SqlLine configuration.", configName); } } public Config getConfig() { return config; } @Override public String getInfoMessage() { if (config.hasPath(INFO_MESSAGE_TEMPLATE_CONF)) { String quote = ""; if (config.hasPath(QUOTES_CONF)) { List quotes = config.getStringList(QUOTES_CONF); quote = quotes.get(new Random().nextInt(quotes.size())); } return String.format(config.getString(INFO_MESSAGE_TEMPLATE_CONF), getVersion(), quote); } return super.getInfoMessage(); } @Override public String getVersion() { return DrillVersionInfo.getVersion(); } @Override public List allowedDrivers() { if (config.hasPath(DRIVERS_CONF)) { return config.getStringList(DRIVERS_CONF); } return super.allowedDrivers(); } @Override public Map getOutputFormats(SqlLine sqlLine) { return sqlLine.getOutputFormats(); } @Override public Collection getConnectionUrlExamples() { if (config.hasPath(CONNECTION_URL_EXAMPLES_CONF)) { return config.getStringList(CONNECTION_URL_EXAMPLES_CONF); } return super.getConnectionUrlExamples(); } @Override public Collection getCommandHandlers(SqlLine sqlLine) { List commandsToExclude = new ArrayList<>(); // exclude connect command and then add it back to ensure connection url examples are updated boolean reloadConnect = config.hasPath(CONNECTION_URL_EXAMPLES_CONF); if (reloadConnect) { commandsToExclude.add("connect"); } if (config.hasPath(COMMANDS_TO_EXCLUDE_CONF)) { commandsToExclude.addAll(config.getStringList(COMMANDS_TO_EXCLUDE_CONF)); } if (commandsToExclude.isEmpty()) { return sqlLine.getCommandHandlers(); } List commandHandlers = sqlLine.getCommandHandlers().stream() .filter(c -> c.getNames().stream() .noneMatch(commandsToExclude::contains)) .collect(Collectors.toList()); if (reloadConnect) { commandHandlers.add(new ReflectiveCommandHandler(sqlLine, new StringsCompleter(getConnectionUrlExamples()), "connect", "open")); } return commandHandlers; } @Override public SqlLineOpts getOpts(SqlLine sqlLine) { SqlLineOpts opts = sqlLine.getOpts(); if (config.hasPath(OPTS_CONF)) { Config optsConfig = config.getConfig(OPTS_CONF); optsConfig.entrySet().forEach( e -> { String key = e.getKey(); String value = String.valueOf(e.getValue().unwrapped()); if (!opts.set(key, value, true)) { logger.warn("Unable to set SqlLine property [{}] to [{}].", key, value); } } ); } return opts; } @Override public PromptHandler getPromptHandler(SqlLine sqlLine) { if (config.hasPath(PROMPT_WITH_SCHEMA) && config.getBoolean(PROMPT_WITH_SCHEMA)) { return new PromptHandler(sqlLine) { @Override protected String getDefaultPrompt(int connectionIndex, String url, String defaultPrompt) { StringBuilder builder = new StringBuilder(); builder.append("apache drill"); ConnectionMetadata meta = sqlLine.getConnectionMetadata(); String currentSchema = meta.getCurrentSchema(); if (currentSchema != null) { builder.append(" (").append(currentSchema).append(")"); } return builder.append("> ").toString(); } }; } return super.getPromptHandler(sqlLine); } private Config loadConfig(String configName) { Set urls = ClassPathScanner.forResource(configName, false); if (urls.size() != 1) { if (logger.isDebugEnabled()) { urls.forEach( u -> logger.debug("Found duplicating [{}]: [{}].", configName, u.getPath()) ); } return ConfigFactory.empty(); } URL url = urls.iterator().next(); try { logger.debug("Parsing [{}] for the url: [{}].", configName, url.getPath()); return ConfigFactory.parseURL(url); } catch (Exception e) { logger.warn("Was unable to parse [{}].", url.getPath(), e); return ConfigFactory.empty(); } } private Config overrideConfig(String configName, Config config) { Config overrideConfig = loadConfig(configName); return overrideConfig.withFallback(config).resolve(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy