HttpDialectConverterPlugin.java
// 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.doris.plugin.dialect;
import org.apache.doris.analysis.StatementBase;
import org.apache.doris.common.util.DigitalVersion;
import org.apache.doris.nereids.parser.Dialect;
import org.apache.doris.plugin.DialectConverterPlugin;
import org.apache.doris.plugin.Plugin;
import org.apache.doris.plugin.PluginContext;
import org.apache.doris.plugin.PluginException;
import org.apache.doris.plugin.PluginInfo;
import org.apache.doris.plugin.PluginInfo.PluginType;
import org.apache.doris.plugin.PluginMgr;
import org.apache.doris.qe.GlobalVariable;
import org.apache.doris.qe.SessionVariable;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
/**
* Currently, there are many frameworks and services that support SQL dialect conversion,
* but they may not be implemented in Java.
* Therefore, we can encapsulate these SQL dialect conversion frameworks or services into an HTTP service,
* and combine them with this plugin to provide dialect conversion capabilities.
* Note that the protocol request/response for the wrapped HTTP service must comply with the following rules:
* <pre>
* Request body:
* {
* "version": "v1",
* "sql": "select * from t",
* "from": "presto",
* "to": "doris",
* "source": "text",
* "case_sensitive": "0"
* }
*
* Response body:
* {
* "version": "v1",
* "data": "select * from t",
* "code": 0,
* "message": ""
* }
* </pre>
* */
public class HttpDialectConverterPlugin extends Plugin implements DialectConverterPlugin {
private volatile boolean isInit = false;
private volatile ImmutableSet<Dialect> acceptDialects;
private final PluginInfo pluginInfo;
public HttpDialectConverterPlugin() {
pluginInfo = new PluginInfo(PluginMgr.BUILTIN_PLUGIN_PREFIX + "SqlDialectConverter", PluginType.DIALECT,
"builtin sql dialect converter", DigitalVersion.fromString("2.1.0"),
DigitalVersion.fromString("1.8.31"), HttpDialectConverterPlugin.class.getName(), null, null);
acceptDialects = ImmutableSet.copyOf(Arrays.asList(Dialect.PRESTO, Dialect.TRINO, Dialect.HIVE,
Dialect.SPARK, Dialect.POSTGRES, Dialect.CLICKHOUSE, Dialect.STARROCKS));
}
public PluginInfo getPluginInfo() {
return pluginInfo;
}
@Override
public void init(PluginInfo info, PluginContext ctx) throws PluginException {
super.init(info, ctx);
}
@Override
public void close() throws IOException {
super.close();
}
@Override
public ImmutableSet<Dialect> acceptDialects() {
return acceptDialects;
}
@Override
public @Nullable String convertSql(String originSql, SessionVariable sessionVariable) {
String targetURL = GlobalVariable.sqlConverterServiceUrl;
if (Strings.isNullOrEmpty(targetURL)) {
return null;
}
return HttpDialectUtils.convertSql(targetURL, originSql, sessionVariable.getSqlDialect(),
sessionVariable.getSqlConvertorFeatures(), sessionVariable.getSqlConvertorConfig());
}
// no need to override parseSqlWithDialect, just return null
@Override
public List<StatementBase> parseSqlWithDialect(String sql, SessionVariable sessionVariable) {
return null;
}
}