From d41b907cf8a16f176cda3e59fe4f6cc7e61cf59c Mon Sep 17 00:00:00 2001 From: honma Date: Thu, 13 Nov 2014 16:49:08 +0800 Subject: [PATCH 1/9] add a API for purging cubes --- .../kylinolap/rest/controller/CubeController.java | 32 ++++++++------ .../rest/interceptor/CacheIntercaptor.java | 2 +- .../com/kylinolap/rest/service/CubeService.java | 50 ++++++++++++++++------ 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/server/src/main/java/com/kylinolap/rest/controller/CubeController.java b/server/src/main/java/com/kylinolap/rest/controller/CubeController.java index c8f4252..5ea9df2 100644 --- a/server/src/main/java/com/kylinolap/rest/controller/CubeController.java +++ b/server/src/main/java/com/kylinolap/rest/controller/CubeController.java @@ -215,12 +215,6 @@ public JobInstance rebuild(@PathVariable String cubeName, @RequestBody JobBuildR return jobInstance; } - /** - * Get available table list of the input database - * - * @return true - * @throws IOException - */ @RequestMapping(value = "/{cubeName}/disable", method = { RequestMethod.PUT }) @ResponseBody @Metered(name = "disableCube") @@ -240,12 +234,26 @@ public CubeInstance disableCube(@PathVariable String cubeName) { } } - /** - * Get available table list of the input database - * - * @return true - * @throws IOException - */ + @RequestMapping(value = "/{cubeName}/purge", method = { RequestMethod.PUT }) + @ResponseBody + @Metered(name = "purgeCube") + public CubeInstance purgeCube(@PathVariable String cubeName) { + try { + CubeInstance cube = cubeService.getCubeManager().getCube(cubeName); + + if (cube == null) { + throw new InternalErrorException("Cannot find cube " + cubeName); + } + + return cubeService.purgeCube(cube); + } catch (Exception e) { + String message = "Failed to purge cube: " + cubeName; + logger.error(message, e); + throw new InternalErrorException(message + " Caused by: " + e.getMessage(), e); + } + } + + @RequestMapping(value = "/{cubeName}/enable", method = { RequestMethod.PUT }) @ResponseBody @Metered(name = "enableCube") diff --git a/server/src/main/java/com/kylinolap/rest/interceptor/CacheIntercaptor.java b/server/src/main/java/com/kylinolap/rest/interceptor/CacheIntercaptor.java index 7bf2b98..2b763dd 100644 --- a/server/src/main/java/com/kylinolap/rest/interceptor/CacheIntercaptor.java +++ b/server/src/main/java/com/kylinolap/rest/interceptor/CacheIntercaptor.java @@ -35,7 +35,7 @@ public void flush(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); - if (methodName.matches("(update|create|save|disable|enable|delete|drop)")) { + if (methodName.matches("(update|create|save|disable|enable|delete|drop|purge)")) { Broadcaster.flush(); } } diff --git a/server/src/main/java/com/kylinolap/rest/service/CubeService.java b/server/src/main/java/com/kylinolap/rest/service/CubeService.java index 0c03e3d..1523142 100644 --- a/server/src/main/java/com/kylinolap/rest/service/CubeService.java +++ b/server/src/main/java/com/kylinolap/rest/service/CubeService.java @@ -83,7 +83,7 @@ /** * Stateless & lightweight service facade of cube management functions. - * + * * @author yangli9 */ @Component("cubeMgmtService") @@ -267,9 +267,36 @@ public void removeCubeCache(String cubeName) { } /** + * Stop all jobs belonging to this cube and clean out all segments + * + * @param cube + * @return + * @throws IOException + * @throws CubeIntegrityException + * @throws JobException + */ + @PreAuthorize(Constant.ACCESS_HAS_ROLE_ADMIN + " or hasPermission(#cube, 'ADMINISTRATION') or hasPermission(#cube, 'OPERATION') or hasPermission(#cube, 'MANAGEMENT')") + @Caching(evict = { @CacheEvict(value = QueryController.SUCCESS_QUERY_CACHE, allEntries = true), @CacheEvict(value = QueryController.EXCEPTION_QUERY_CACHE, allEntries = true) }) + public CubeInstance purgeCube(CubeInstance cube) throws IOException, CubeIntegrityException, JobException { + String cubeName = cube.getName(); + + CubeStatusEnum ostatus = cube.getStatus(); + if (null != ostatus && !CubeStatusEnum.DISABLED.equals(ostatus)) { + throw new InternalErrorException("Only disabled cube can be purged, status of " + cubeName + " is " + ostatus); + } + + try { + this.releaseAllSegments(cube); + return cube; + } catch (IOException e) { + throw e; + } + + } + + /** * Update a cube status from ready to disabled. - * - * @param cubeName + * * @return * @throws CubeIntegrityException * @throws IOException @@ -297,7 +324,7 @@ public CubeInstance disableCube(CubeInstance cube) throws IOException, CubeInteg /** * Update a cube status from disable to ready. - * + * * @return * @throws CubeIntegrityException * @throws IOException @@ -365,13 +392,11 @@ public MetricsResponse calculateMetrics(MetricsRequest request) { /** * Calculate size of each region for given table and other info of the * table. - * - * @param tableName - * The table name. + * + * @param tableName The table name. * @return The HBaseResponse object contains table size, region count. null - * if error happens. - * @throws IOException - * Exception when HTable resource is not closed correctly. + * if error happens. + * @throws IOException Exception when HTable resource is not closed correctly. */ public HBaseResponse getHTableInfo(String tableName) throws IOException { // Get HBase storage conf. @@ -411,7 +436,7 @@ public HBaseResponse getHTableInfo(String tableName) throws IOException { /** * Generate cardinality for table This will trigger a hadoop job and nothing * The result will be merged into table exd info - * + * * @param tableName * @param delimiter * @param format @@ -532,7 +557,8 @@ public CubeInstance rebuildLookupSnapshot(String cubeName, String segmentName, S } /** - * @param cube + * purge the cube + * * @throws IOException * @throws JobException * @throws UnknownHostException From 097bf405ae224f9e6bc23abbed1e3f45ded89342 Mon Sep 17 00:00:00 2001 From: jiazhong Date: Thu, 13 Nov 2014 17:24:06 +0800 Subject: [PATCH 2/9] add purge cube in front page --- webapp/app/js/controllers/cubes.js | 8 ++++++++ webapp/app/js/services/cubes.js | 1 + webapp/app/partials/cubes/cubes.html | 2 ++ 3 files changed, 11 insertions(+) diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js index ece6f01..f6dca82 100644 --- a/webapp/app/js/controllers/cubes.js +++ b/webapp/app/js/controllers/cubes.js @@ -118,6 +118,14 @@ KylinApp } } + $scope.purge = function (cube) { + if (confirm("Are you sure to purge the cube? ")) { + CubeService.purge({cubeId: cube.name}, {}, function (result) { + MessageService.sendMsg('Purge job was submitted successfully', 'success', {}); + }); + } + } + $scope.disable = function (cube) { if (confirm("Are you sure to disable the cube?")) { CubeService.disable({cubeId: cube.name}, {}, function (result) { diff --git a/webapp/app/js/services/cubes.js b/webapp/app/js/services/cubes.js index 4753bcd..ad7f670 100644 --- a/webapp/app/js/services/cubes.js +++ b/webapp/app/js/services/cubes.js @@ -8,6 +8,7 @@ KylinApp.factory('CubeService', ['$resource', function ($resource, config) { rebuildCube: {method: 'PUT', params: {action: 'rebuild'}, isArray: false}, disable: {method: 'PUT', params: {action: 'disable'}, isArray: false}, enable: {method: 'PUT', params: {action: 'enable'}, isArray: false}, + purge: {method: 'PUT', params: {action: 'purge'}, isArray: false}, drop: {method: 'DELETE', params: {}, isArray: false}, save: {method: 'POST', params: {}, isArray: false}, update: {method: 'PUT', params: {}, isArray: false}, diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html index 437aaa3..c9be05c 100644 --- a/webapp/app/partials/cubes/cubes.html +++ b/webapp/app/partials/cubes/cubes.html @@ -97,6 +97,8 @@
  • Merge
  • Disable
  • Enable
  • +
  • Purge
  • + From 579ae3404f1b8142be86272b25db0f3b26f2644f Mon Sep 17 00:00:00 2001 From: "Li, Yang" Date: Thu, 13 Nov 2014 17:27:57 +0800 Subject: [PATCH 3/9] exclude a few files in coverage test --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 15af0dd..84edc94 100644 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,7 @@ reuseReports ${project.basedir}/../target/jacoco.exec java + com/kylinolap/**/tools/**:net/hydromatic/optiq/**:org/eigenbase/sql2rel/** From cdb6b4f72b98b1200d37c69899a9c281cc899469 Mon Sep 17 00:00:00 2001 From: "Li, Yang" Date: Thu, 13 Nov 2014 17:28:43 +0800 Subject: [PATCH 4/9] rename package to com/kylinolap/jdbc --- jdbc/src/main/java/com/kylinolap/jdbc/Driver.java | 137 ++++ .../com/kylinolap/jdbc/KylinConnectionImpl.java | 157 ++++ .../java/com/kylinolap/jdbc/KylinEnumerator.java | 85 +++ .../com/kylinolap/jdbc/KylinJdbc40Factory.java | 28 + .../com/kylinolap/jdbc/KylinJdbc41Factory.java | 125 ++++ .../java/com/kylinolap/jdbc/KylinMetaImpl.java | 825 +++++++++++++++++++++ .../main/java/com/kylinolap/jdbc/KylinPrepare.java | 96 +++ .../java/com/kylinolap/jdbc/KylinPrepareImpl.java | 45 ++ .../kylinolap/jdbc/KylinPrepareStatementImpl.java | 168 +++++ .../java/com/kylinolap/jdbc/KylinResultSet.java | 43 ++ .../com/kylinolap/jdbc/KylinStatementImpl.java | 52 ++ .../kylinolap/jdbc/stub/ConnectionException.java | 53 ++ .../main/java/com/kylinolap/jdbc/stub/DataSet.java | 53 ++ .../java/com/kylinolap/jdbc/stub/KylinClient.java | 376 ++++++++++ .../kylinolap/jdbc/stub/KylinColumnMetaData.java | 36 + .../java/com/kylinolap/jdbc/stub/RemoteClient.java | 57 ++ .../com/kylinolap/jdbc/stub/SQLResponseStub.java | 320 ++++++++ .../com/kylinolap/jdbc/stub/TableMetaStub.java | 329 ++++++++ .../jdbc/util/DefaultSslProtocolSocketFactory.java | 148 ++++ .../jdbc/util/DefaultX509TrustManager.java | 112 +++ .../java/com/kylinolap/jdbc/util/SQLTypeMap.java | 179 +++++ .../main/java/com/kylinolap/kylin/jdbc/Driver.java | 137 ---- .../kylinolap/kylin/jdbc/KylinConnectionImpl.java | 157 ---- .../com/kylinolap/kylin/jdbc/KylinEnumerator.java | 85 --- .../kylinolap/kylin/jdbc/KylinJdbc40Factory.java | 28 - .../kylinolap/kylin/jdbc/KylinJdbc41Factory.java | 125 ---- .../com/kylinolap/kylin/jdbc/KylinMetaImpl.java | 825 --------------------- .../com/kylinolap/kylin/jdbc/KylinPrepare.java | 96 --- .../com/kylinolap/kylin/jdbc/KylinPrepareImpl.java | 45 -- .../kylin/jdbc/KylinPrepareStatementImpl.java | 168 ----- .../com/kylinolap/kylin/jdbc/KylinResultSet.java | 43 -- .../kylinolap/kylin/jdbc/KylinStatementImpl.java | 52 -- .../kylin/jdbc/stub/ConnectionException.java | 53 -- .../com/kylinolap/kylin/jdbc/stub/DataSet.java | 53 -- .../com/kylinolap/kylin/jdbc/stub/KylinClient.java | 376 ---------- .../kylin/jdbc/stub/KylinColumnMetaData.java | 36 - .../kylinolap/kylin/jdbc/stub/RemoteClient.java | 57 -- .../kylinolap/kylin/jdbc/stub/SQLResponseStub.java | 320 -------- .../kylinolap/kylin/jdbc/stub/TableMetaStub.java | 329 -------- .../jdbc/util/DefaultSslProtocolSocketFactory.java | 148 ---- .../kylin/jdbc/util/DefaultX509TrustManager.java | 112 --- .../com/kylinolap/kylin/jdbc/util/SQLTypeMap.java | 179 ----- .../test/java/com/kylinolap/jdbc/DriverTest.java | 158 ++++ .../test/java/com/kylinolap/jdbc/DummyClient.java | 69 ++ .../test/java/com/kylinolap/jdbc/DummyDriver.java | 16 + .../com/kylinolap/jdbc/DummyJdbc41Factory.java | 19 + .../java/com/kylinolap/kylin/jdbc/DriverTest.java | 156 ---- .../java/com/kylinolap/kylin/jdbc/DummyClient.java | 67 -- .../java/com/kylinolap/kylin/jdbc/DummyDriver.java | 14 - .../kylinolap/kylin/jdbc/DummyJdbc41Factory.java | 17 - 50 files changed, 3686 insertions(+), 3678 deletions(-) create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/Driver.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinConnectionImpl.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinEnumerator.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc40Factory.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc41Factory.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinMetaImpl.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepare.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareImpl.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareStatementImpl.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinResultSet.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/KylinStatementImpl.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/ConnectionException.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/DataSet.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinClient.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinColumnMetaData.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/RemoteClient.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/SQLResponseStub.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/stub/TableMetaStub.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultSslProtocolSocketFactory.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultX509TrustManager.java create mode 100644 jdbc/src/main/java/com/kylinolap/jdbc/util/SQLTypeMap.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/Driver.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinConnectionImpl.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinEnumerator.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc40Factory.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc41Factory.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinMetaImpl.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepare.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareImpl.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareStatementImpl.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinResultSet.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinStatementImpl.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/ConnectionException.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/DataSet.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinClient.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinColumnMetaData.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/RemoteClient.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/SQLResponseStub.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/TableMetaStub.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultSslProtocolSocketFactory.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultX509TrustManager.java delete mode 100644 jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/SQLTypeMap.java create mode 100644 jdbc/src/test/java/com/kylinolap/jdbc/DriverTest.java create mode 100644 jdbc/src/test/java/com/kylinolap/jdbc/DummyClient.java create mode 100644 jdbc/src/test/java/com/kylinolap/jdbc/DummyDriver.java create mode 100644 jdbc/src/test/java/com/kylinolap/jdbc/DummyJdbc41Factory.java delete mode 100644 jdbc/src/test/java/com/kylinolap/kylin/jdbc/DriverTest.java delete mode 100644 jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyClient.java delete mode 100644 jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyDriver.java delete mode 100644 jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyJdbc41Factory.java diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/Driver.java b/jdbc/src/main/java/com/kylinolap/jdbc/Driver.java new file mode 100644 index 0000000..0f5e380 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/Driver.java @@ -0,0 +1,137 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.sql.SQLException; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.DriverVersion; +import net.hydromatic.avatica.Handler; +import net.hydromatic.avatica.HandlerImpl; +import net.hydromatic.avatica.UnregisteredDriver; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.kylinolap.jdbc.stub.ConnectionException; +import com.kylinolap.jdbc.stub.RemoteClient; + +/** + *

    + * Kylin JDBC Driver based on optiq avatica and kylin restful api.
    + * Supported versions: + *

    + *
      + *
    • jdbc 4.0
    • + *
    • jdbc 4.1
    • + *
    + * + *

    + * Supported Statements: + *

    + *
      + *
    • {@link KylinStatementImpl}
    • + *
    • {@link KylinPrepareStatementImpl}
    • + *
    + * + *

    + * Supported properties: + *

      + *
    • user: username
    • + *
    • password: password
    • + *
    • ssl: true/false
    • + *
    + *

    + * + *

    + * Driver init code sample:
    + * + *

    + * Driver driver = (Driver) Class.forName("com.kylinolap.kylin.jdbc.Driver").newInstance();
    + * Properties info = new Properties();
    + * info.put("user", "user");
    + * info.put("password", "password");
    + * info.put("ssl", true);
    + * Connection conn = driver.connect("jdbc:kylin://{domain}/{project}", info);
    + * 
    + * + *

    + * + * @author xduo + * + */ +public class Driver extends UnregisteredDriver { + private static final Logger logger = LoggerFactory.getLogger(Driver.class); + + public static final String CONNECT_STRING_PREFIX = "jdbc:kylin:"; + + @Override + protected DriverVersion createDriverVersion() { + return DriverVersion.load(Driver.class, "com-kylinolap-kylin-jdbc.properties", "Kylin JDBC Driver", "unknown version", "Kylin", "unknown version"); + } + + @Override + protected String getFactoryClassName(JdbcVersion jdbcVersion) { + switch (jdbcVersion) { + case JDBC_30: + throw new UnsupportedOperationException(); + case JDBC_40: + return "com.kylinolap.kylin.jdbc.KylinJdbc40Factory"; + case JDBC_41: + default: + return "com.kylinolap.kylin.jdbc.KylinJdbc41Factory"; + } + } + + @Override + protected Handler createHandler() { + return new HandlerImpl() { + @Override + public void onConnectionInit(AvaticaConnection connection_) throws SQLException { + KylinConnectionImpl kylinConn = (KylinConnectionImpl) connection_; + RemoteClient runner = ((KylinJdbc41Factory) factory).newRemoteClient(kylinConn); + try { + runner.connect(); + kylinConn.setMetaProject(runner.getMetadata(kylinConn.getProject())); + logger.debug("Connection inited."); + } catch (ConnectionException e) { + logger.error(e.getLocalizedMessage(), e); + throw new SQLException(e.getLocalizedMessage()); + } + } + + public void onConnectionClose(AvaticaConnection connection) { + logger.debug("Connection closed."); + } + + public void onStatementExecute(AvaticaStatement statement, ResultSink resultSink) { + logger.debug("statement executed."); + } + + public void onStatementClose(AvaticaStatement statement) { + logger.debug("statement closed."); + } + }; + } + + @Override + protected String getConnectStringPrefix() { + return CONNECT_STRING_PREFIX; + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinConnectionImpl.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinConnectionImpl.java new file mode 100644 index 0000000..2b412ed --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinConnectionImpl.java @@ -0,0 +1,157 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import javax.xml.bind.DatatypeConverter; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaFactory; +import net.hydromatic.avatica.AvaticaPreparedStatement; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.Meta; +import net.hydromatic.avatica.UnregisteredDriver; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.kylinolap.jdbc.KylinMetaImpl.MetaProject; +import com.kylinolap.jdbc.KylinPrepare.PrepareResult; + +/** + * Kylin connection implementation + * + * @author xduo + * + */ +public abstract class KylinConnectionImpl extends AvaticaConnection { + private static final Logger logger = LoggerFactory.getLogger(KylinConnectionImpl.class); + + private final String baseUrl; + private final String project; + private MetaProject metaProject; + public final List statements; + static final Trojan TROJAN = createTrojan(); + + protected KylinConnectionImpl(UnregisteredDriver driver, AvaticaFactory factory, String url, Properties info) { + super(driver, factory, url, info); + + String odbcUrl = url; + odbcUrl = odbcUrl.replace(Driver.CONNECT_STRING_PREFIX + "//", ""); + String[] temps = odbcUrl.split("/"); + + assert temps.length == 2; + + this.baseUrl = temps[0]; + this.project = temps[1]; + + logger.debug("Kylin base url " + this.baseUrl + ", project name " + this.project); + + statements = new ArrayList(); + } + + @Override + protected Meta createMeta() { + return new KylinMetaImpl(this, (KylinJdbc41Factory) factory); + } + + @Override + public AvaticaStatement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + AvaticaStatement statement = super.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + statements.add(statement); + + return statement; + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + PrepareResult pr = new KylinPrepareImpl().prepare(sql); + AvaticaPreparedStatement statement = ((KylinJdbc41Factory) factory).newPreparedStatement(this, pr, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, this.getHoldability()); + statements.add(statement); + + return statement; + } + + // ~ kylin specified implements + + public String getBasicAuthHeader() { + String username = this.info.getProperty("user"); + String password = this.info.getProperty("password"); + + return DatatypeConverter.printBase64Binary((username + ":" + password).getBytes()); + } + + public String getConnectUrl() { + boolean isSsl = Boolean.parseBoolean((this.info.getProperty("ssl", "false"))); + return (isSsl ? "https://" : "http://") + this.baseUrl + ":" + (isSsl ? 443 : 80) + "/kylin/api/user/authentication"; + } + + public String getMetaProjectUrl(String project) { + assert project != null; + boolean isSsl = Boolean.parseBoolean((this.info.getProperty("ssl", "false"))); + return (isSsl ? "https://" : "http://") + this.baseUrl + ":" + (isSsl ? 443 : 80) + "/kylin/api/tables_and_columns?project=" + project; + } + + public String getQueryUrl() { + boolean isSsl = Boolean.parseBoolean((this.info.getProperty("ssl", "false"))); + return (isSsl ? "https://" : "http://") + this.baseUrl + ":" + (isSsl ? 443 : 80) + "/kylin/api/query"; + } + + public String getProject() { + return this.project; + } + + public Meta getMeta() { + return this.meta; + } + + public AvaticaFactory getFactory() { + return this.factory; + } + + public UnregisteredDriver getDriver() { + return this.driver; + } + + public MetaProject getMetaProject() { + return metaProject; + } + + public void setMetaProject(MetaProject metaProject) { + this.metaProject = metaProject; + } + + @Override + public void close() throws SQLException { + super.close(); + + this.metaProject = null; + this.statements.clear(); + } + + @Override + public String toString() { + return "KylinConnectionImpl [baseUrl=" + baseUrl + ", project=" + project + ", metaProject=" + metaProject + "]"; + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinEnumerator.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinEnumerator.java new file mode 100644 index 0000000..8ef6f66 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinEnumerator.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.util.Collection; +import java.util.Iterator; + +import net.hydromatic.linq4j.Enumerator; + +/** + * Query results enumerator + * + * @author xduo + * + */ +public class KylinEnumerator implements Enumerator { + + /** + * current row + */ + private E current; + + /** + * data collection + */ + private Collection dataCollection; + + /** + * result iterator + */ + private Iterator cursor; + + public KylinEnumerator(Collection dataCollection) { + this.dataCollection = dataCollection; + this.cursor = this.dataCollection.iterator(); + + if (null == this.cursor) { + throw new RuntimeException("Cursor can't be null"); + } + } + + @Override + public E current() { + return current; + } + + @Override + public boolean moveNext() { + if (!cursor.hasNext()) { + this.reset(); + + return false; + } + + current = cursor.next(); + + return true; + } + + @Override + public void reset() { + this.cursor = this.dataCollection.iterator(); + } + + @Override + public void close() { + this.cursor = null; + this.dataCollection = null; + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc40Factory.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc40Factory.java new file mode 100644 index 0000000..83fcca3 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc40Factory.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +/** + * @author xduo + * + */ +public class KylinJdbc40Factory extends KylinJdbc41Factory { + + public KylinJdbc40Factory() { + super(4, 0); + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc41Factory.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc41Factory.java new file mode 100644 index 0000000..10a8e02 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinJdbc41Factory.java @@ -0,0 +1,125 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; +import java.util.Properties; +import java.util.TimeZone; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaDatabaseMetaData; +import net.hydromatic.avatica.AvaticaFactory; +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaPreparedStatement; +import net.hydromatic.avatica.AvaticaResultSet; +import net.hydromatic.avatica.AvaticaResultSetMetaData; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.avatica.UnregisteredDriver; + +import com.kylinolap.jdbc.stub.KylinClient; +import com.kylinolap.jdbc.stub.RemoteClient; + +/** + * Kylin JDBC factory. + * + * @author xduo + * + */ +public class KylinJdbc41Factory implements AvaticaFactory { + private final int major; + private final int minor; + + /** Creates a JDBC factory. */ + public KylinJdbc41Factory() { + this(4, 1); + } + + /** Creates a JDBC factory with given major/minor version number. */ + protected KylinJdbc41Factory(int major, int minor) { + this.major = major; + this.minor = minor; + } + + public int getJdbcMajorVersion() { + return major; + } + + public int getJdbcMinorVersion() { + return minor; + } + + public AvaticaConnection newConnection(UnregisteredDriver driver, AvaticaFactory factory, String url, Properties info) { + return new KylinJdbc41Connection(driver, factory, url, info); + } + + public AvaticaDatabaseMetaData newDatabaseMetaData(AvaticaConnection connection) { + return new AvaticaJdbc41DatabaseMetaData(connection); + } + + public AvaticaStatement newStatement(AvaticaConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { + return new KylinJdbc41Statement(connection, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public AvaticaPreparedStatement newPreparedStatement(AvaticaConnection connection, AvaticaPrepareResult prepareResult, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + return new KylinJdbc41PreparedStatement(connection, prepareResult, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + public AvaticaResultSet newResultSet(AvaticaStatement statement, AvaticaPrepareResult prepareResult, TimeZone timeZone) { + final ResultSetMetaData metaData = newResultSetMetaData(statement, prepareResult.getColumnList()); + return new KylinResultSet(statement, prepareResult, metaData, timeZone); + } + + public AvaticaResultSetMetaData newResultSetMetaData(AvaticaStatement statement, List columnMetaDataList) { + return new AvaticaResultSetMetaData(statement, null, columnMetaDataList); + } + + // ~ kylin sepcified + public RemoteClient newRemoteClient(KylinConnectionImpl connection) { + return new KylinClient(connection); + } + + /** Implementation of Connection for JDBC 4.1. */ + private static class KylinJdbc41Connection extends KylinConnectionImpl { + KylinJdbc41Connection(UnregisteredDriver driver, AvaticaFactory factory, String url, Properties info) { + super(driver, (KylinJdbc41Factory) factory, url, info); + } + } + + /** Implementation of Statement for JDBC 4.1. */ + public static class KylinJdbc41Statement extends KylinStatementImpl { + public KylinJdbc41Statement(AvaticaConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { + super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); + } + } + + /** Implementation of PreparedStatement for JDBC 4.1. */ + public static class KylinJdbc41PreparedStatement extends KylinPrepareStatementImpl { + KylinJdbc41PreparedStatement(AvaticaConnection connection, AvaticaPrepareResult sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + super(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability); + } + } + + /** Implementation of DatabaseMetaData for JDBC 4.1. */ + private static class AvaticaJdbc41DatabaseMetaData extends AvaticaDatabaseMetaData { + AvaticaJdbc41DatabaseMetaData(AvaticaConnection connection) { + super(connection); + } + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinMetaImpl.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinMetaImpl.java new file mode 100644 index 0000000..8be47b0 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinMetaImpl.java @@ -0,0 +1,825 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.lang.reflect.Field; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.regex.Pattern; + +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaResultSet; +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.avatica.ColumnMetaData.Rep; +import net.hydromatic.avatica.Cursor; +import net.hydromatic.avatica.Meta; +import net.hydromatic.linq4j.Enumerator; +import net.hydromatic.optiq.runtime.EnumeratorCursor; + +import org.eigenbase.sql.SqlJdbcFunctionCall; +import org.eigenbase.sql.parser.SqlParser; +import org.eigenbase.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.kylinolap.jdbc.stub.DataSet; +import com.kylinolap.jdbc.stub.KylinColumnMetaData; +import com.kylinolap.jdbc.stub.RemoteClient; +import com.kylinolap.jdbc.util.SQLTypeMap; + +/** + * Implementation of avatica interface + * + * @author xduo + */ +public class KylinMetaImpl implements Meta { + + private static final Logger logger = LoggerFactory.getLogger(KylinMetaImpl.class); + + private final KylinConnectionImpl conn; + + private final KylinJdbc41Factory factory; + + /** + * @param conn + */ + public KylinMetaImpl(KylinConnectionImpl conn, KylinJdbc41Factory factory) { + super(); + this.conn = conn; + this.factory = factory; + } + + private ResultSet mockEmptyResultSet() { + AvaticaResultSet resultSet = null; + try { + List columnMetas = new ArrayList(); + List data = new ArrayList(); + resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, new KylinEnumerator(data), ColumnMetaData.struct(columnMetas)), this.conn.getTimeZone()); + KylinConnectionImpl.TROJAN.execute(resultSet); + } catch (SQLException e) { + logger.error(e.getLocalizedMessage(), e); + } + + return resultSet; + } + + public String getSqlKeywords() { + return SqlParser.create("").getMetadata().getJdbcKeywords(); + } + + public String getNumericFunctions() { + return SqlJdbcFunctionCall.getNumericFunctions(); + } + + public String getStringFunctions() { + return SqlJdbcFunctionCall.getStringFunctions(); + } + + public String getSystemFunctions() { + return SqlJdbcFunctionCall.getSystemFunctions(); + } + + public String getTimeDateFunctions() { + return SqlJdbcFunctionCall.getTimeDateFunctions(); + } + + public ResultSet getTables(String catalog, Pat schemaPattern, Pat tableNamePattern, List typeList) { + logger.debug("Get tables with conn " + conn); + MetaProject metaProject = conn.getMetaProject(); + + if (null != metaProject) { + final DataSet tables = metaProject.getMetaTables(catalog, schemaPattern, tableNamePattern); + final NamedFieldGetter tableGetter = new NamedFieldGetter(MetaTable.class, tables.getMeta(), "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION"); + + AvaticaResultSet resultSet = null; + try { + resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, tableGetter.structType) { + @Override + public Cursor createCursor() { + return tableGetter.cursor(tables.getEnumerator()); + } + }, this.conn.getTimeZone()); + KylinConnectionImpl.TROJAN.execute(resultSet); + } catch (SQLException e) { + logger.error(e.getLocalizedMessage(), e); + } + + return resultSet; + } else { + return mockEmptyResultSet(); + } + } + + public ResultSet getColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { + logger.debug("Get columns with conn " + conn); + MetaProject metaProject = conn.getMetaProject(); + + if (null != metaProject) { + final DataSet columns = metaProject.getMetaColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); + final NamedFieldGetter columnGetter = new NamedFieldGetter(MetaColumn.class, columns.getMeta(), "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS", "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATALOG", "SCOPE_TABLE", "SOURCE_DATA_TYPE", "IS_AUTOINCREMENT", "IS_GENERATEDCOLUMN"); + + AvaticaResultSet resultSet = null; + try { + resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, columnGetter.structType) { + @Override + public Cursor createCursor() { + return columnGetter.cursor(columns.getEnumerator()); + } + }, this.conn.getTimeZone()); + + KylinConnectionImpl.TROJAN.execute(resultSet); + } catch (SQLException e) { + logger.error(e.getLocalizedMessage(), e); + } + + return resultSet; + } else { + return mockEmptyResultSet(); + } + } + + public ResultSet getSchemas(String catalog, Pat schemaPattern) { + logger.debug("Get schemas with conn " + conn); + MetaProject metaProject = conn.getMetaProject(); + + if (null != metaProject) { + final DataSet schemas = metaProject.getMetaSchemas(catalog, schemaPattern); + final NamedFieldGetter schemaGetter = new NamedFieldGetter(MetaSchema.class, schemas.getMeta(), "TABLE_SCHEM", "TABLE_CATALOG"); + + AvaticaResultSet resultSet = null; + try { + resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, schemaGetter.structType) { + @Override + public Cursor createCursor() { + return schemaGetter.cursor(schemas.getEnumerator()); + } + }, this.conn.getTimeZone()); + + KylinConnectionImpl.TROJAN.execute(resultSet); + } catch (SQLException e) { + logger.error(e.getLocalizedMessage(), e); + } + + return resultSet; + } else { + return mockEmptyResultSet(); + } + } + + public ResultSet getCatalogs() { + MetaProject metaProject = conn.getMetaProject(); + + if (null != metaProject) { + final DataSet catalogs = metaProject.getMetaCatalogs(); + final NamedFieldGetter catalogGetter = new NamedFieldGetter(MetaCatalog.class, catalogs.getMeta(), "TABLE_CATALOG"); + + AvaticaResultSet resultSet = null; + try { + resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, catalogGetter.structType) { + @Override + public Cursor createCursor() { + return catalogGetter.cursor(catalogs.getEnumerator()); + } + }, this.conn.getTimeZone()); + + KylinConnectionImpl.TROJAN.execute(resultSet); + } catch (SQLException e) { + logger.error(e.getLocalizedMessage(), e); + } + + return resultSet; + } else { + return mockEmptyResultSet(); + } + } + + public ResultSet getTableTypes() { + List tableTypeMeta = new ArrayList(); + tableTypeMeta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), false)); + List data = new ArrayList(); + Object[] row = new Object[1]; + row[0] = "TABLE"; + data.add(row); + + AvaticaResultSet resultSet = null; + try { + resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, new KylinEnumerator(data), ColumnMetaData.struct(tableTypeMeta)), this.conn.getTimeZone()); + KylinConnectionImpl.TROJAN.execute(resultSet); + } catch (SQLException e) { + logger.error(e.getLocalizedMessage(), e); + } + + return resultSet; + } + + public ResultSet getProcedures(String catalog, Pat schemaPattern, Pat procedureNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getProcedureColumns(String catalog, Pat schemaPattern, Pat procedureNamePattern, Pat columnNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getColumnPrivileges(String catalog, String schema, String table, Pat columnNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getTablePrivileges(String catalog, Pat schemaPattern, Pat tableNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) { + return mockEmptyResultSet(); + } + + public ResultSet getVersionColumns(String catalog, String schema, String table) { + return mockEmptyResultSet(); + } + + public ResultSet getPrimaryKeys(String catalog, String schema, String table) { + return mockEmptyResultSet(); + } + + public ResultSet getImportedKeys(String catalog, String schema, String table) { + return mockEmptyResultSet(); + } + + public ResultSet getExportedKeys(String catalog, String schema, String table) { + return mockEmptyResultSet(); + } + + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) { + return mockEmptyResultSet(); + } + + public ResultSet getTypeInfo() { + return mockEmptyResultSet(); + } + + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) { + return mockEmptyResultSet(); + } + + public ResultSet getUDTs(String catalog, Pat schemaPattern, Pat typeNamePattern, int[] types) { + return mockEmptyResultSet(); + } + + public ResultSet getSuperTypes(String catalog, Pat schemaPattern, Pat typeNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getSuperTables(String catalog, Pat schemaPattern, Pat tableNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getAttributes(String catalog, Pat schemaPattern, Pat typeNamePattern, Pat attributeNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getClientInfoProperties() { + return mockEmptyResultSet(); + } + + public ResultSet getFunctions(String catalog, Pat schemaPattern, Pat functionNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getFunctionColumns(String catalog, Pat schemaPattern, Pat functionNamePattern, Pat columnNamePattern) { + return mockEmptyResultSet(); + } + + public ResultSet getPseudoColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { + return mockEmptyResultSet(); + } + + public Cursor createCursor(AvaticaResultSet resultSet) { + + if (!(resultSet instanceof KylinResultSet)) + throw new IllegalStateException("resultSet is not KylinResultSet"); + + KylinPrepare.PrepareResult result = ((KylinResultSet) resultSet).getPrepareResult(); + + return result.createCursor(); + } + + /* + * Client could request metadata after prepare + * + * (non-Javadoc) + * @see net.hydromatic.avatica.Meta#prepare(net.hydromatic.avatica.AvaticaStatement, java.lang.String) + */ + public AvaticaPrepareResult prepare(AvaticaStatement statement, String sql) { + RemoteClient client = factory.newRemoteClient(conn); + DataSet result = null; + + try { + result = (DataSet) client.query(statement, sql); + } catch (Exception e) { + logger.error(e.getLocalizedMessage(), e); + throw new RuntimeException("Failed to query kylin server with exception " + e.getLocalizedMessage()); + } + + return new KylinPrepare.PrepareResult(sql, null, (Enumerator) result.getEnumerator(), ColumnMetaData.struct(result.getMeta())); + } + + /** + * Tree node used by project tree-like structure + * + * @author xduo + */ + interface Node { + /** + * Get the node name + * + * @return + */ + public String getName(); + + /** + * Get direct children of the node. + * + * @return + */ + public List getChildren(); + + /** + * Search the subtree of the node with patterns. One pattern, one level. + * + * @param patterns + * @return + */ + public List searchByPatterns(Pat... patterns); + } + + /** + * Abstract of the tree-like structure + * + * @author xduo + */ + public static abstract class AbstractNode implements Node { + + public List searchByPatterns(Pat... patterns) { + if (patterns.length == 1) { + return findChildren(patterns[0]); + } else { + List children = new ArrayList(); + + for (Node child : this.findChildren(patterns[0])) { + children.addAll(child.searchByPatterns(Arrays.copyOfRange(patterns, 1, patterns.length))); + } + + return children; + } + } + + private List findChildren(Pat pattern) { + if (null == pattern.s || pattern.s.equals("%")) { + return this.getChildren(); + } + + List list = new ArrayList(); + + for (Node c : this.getChildren()) { + if (likeToRegex(pattern).matcher(c.getName()).matches()) { + list.add(c); + } + } + + return list; + } + + ; + + /** + * Converts a LIKE-style pattern (where '%' represents a wild-card, + * escaped using '\') to a Java regex. + */ + private Pattern likeToRegex(Pat pattern) { + StringBuilder buf = new StringBuilder("^"); + char[] charArray = pattern.s.toCharArray(); + int slash = -2; + for (int i = 0; i < charArray.length; i++) { + char c = charArray[i]; + if (slash == i - 1) { + buf.append('[').append(c).append(']'); + } else { + switch (c) { + case '\\': + slash = i; + break; + case '%': + buf.append(".*"); + break; + case '[': + buf.append("\\["); + break; + case ']': + buf.append("\\]"); + break; + default: + buf.append('[').append(c).append(']'); + } + } + } + buf.append("$"); + + return Pattern.compile(buf.toString()); + } + } + + public static class MetaProject extends AbstractNode { + public final String project; + public final List catalogs; + + public MetaProject(String project, List catalogs) { + super(); + this.project = project; + this.catalogs = catalogs; + } + + public DataSet getMetaCatalogs() { + return new DataSet(MetaCatalog.meta, new KylinEnumerator(catalogs)); + } + + /** + * facade method to search schemas in current project. + * + * @param catalog + * @param schemaPattern + * @return + */ + @SuppressWarnings("unchecked") + public DataSet getMetaSchemas(String catalog, Pat schemaPattern) { + List metaSchemas = this.searchByPatterns(Pat.of(catalog), schemaPattern); + + return new DataSet(MetaSchema.meta, new KylinEnumerator((Collection) metaSchemas)); + } + + /** + * facade method to search tables in current project + * + * @param catalog + * @param schemaPattern + * @param tableNamePattern + * @return + */ + @SuppressWarnings("unchecked") + public DataSet getMetaTables(String catalog, Pat schemaPattern, Pat tableNamePattern) { + logger.debug("getMetaTables with catalog:" + catalog + ", schema:" + schemaPattern.s + ", table:" + tableNamePattern.s); + List tables = this.searchByPatterns(Pat.of(catalog), schemaPattern, tableNamePattern); + + return new DataSet(MetaTable.meta, new KylinEnumerator((Collection) tables)); + } + + /** + * facade method to search columns in current project + * + * @param catalog + * @param schemaPattern + * @param tableNamePattern + * @param columnNamePattern + * @return + */ + @SuppressWarnings("unchecked") + public DataSet getMetaColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { + logger.debug("getMetaColumns with catalog:" + catalog + ", schema:" + schemaPattern.s + ", table:" + tableNamePattern.s + ", column:" + columnNamePattern.s); + List columns = this.searchByPatterns(Pat.of(catalog), schemaPattern, tableNamePattern, columnNamePattern); + + return new DataSet(MetaColumn.meta, new KylinEnumerator((Collection) columns)); + } + + @Override + public String getName() { + return project; + } + + @Override + public List getChildren() { + return this.catalogs; + } + } + + /** + * Metadata describing a catalog. + */ + public static class MetaCatalog extends AbstractNode { + public static final List meta = new ArrayList(); + public final String tableCatalog; + public final List schemas; + + static { + meta.add(KylinColumnMetaData.dummy(0, "TABLE_CAT", "TABLE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + } + + public MetaCatalog(String tableCatalog, List schemas) { + this.tableCatalog = tableCatalog; + this.schemas = schemas; + } + + public String getName() { + return tableCatalog; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((tableCatalog == null) ? 0 : tableCatalog.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MetaCatalog other = (MetaCatalog) obj; + if (tableCatalog == null) { + if (other.tableCatalog != null) + return false; + } else if (!tableCatalog.equals(other.tableCatalog)) + return false; + return true; + } + + @Override + public List getChildren() { + return schemas; + } + + } + + /** + * Metadata describing a schema. + */ + public static class MetaSchema extends AbstractNode { + public static final List meta = new ArrayList(); + public final String tableCatalog; + public final String tableSchem; + public final List tables; + + static { + for (ColumnMetaData cmd : SQLTypeMap.schemaMetaTypeMapping.values()) { + meta.add(cmd); + } + } + + public MetaSchema(String tableCatalog, String tableSchem, List tables) { + this.tableCatalog = tableCatalog; + this.tableSchem = tableSchem; + this.tables = tables; + } + + public String getName() { + return tableSchem; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((tableCatalog == null) ? 0 : tableCatalog.hashCode()); + result = prime * result + ((tableSchem == null) ? 0 : tableSchem.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + MetaSchema other = (MetaSchema) obj; + if (tableCatalog == null) { + if (other.tableCatalog != null) + return false; + } else if (!tableCatalog.equals(other.tableCatalog)) + return false; + if (tableSchem == null) { + if (other.tableSchem != null) + return false; + } else if (!tableSchem.equals(other.tableSchem)) + return false; + return true; + } + + @Override + public List getChildren() { + return this.tables; + } + } + + /** + * Metadata describing a table type. + */ + public static class MetaTableType { + public final String tableType; + + public MetaTableType(String tableType) { + this.tableType = tableType; + } + } + + /** + * Metadata describing a table. + */ + public static class MetaTable extends AbstractNode { + public static final List meta = new ArrayList(); + public final String tableCat; + public final String tableSchem; + public final String tableName; + public final String tableType; + public final String remarks; + public final String typeCat; + public final String typeSchem; + public final String typeName; + public final String selfReferencingColName; + public final String refGeneration; + public final List columns; + + static { + for (ColumnMetaData cmd : SQLTypeMap.tableMetaTypeMapping.values()) { + meta.add(cmd); + } + } + + public MetaTable(String tableCat, String tableSchem, String tableName, String tableType, String remarks, String typeCat, String typeSchem, String typeName, String selfReferencingColName, String refGeneration, List columns) { + this.tableCat = tableCat; + this.tableSchem = tableSchem; + this.tableName = tableName; + this.tableType = tableType; + this.remarks = remarks; + this.typeCat = typeCat; + this.typeSchem = typeSchem; + this.typeName = typeName; + this.selfReferencingColName = selfReferencingColName; + this.refGeneration = refGeneration; + this.columns = columns; + } + + public String getName() { + return tableName; + } + + @Override + public List getChildren() { + return this.columns; + } + } + + /** + * Metadata describing a column. + */ + public static class MetaColumn implements Node { + public static final List meta = new ArrayList(); + public final String tableCat; + public final String tableSchem; + public final String tableName; + public final String columnName; + public final int dataType; + public final String typeName; + public final int columnSize; + public final int bufferLength; + public final int decimalDigits; + public final int numPrecRadix; + public final int nullable; + public final String remarks; + public final String columnDef; + public final int sqlDataType; + public final int sqlDatetimeSub; + public final int charOctetLength; + public final int ordinalPosition; + public final String isNullable; + public final String scopeCatalog; + public final String scopeTable; + public final int sourceDataType; + public final String isAutoincrement; + public final String isGeneratedcolumn; + + static { + for (ColumnMetaData cmd : SQLTypeMap.columnMetaTypeMapping.values()) { + meta.add(cmd); + } + } + + public MetaColumn(String tableCat, String tableSchem, String tableName, String columnName, int dataType, String typeName, int columnSize, int bufferLength, int decimalDigits, int numPrecRadix, int nullable, String remarks, String columnDef, int sqlDataType, int sqlDatetimeSub, int charOctetLength, int ordinalPosition, String isNullable, String scopeCatalog, String scopeTable, int sourceDataType, String isAutoincrement, String isGeneratedcolumn) { + super(); + this.tableCat = tableCat; + this.tableSchem = tableSchem; + this.tableName = tableName; + this.columnName = columnName; + this.dataType = dataType; + this.typeName = typeName; + this.columnSize = columnSize; + this.bufferLength = bufferLength; + this.decimalDigits = decimalDigits; + this.numPrecRadix = numPrecRadix; + this.nullable = nullable; + this.remarks = remarks; + this.columnDef = columnDef; + this.sqlDataType = sqlDataType; + this.sqlDatetimeSub = sqlDatetimeSub; + this.charOctetLength = charOctetLength; + this.ordinalPosition = ordinalPosition; + this.isNullable = isNullable; + this.scopeCatalog = scopeCatalog; + this.scopeTable = scopeTable; + this.sourceDataType = sourceDataType; + this.isAutoincrement = isAutoincrement; + this.isGeneratedcolumn = isGeneratedcolumn; + } + + public String getName() { + return columnName; + } + + @Override + public List getChildren() { + return Collections.emptyList(); + } + + @Override + public List searchByPatterns(Pat... patterns) { + return Collections.emptyList(); + } + } + + /** + * Accesses fields by name. + */ + private static class NamedFieldGetter { + private final List fields = new ArrayList(); + private final ColumnMetaData.StructType structType; + + public NamedFieldGetter(Class clazz, List columns, String... names) { + init(clazz, names, fields); + structType = ColumnMetaData.struct(columns); + } + + private void init(Class clazz, String[] names, List fields) { + for (String name : names) { + final String fieldName = Util.toCamelCase(name); + final Field field; + try { + field = clazz.getField(fieldName); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + fields.add(field); + } + } + + Object get(Object o, int columnIndex) { + try { + return fields.get(columnIndex).get(o); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + public Cursor cursor(Enumerator enumerator) { + // noinspection unchecked + return new EnumeratorCursor(enumerator) { + protected Getter createGetter(final int ordinal) { + return new Getter() { + public Object getObject() { + return get(current(), ordinal); + } + + public boolean wasNull() { + return getObject() == null; + } + }; + } + }; + } + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepare.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepare.java new file mode 100644 index 0000000..a19b1b1 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepare.java @@ -0,0 +1,96 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.util.List; + +import net.hydromatic.avatica.AvaticaParameter; +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.avatica.Cursor; +import net.hydromatic.linq4j.Enumerator; +import net.hydromatic.optiq.runtime.EnumeratorCursor; + +/** + * Interface of kylin prepare statement implementation + * + * @author xduo + * + */ +public interface KylinPrepare { + + PrepareResult prepare(String sql); + + /** + * The result of preparing a query. It gives the Avatica driver framework + * the information it needs to create a prepared statement, or to execute a + * statement directly, without an explicit prepare step. + */ + public static class PrepareResult implements AvaticaPrepareResult { + public final String sql; // for debug + public final ColumnMetaData.StructType structType; + public final Enumerator enumerator; + public final List parameterList; + + public PrepareResult(String sql, List parameterList, Enumerator enumerator, ColumnMetaData.StructType structType) { + super(); + this.sql = sql; + this.parameterList = parameterList; + this.enumerator = enumerator; + this.structType = structType; + } + + public Cursor createCursor() { + return new EnumeratorCursor(enumerator) { + @Override + protected Getter createGetter(int ordinal) { + return new ArrayEnumeratorGetter(ordinal); + } + + /** + * Row field accessor via index + */ + class ArrayEnumeratorGetter extends AbstractGetter { + protected final int field; + + public ArrayEnumeratorGetter(int field) { + this.field = field; + } + + public Object getObject() { + Object o = current()[field]; + wasNull[0] = o == null; + return o; + } + } + }; + } + + public List getColumnList() { + return structType.columns; + } + + public List getParameterList() { + return parameterList; + } + + public String getSql() { + return sql; + } + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareImpl.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareImpl.java new file mode 100644 index 0000000..3e1d5ce --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareImpl.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.util.ArrayList; +import java.util.List; + +import net.hydromatic.avatica.AvaticaParameter; +import net.hydromatic.avatica.ColumnMetaData; + +/** + * @author xduo + * + */ +public class KylinPrepareImpl implements KylinPrepare { + + @Override + public PrepareResult prepare(String sql) { + List aps = new ArrayList(); + + int startIndex = 0; + while (sql.indexOf("?", startIndex) >= 0) { + AvaticaParameter ap = new AvaticaParameter(false, 0, 0, 0, null, null, null); + aps.add(ap); + startIndex = sql.indexOf("?", startIndex) + 1; + } + + return new KylinPrepare.PrepareResult(sql, aps, null, ColumnMetaData.struct(new ArrayList())); + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareStatementImpl.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareStatementImpl.java new file mode 100644 index 0000000..648c806 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinPrepareStatementImpl.java @@ -0,0 +1,168 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.NClob; +import java.sql.ResultSet; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.util.Collections; +import java.util.List; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaPreparedStatement; +import net.hydromatic.avatica.AvaticaResultSet; + +/** + * Kylin prepare statement.
    + * Supported operations: + *
      + *
    • setString
    • + *
    • setInt
    • + *
    • setShort
    • + *
    • setLong
    • + *
    • setFloat
    • + *
    • setDouble
    • + *
    • setBoolean
    • + *
    • setByte
    • + *
    • setDate
    • + *
    • setTime
    • + *
    • setTimestamp
    • + *
    + * + * @author xduo + * + */ +public abstract class KylinPrepareStatementImpl extends AvaticaPreparedStatement { + + /** + * Before real query, + */ + protected AvaticaPrepareResult prequeryResult; + + protected KylinPrepareStatementImpl(AvaticaConnection connection, AvaticaPrepareResult prepareResult, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + super(connection, prepareResult, resultSetType, resultSetConcurrency, resultSetHoldability); + + this.prequeryResult = prepareResult; + } + + @Override + public ResultSet executeQuery() throws SQLException { + AvaticaPrepareResult queriedResult = ((KylinConnectionImpl) this.connection).getMeta().prepare(this, this.prequeryResult.getSql()); + + return executeQueryInternal(queriedResult); + } + + @Override + protected void close_() { + if (!closed) { + closed = true; + final KylinConnectionImpl connection_ = (KylinConnectionImpl) connection; + connection_.statements.remove(this); + if (openResultSet != null) { + AvaticaResultSet c = openResultSet; + openResultSet = null; + c.close(); + } + // If onStatementClose throws, this method will throw an + // exception (later + // converted to SQLException), but this statement still gets + // closed. + connection_.getDriver().handler.onStatementClose(this); + } + } + + public List getParameterValues() { + return (List) Collections.unmodifiableList(super.getParameterValues()); + } + + public void setRowId(int parameterIndex, RowId x) throws SQLException { + getParameter(parameterIndex).setRowId(x); + } + + public void setNString(int parameterIndex, String value) throws SQLException { + getParameter(parameterIndex).setNString(value); + } + + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + getParameter(parameterIndex).setNCharacterStream(value, length); + } + + public void setNClob(int parameterIndex, NClob value) throws SQLException { + getParameter(parameterIndex).setNClob(value); + } + + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + getParameter(parameterIndex).setClob(reader, length); + } + + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + getParameter(parameterIndex).setBlob(inputStream, length); + } + + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + getParameter(parameterIndex).setNClob(reader, length); + } + + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + getParameter(parameterIndex).setSQLXML(xmlObject); + } + + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + getParameter(parameterIndex).setAsciiStream(x, length); + } + + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + getParameter(parameterIndex).setBinaryStream(x, length); + } + + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + getParameter(parameterIndex).setCharacterStream(reader, length); + } + + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + getParameter(parameterIndex).setAsciiStream(x); + } + + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + getParameter(parameterIndex).setBinaryStream(x); + } + + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + getParameter(parameterIndex).setCharacterStream(reader); + } + + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + getParameter(parameterIndex).setNCharacterStream(value); + } + + public void setClob(int parameterIndex, Reader reader) throws SQLException { + getParameter(parameterIndex).setClob(reader); + } + + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + getParameter(parameterIndex).setBlob(inputStream); + } + + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + getParameter(parameterIndex).setNClob(reader); + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinResultSet.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinResultSet.java new file mode 100644 index 0000000..c73cc96 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinResultSet.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc; + +import java.sql.ResultSetMetaData; +import java.util.TimeZone; + +import net.hydromatic.avatica.AvaticaPrepareResult; +import net.hydromatic.avatica.AvaticaResultSet; +import net.hydromatic.avatica.AvaticaStatement; + +import com.kylinolap.jdbc.KylinPrepare.PrepareResult; + +/** + * Kylin query result set + * + * @author xduo + * + */ +public class KylinResultSet extends AvaticaResultSet { + + public KylinResultSet(AvaticaStatement statement, AvaticaPrepareResult prepareResult, ResultSetMetaData resultSetMetaData, TimeZone timeZone) { + super(statement, prepareResult, resultSetMetaData, timeZone); + } + + public KylinPrepare.PrepareResult getPrepareResult() { + return (PrepareResult) prepareResult; + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/KylinStatementImpl.java b/jdbc/src/main/java/com/kylinolap/jdbc/KylinStatementImpl.java new file mode 100644 index 0000000..1dcef83 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/KylinStatementImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2014 eBay Softwarimport net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaResultSet; +import net.hydromatic.avatica.AvaticaStatement; +ense. + * 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.kylinolap.jdbc; + +import net.hydromatic.avatica.AvaticaConnection; +import net.hydromatic.avatica.AvaticaResultSet; +import net.hydromatic.avatica.AvaticaStatement; + +/** + * Kylin statement implementation + * + * @author xduo + * + */ +public abstract class KylinStatementImpl extends AvaticaStatement { + + protected KylinStatementImpl(AvaticaConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { + super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); + } + + @Override + protected void close_() { + if (!closed) { + closed = true; + final KylinConnectionImpl connection_ = (KylinConnectionImpl) connection; + connection_.statements.remove(this); + if (openResultSet != null) { + AvaticaResultSet c = openResultSet; + openResultSet = null; + c.close(); + } + // If onStatementClose throws, this method will throw an exception + // (later + // converted to SQLException), but this statement still gets closed. + connection_.getDriver().handler.onStatementClose(this); + } + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/ConnectionException.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/ConnectionException.java new file mode 100644 index 0000000..bce8280 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/ConnectionException.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.stub; + +/** + * @author xduo + * + */ +public class ConnectionException extends Exception { + + private static final long serialVersionUID = 1L; + + public ConnectionException() { + super(); + } + + /** + * @param message + * @param cause + */ + public ConnectionException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + */ + public ConnectionException(String message) { + super(message); + } + + /** + * @param cause + */ + public ConnectionException(Throwable cause) { + super(cause); + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/DataSet.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/DataSet.java new file mode 100644 index 0000000..f717234 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/DataSet.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.stub; + +import java.util.List; + +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.linq4j.Enumerator; + +/** + * Data set wrapper. + * + * @author xduo + * + */ +public class DataSet { + + private final List meta; + + private final Enumerator enumerator; + + /** + * @param meta + * @param enumerator + */ + public DataSet(List meta, Enumerator enumerator) { + this.meta = meta; + this.enumerator = enumerator; + } + + public List getMeta() { + return meta; + } + + public Enumerator getEnumerator() { + return enumerator; + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinClient.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinClient.java new file mode 100644 index 0000000..0e8fbcf --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinClient.java @@ -0,0 +1,376 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.stub; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.avatica.ColumnMetaData.Rep; +import net.hydromatic.avatica.ColumnMetaData.ScalarType; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.HashMultimap; +import com.kylinolap.jdbc.KylinConnectionImpl; +import com.kylinolap.jdbc.KylinEnumerator; +import com.kylinolap.jdbc.KylinJdbc41Factory.KylinJdbc41PreparedStatement; +import com.kylinolap.jdbc.KylinMetaImpl.MetaCatalog; +import com.kylinolap.jdbc.KylinMetaImpl.MetaColumn; +import com.kylinolap.jdbc.KylinMetaImpl.MetaProject; +import com.kylinolap.jdbc.KylinMetaImpl.MetaSchema; +import com.kylinolap.jdbc.KylinMetaImpl.MetaTable; +import com.kylinolap.jdbc.stub.TableMetaStub.ColumnMetaStub; +import com.kylinolap.jdbc.util.DefaultSslProtocolSocketFactory; +import com.kylinolap.jdbc.util.SQLTypeMap; + +/** + * @author xduo + * + */ +public class KylinClient implements RemoteClient { + private static final Logger logger = LoggerFactory.getLogger(KylinClient.class); + + private final KylinConnectionImpl conn; + + public KylinClient(KylinConnectionImpl conn) { + this.conn = conn; + } + + @Override + public void connect() throws ConnectionException { + PostMethod post = new PostMethod(conn.getConnectUrl()); + HttpClient httpClient = new HttpClient(); + + if (conn.getConnectUrl().toLowerCase().startsWith("https://")) { + registerSsl(); + } + addPostHeaders(post); + + try { + StringRequestEntity requestEntity = new StringRequestEntity("{}", "application/json", "UTF-8"); + post.setRequestEntity(requestEntity); + httpClient.executeMethod(post); + + if (post.getStatusCode() != 200 && post.getStatusCode() != 201) { + logger.error("Authentication Failed with error code " + post.getStatusCode() + " and message:\n" + post.getResponseBodyAsString()); + + throw new ConnectionException("Authentication Failed."); + } + } catch (HttpException e) { + logger.error(e.getLocalizedMessage(), e); + throw new ConnectionException(e.getLocalizedMessage()); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + throw new ConnectionException(e.getLocalizedMessage()); + } + } + + @Override + public MetaProject getMetadata(String project) throws ConnectionException { + GetMethod get = new GetMethod(conn.getMetaProjectUrl(project)); + HttpClient httpClient = new HttpClient(); + + if (conn.getConnectUrl().toLowerCase().startsWith("https://")) { + registerSsl(); + } + addPostHeaders(get); + + List tableMetaStubs = null; + try { + httpClient.executeMethod(get); + + if (get.getStatusCode() != 200 && get.getStatusCode() != 201) { + logger.error("Authentication Failed with error code " + get.getStatusCode() + " and message:\n" + get.getResponseBodyAsString()); + + throw new ConnectionException("Authentication Failed."); + } + + tableMetaStubs = new ObjectMapper().readValue(get.getResponseBodyAsString(), new TypeReference>() { + }); + + List tables = new ArrayList(); + HashMultimap schemasMap = HashMultimap.create(); + + for (TableMetaStub tableMetaStub : tableMetaStubs) { + List columns = new ArrayList(); + + for (ColumnMetaStub columnMetaStub : tableMetaStub.getColumns()) { + MetaColumn column = createNewColumn(columnMetaStub); + columns.add(column); + } + + MetaTable table = createNewTable(tableMetaStub, columns); + tables.add(table); + schemasMap.put(tableMetaStub.getTABLE_CAT() + "#" + tableMetaStub.getTABLE_SCHEM(), table); + } + + HashMultimap catalogMap = HashMultimap.create(); + List schemas = new ArrayList(); + for (String key : schemasMap.keySet()) { + String cat = key.split("#")[0]; + String schema = key.split("#")[1]; + MetaSchema metaSchema = new MetaSchema(cat, schema, new ArrayList(schemasMap.get(key))); + schemas.add(metaSchema); + catalogMap.put(cat, metaSchema); + } + + List catalogs = new ArrayList(); + for (String key : catalogMap.keySet()) { + MetaCatalog metaCatalog = new MetaCatalog(key, new ArrayList(catalogMap.get(key))); + catalogs.add(metaCatalog); + } + + return new MetaProject(project, catalogs); + } catch (HttpException e) { + logger.error(e.getLocalizedMessage(), e); + throw new ConnectionException(e.getLocalizedMessage()); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + throw new ConnectionException(e.getLocalizedMessage()); + } + } + + private MetaTable createNewTable(TableMetaStub tableMetaStub, List columns) { + MetaTable table = new MetaTable(tableMetaStub.getTABLE_CAT(), tableMetaStub.getTABLE_SCHEM(), tableMetaStub.getTABLE_NAME(), tableMetaStub.getTABLE_TYPE(), tableMetaStub.getREMARKS(), tableMetaStub.getTYPE_CAT(), tableMetaStub.getTYPE_SCHEM(), tableMetaStub.getTYPE_NAME(), tableMetaStub.getSELF_REFERENCING_COL_NAME(), tableMetaStub.getREF_GENERATION(), columns); + return table; + } + + private MetaColumn createNewColumn(ColumnMetaStub columnMetaStub) { + MetaColumn column = new MetaColumn(columnMetaStub.getTABLE_CAT(), columnMetaStub.getTABLE_SCHEM(), columnMetaStub.getTABLE_NAME(), columnMetaStub.getCOLUMN_NAME(), columnMetaStub.getDATA_TYPE(), columnMetaStub.getTYPE_NAME(), columnMetaStub.getCOLUMN_SIZE(), columnMetaStub.getBUFFER_LENGTH(), columnMetaStub.getDECIMAL_DIGITS(), columnMetaStub.getNUM_PREC_RADIX(), columnMetaStub.getNULLABLE(), columnMetaStub.getREMARKS(), columnMetaStub.getCOLUMN_DEF(), columnMetaStub.getSQL_DATA_TYPE(), columnMetaStub.getSQL_DATETIME_SUB(), columnMetaStub.getCHAR_OCTET_LENGTH(), columnMetaStub.getORDINAL_POSITION(), columnMetaStub.getIS_NULLABLE(), columnMetaStub.getSCOPE_CATLOG(), columnMetaStub.getSCOPE_TABLE(), columnMetaStub.getSOURCE_DATA_TYPE(), columnMetaStub.getIS_AUTOINCREMENT(), columnMetaStub.getSCOPE_SCHEMA()); + return column; + } + + @Override + public DataSet query(AvaticaStatement statement, String sql) throws SQLException { + SQLResponseStub queryRes = null; + + List params = null; + if (statement instanceof KylinJdbc41PreparedStatement) { + params = genPrestateStates(statement); + } + + queryRes = runKylinQuery(sql, params); + + List metas = genColumnMeta(queryRes); + List data = genResultData(queryRes, metas); + + return new DataSet(metas, new KylinEnumerator(data)); + } + + /** + * @param queryRes + * @param metas + * @return + */ + private List genResultData(SQLResponseStub queryRes, List metas) { + List data = new ArrayList(); + for (String[] result : queryRes.getResults()) { + Object[] row = new Object[result.length]; + + for (int i = 0; i < result.length; i++) { + ColumnMetaData meta = metas.get(i); + row[i] = SQLTypeMap.wrapObject(result[i], meta.type.type); + } + + data.add(row); + } + return data; + } + + /** + * @param statement + * @param params + */ + private List genPrestateStates(AvaticaStatement statement) { + List params = new ArrayList(); + List values = ((KylinJdbc41PreparedStatement) statement).getParameterValues(); + + for (int i = 0; i < values.size(); i++) { + Object value = values.get(i); + params.add(new StateParam(value.getClass().getCanonicalName(), String.valueOf(value))); + } + + return params; + } + + /** + * @param queryRes + * @return + */ + private List genColumnMeta(SQLResponseStub queryRes) { + List metas = new ArrayList(); + for (int i = 0; i < queryRes.getColumnMetas().size(); i++) { + SQLResponseStub.ColumnMetaStub scm = queryRes.getColumnMetas().get(i); + ScalarType type = ColumnMetaData.scalar(scm.getColumnType(), scm.getColumnTypeName(), Rep.of(SQLTypeMap.convert(scm.getColumnType()))); + + ColumnMetaData meta = new ColumnMetaData(i, scm.isAutoIncrement(), scm.isCaseSensitive(), scm.isSearchable(), scm.isCurrency(), scm.getIsNullable(), scm.isSigned(), scm.getDisplaySize(), scm.getLabel(), scm.getName(), scm.getSchemaName(), scm.getPrecision(), scm.getScale(), scm.getTableName(), scm.getSchemaName(), type, scm.isReadOnly(), scm.isWritable(), scm.isWritable(), null); + + metas.add(meta); + } + + return metas; + } + + /** + * @param sql + * @return + * @throws IOException + */ + private SQLResponseStub runKylinQuery(String sql, List params) throws SQLException { + String url = conn.getQueryUrl(); + String project = conn.getProject(); + QueryRequest request = null; + + if (null != params) { + request = new PreQueryRequest(); + ((PreQueryRequest) request).setParams(params); + url += "/prestate"; + } else { + request = new QueryRequest(); + } + request.setSql(sql); + request.setProject(project); + + PostMethod post = new PostMethod(url); + addPostHeaders(post); + HttpClient httpClient = new HttpClient(); + if (conn.getQueryUrl().toLowerCase().startsWith("https://")) { + registerSsl(); + } + + String postBody = null; + ObjectMapper mapper = new ObjectMapper(); + try { + postBody = mapper.writeValueAsString(request); + logger.debug("Post body:\n " + postBody); + } catch (JsonProcessingException e) { + logger.error(e.getLocalizedMessage(), e); + } + String response = null; + SQLResponseStub queryRes = null; + + try { + StringRequestEntity requestEntity = new StringRequestEntity(postBody, "application/json", "UTF-8"); + post.setRequestEntity(requestEntity); + + httpClient.executeMethod(post); + response = post.getResponseBodyAsString(); + + if (post.getStatusCode() != 200 && post.getStatusCode() != 201) { + logger.error("Failed to query", response); + throw new SQLException(response); + } + + queryRes = new ObjectMapper().readValue(response, SQLResponseStub.class); + + } catch (HttpException e) { + logger.error(e.getLocalizedMessage(), e); + throw new SQLException(e.getLocalizedMessage()); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + throw new SQLException(e.getLocalizedMessage()); + } + + return queryRes; + } + + private void addPostHeaders(HttpMethodBase method) { + method.addRequestHeader("Accept", "application/json, text/plain, */*"); + method.addRequestHeader("Content-Type", "application/json"); + method.addRequestHeader("Authorization", "Basic " + conn.getBasicAuthHeader()); + } + + private void registerSsl() { + Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) new DefaultSslProtocolSocketFactory(), 443)); + } + + public class QueryRequest { + private String sql; + private String project; + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public String getProject() { + return project; + } + + public void setProject(String project) { + this.project = project; + } + } + + public class PreQueryRequest extends QueryRequest { + private List params; + + public List getParams() { + return params; + } + + public void setParams(List params) { + this.params = params; + } + } + + public class StateParam { + private String className; + private String value; + + public StateParam(String className, String value) { + super(); + this.className = className; + this.value = value; + } + + public String getClassName() { + return className; + } + + public void setClazz(String className) { + this.className = className; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinColumnMetaData.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinColumnMetaData.java new file mode 100644 index 0000000..a3d5c84 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/KylinColumnMetaData.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.stub; + +import java.sql.DatabaseMetaData; + +import net.hydromatic.avatica.ColumnMetaData; + +/** + * @author xduo + * + */ +public class KylinColumnMetaData extends ColumnMetaData { + + public KylinColumnMetaData(int ordinal, boolean autoIncrement, boolean caseSensitive, boolean searchable, boolean currency, int nullable, boolean signed, int displaySize, String label, String columnName, String schemaName, int precision, int scale, String tableName, String catalogName, AvaticaType type, boolean readOnly, boolean writable, boolean definitelyWritable, String columnClassName) { + super(ordinal, autoIncrement, caseSensitive, searchable, currency, nullable, signed, displaySize, label, columnName, schemaName, precision, scale, tableName, catalogName, type, readOnly, writable, definitelyWritable, columnClassName); + } + + public static ColumnMetaData dummy(int ordinal, String label, String columnName, AvaticaType type, boolean nullable) { + return new ColumnMetaData(ordinal, false, true, false, false, nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, true, -1, label, columnName, null, -1, -1, null, null, type, true, false, false, null); + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/RemoteClient.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/RemoteClient.java new file mode 100644 index 0000000..43ded3b --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/RemoteClient.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.stub; + +import java.sql.SQLException; + +import net.hydromatic.avatica.AvaticaStatement; + +import com.kylinolap.jdbc.KylinMetaImpl.MetaProject; + +/** + * Remote query stub of kylin restful service + * + * @author xduo + * + */ +public interface RemoteClient { + + /** + * Connect to kylin restful service. ConnectionException will be thrown if + * authentication failed. + * + * @throws ConnectionException + */ + public void connect() throws ConnectionException; + + /** + * @param project + * @return + */ + public MetaProject getMetadata(String project) throws ConnectionException; + + /** + * Run query + * + * @param statement + * @param sql + * @return + * @throws SQLException + */ + public DataSet query(AvaticaStatement statement, String sql) throws SQLException; + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/SQLResponseStub.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/SQLResponseStub.java new file mode 100644 index 0000000..d980d8d --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/SQLResponseStub.java @@ -0,0 +1,320 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.stub; + +import java.io.Serializable; +import java.util.List; + +/** + * @author xduo + * + */ +public class SQLResponseStub implements Serializable { + private static final long serialVersionUID = 1L; + + // private static final Logger logger = + // LoggerFactory.getLogger(SQLResponse.class); + + // the data type for each column + private List columnMetas; + + // the results rows, each row contains several columns + private List results; + + private String cube; + + // if not select query, only return affected row count + private int affectedRowCount; + + // if isException, the detailed exception message + private String exceptionMessage; + + private boolean isException; + + private long duration; + + private boolean isPartial = false; + + private long totalScanCount; + + private boolean hitCache = false; + + public SQLResponseStub() { + } + + public List getColumnMetas() { + return columnMetas; + } + + public void setColumnMetas(List columnMetas) { + this.columnMetas = columnMetas; + } + + public List getResults() { + return results; + } + + public void setResults(List results) { + this.results = results; + } + + public String getCube() { + return cube; + } + + public void setCube(String cube) { + this.cube = cube; + } + + public int getAffectedRowCount() { + return affectedRowCount; + } + + public void setAffectedRowCount(int affectedRowCount) { + this.affectedRowCount = affectedRowCount; + } + + public boolean getIsException() { + return isException; + } + + public void setIsException(boolean isException) { + this.isException = isException; + } + + public String getExceptionMessage() { + return exceptionMessage; + } + + public void setExceptionMessage(String exceptionMessage) { + this.exceptionMessage = exceptionMessage; + } + + public long getDuration() { + return duration; + } + + public void setDuration(long duration) { + this.duration = duration; + } + + public boolean isPartial() { + return isPartial; + } + + public void setPartial(boolean isPartial) { + this.isPartial = isPartial; + } + + public long getTotalScanCount() { + return totalScanCount; + } + + public void setTotalScanCount(long totalScanCount) { + this.totalScanCount = totalScanCount; + } + + public boolean isHitCache() { + return hitCache; + } + + public void setHitCache(boolean hitCache) { + this.hitCache = hitCache; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + + public static class ColumnMetaStub { + + private boolean isAutoIncrement; + private boolean isCaseSensitive; + private boolean isSearchable; + private boolean isCurrency; + private int isNullable;// 0:nonull, 1:nullable, 2: nullableunknown + private boolean isSigned; + private int displaySize; + private String label;// AS keyword + private String name; + private String schemaName; + private String catelogName; + private String tableName; + private int precision; + private int scale; + private int columnType;// as defined in java.sql.Types + private String columnTypeName; + private boolean isReadOnly; + private boolean isWritable; + private boolean isDefinitelyWritable; + + public ColumnMetaStub() { + } + + public boolean isAutoIncrement() { + return isAutoIncrement; + } + + public void setAutoIncrement(boolean isAutoIncrement) { + this.isAutoIncrement = isAutoIncrement; + } + + public boolean isCaseSensitive() { + return isCaseSensitive; + } + + public void setCaseSensitive(boolean isCaseSensitive) { + this.isCaseSensitive = isCaseSensitive; + } + + public boolean isSearchable() { + return isSearchable; + } + + public void setSearchable(boolean isSearchable) { + this.isSearchable = isSearchable; + } + + public boolean isCurrency() { + return isCurrency; + } + + public void setCurrency(boolean isCurrency) { + this.isCurrency = isCurrency; + } + + public int getIsNullable() { + return isNullable; + } + + public void setIsNullable(int isNullable) { + this.isNullable = isNullable; + } + + public boolean isSigned() { + return isSigned; + } + + public void setSigned(boolean isSigned) { + this.isSigned = isSigned; + } + + public int getDisplaySize() { + return displaySize; + } + + public void setDisplaySize(int displaySize) { + this.displaySize = displaySize; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSchemaName() { + return schemaName; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + public String getCatelogName() { + return catelogName; + } + + public void setCatelogName(String catelogName) { + this.catelogName = catelogName; + } + + public String getTableName() { + return tableName; + } + + public void setTableName(String tableName) { + this.tableName = tableName; + } + + public int getPrecision() { + return precision; + } + + public void setPrecision(int precision) { + this.precision = precision; + } + + public int getScale() { + return scale; + } + + public void setScale(int scale) { + this.scale = scale; + } + + public int getColumnType() { + return columnType; + } + + public void setColumnType(int columnType) { + this.columnType = columnType; + } + + public String getColumnTypeName() { + return columnTypeName; + } + + public void setColumnTypeName(String columnTypeName) { + this.columnTypeName = columnTypeName; + } + + public boolean isReadOnly() { + return isReadOnly; + } + + public void setReadOnly(boolean isReadOnly) { + this.isReadOnly = isReadOnly; + } + + public boolean isWritable() { + return isWritable; + } + + public void setWritable(boolean isWritable) { + this.isWritable = isWritable; + } + + public boolean isDefinitelyWritable() { + return isDefinitelyWritable; + } + + public void setDefinitelyWritable(boolean isDefinitelyWritable) { + this.isDefinitelyWritable = isDefinitelyWritable; + } + + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/stub/TableMetaStub.java b/jdbc/src/main/java/com/kylinolap/jdbc/stub/TableMetaStub.java new file mode 100644 index 0000000..88290b4 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/stub/TableMetaStub.java @@ -0,0 +1,329 @@ +package com.kylinolap.jdbc.stub; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @author xduo + * + */ +public class TableMetaStub { + + private static final long serialVersionUID = 1L; + private String TABLE_CAT; + private String TABLE_SCHEM; + private String TABLE_NAME; + private String TABLE_TYPE; + private String REMARKS; + private String TYPE_CAT; + private String TYPE_SCHEM; + private String TYPE_NAME; + private String SELF_REFERENCING_COL_NAME; + private String REF_GENERATION; + @JsonProperty("columns") + private List columns = new ArrayList(); + + public String getTABLE_CAT() { + return TABLE_CAT; + } + + public void setTABLE_CAT(String tABLE_CAT) { + TABLE_CAT = tABLE_CAT; + } + + public String getTABLE_SCHEM() { + return TABLE_SCHEM; + } + + public void setTABLE_SCHEM(String tABLE_SCHEM) { + TABLE_SCHEM = tABLE_SCHEM; + } + + public String getTABLE_NAME() { + return TABLE_NAME; + } + + public void setTABLE_NAME(String tABLE_NAME) { + TABLE_NAME = tABLE_NAME; + } + + public String getTABLE_TYPE() { + return TABLE_TYPE; + } + + public void setTABLE_TYPE(String tABLE_TYPE) { + TABLE_TYPE = tABLE_TYPE; + } + + public String getREMARKS() { + return REMARKS; + } + + public void setREMARKS(String rEMARKS) { + REMARKS = rEMARKS; + } + + public String getTYPE_CAT() { + return TYPE_CAT; + } + + public void setTYPE_CAT(String tYPE_CAT) { + TYPE_CAT = tYPE_CAT; + } + + public String getTYPE_SCHEM() { + return TYPE_SCHEM; + } + + public void setTYPE_SCHEM(String tYPE_SCHEM) { + TYPE_SCHEM = tYPE_SCHEM; + } + + public String getTYPE_NAME() { + return TYPE_NAME; + } + + public void setTYPE_NAME(String tYPE_NAME) { + TYPE_NAME = tYPE_NAME; + } + + public String getSELF_REFERENCING_COL_NAME() { + return SELF_REFERENCING_COL_NAME; + } + + public void setSELF_REFERENCING_COL_NAME(String sELF_REFERENCING_COL_NAME) { + SELF_REFERENCING_COL_NAME = sELF_REFERENCING_COL_NAME; + } + + public String getREF_GENERATION() { + return REF_GENERATION; + } + + public void setREF_GENERATION(String rEF_GENERATION) { + REF_GENERATION = rEF_GENERATION; + } + + public List getColumns() { + return columns; + } + + public void setColumns(List columns) { + this.columns = columns; + } + + public static long getSerialversionuid() { + return serialVersionUID; + } + + public static class ColumnMetaStub { + private String TABLE_CAT; + private String TABLE_SCHEM; + private String TABLE_NAME; + private String COLUMN_NAME; + private int DATA_TYPE; + private String TYPE_NAME; + private int COLUMN_SIZE; + private int BUFFER_LENGTH; + private int DECIMAL_DIGITS; + private int NUM_PREC_RADIX; + private int NULLABLE; + private String REMARKS; + private String COLUMN_DEF; + private int SQL_DATA_TYPE; + private int SQL_DATETIME_SUB; + private int CHAR_OCTET_LENGTH; + private int ORDINAL_POSITION; + private String IS_NULLABLE; + private String SCOPE_CATLOG; + private String SCOPE_SCHEMA; + private String SCOPE_TABLE; + private short SOURCE_DATA_TYPE; + private String IS_AUTOINCREMENT; + + public String getTABLE_CAT() { + return TABLE_CAT; + } + + public void setTABLE_CAT(String tABLE_CAT) { + TABLE_CAT = tABLE_CAT; + } + + public String getTABLE_SCHEM() { + return TABLE_SCHEM; + } + + public void setTABLE_SCHEM(String tABLE_SCHEM) { + TABLE_SCHEM = tABLE_SCHEM; + } + + public String getTABLE_NAME() { + return TABLE_NAME; + } + + public void setTABLE_NAME(String tABLE_NAME) { + TABLE_NAME = tABLE_NAME; + } + + public String getCOLUMN_NAME() { + return COLUMN_NAME; + } + + public void setCOLUMN_NAME(String cOLUMN_NAME) { + COLUMN_NAME = cOLUMN_NAME; + } + + public int getDATA_TYPE() { + return DATA_TYPE; + } + + public void setDATA_TYPE(int dATA_TYPE) { + DATA_TYPE = dATA_TYPE; + } + + public String getTYPE_NAME() { + return TYPE_NAME; + } + + public void setTYPE_NAME(String tYPE_NAME) { + TYPE_NAME = tYPE_NAME; + } + + public int getCOLUMN_SIZE() { + return COLUMN_SIZE; + } + + public void setCOLUMN_SIZE(int cOLUMN_SIZE) { + COLUMN_SIZE = cOLUMN_SIZE; + } + + public int getBUFFER_LENGTH() { + return BUFFER_LENGTH; + } + + public void setBUFFER_LENGTH(int bUFFER_LENGTH) { + BUFFER_LENGTH = bUFFER_LENGTH; + } + + public int getDECIMAL_DIGITS() { + return DECIMAL_DIGITS; + } + + public void setDECIMAL_DIGITS(int dECIMAL_DIGITS) { + DECIMAL_DIGITS = dECIMAL_DIGITS; + } + + public int getNUM_PREC_RADIX() { + return NUM_PREC_RADIX; + } + + public void setNUM_PREC_RADIX(int nUM_PREC_RADIX) { + NUM_PREC_RADIX = nUM_PREC_RADIX; + } + + public int getNULLABLE() { + return NULLABLE; + } + + public void setNULLABLE(int nULLABLE) { + NULLABLE = nULLABLE; + } + + public String getREMARKS() { + return REMARKS; + } + + public void setREMARKS(String rEMARKS) { + REMARKS = rEMARKS; + } + + public String getCOLUMN_DEF() { + return COLUMN_DEF; + } + + public void setCOLUMN_DEF(String cOLUMN_DEF) { + COLUMN_DEF = cOLUMN_DEF; + } + + public int getSQL_DATA_TYPE() { + return SQL_DATA_TYPE; + } + + public void setSQL_DATA_TYPE(int sQL_DATA_TYPE) { + SQL_DATA_TYPE = sQL_DATA_TYPE; + } + + public int getSQL_DATETIME_SUB() { + return SQL_DATETIME_SUB; + } + + public void setSQL_DATETIME_SUB(int sQL_DATETIME_SUB) { + SQL_DATETIME_SUB = sQL_DATETIME_SUB; + } + + public int getCHAR_OCTET_LENGTH() { + return CHAR_OCTET_LENGTH; + } + + public void setCHAR_OCTET_LENGTH(int cHAR_OCTET_LENGTH) { + CHAR_OCTET_LENGTH = cHAR_OCTET_LENGTH; + } + + public int getORDINAL_POSITION() { + return ORDINAL_POSITION; + } + + public void setORDINAL_POSITION(int oRDINAL_POSITION) { + ORDINAL_POSITION = oRDINAL_POSITION; + } + + public String getIS_NULLABLE() { + return IS_NULLABLE; + } + + public void setIS_NULLABLE(String iS_NULLABLE) { + IS_NULLABLE = iS_NULLABLE; + } + + public String getSCOPE_CATLOG() { + return SCOPE_CATLOG; + } + + public void setSCOPE_CATLOG(String sCOPE_CATLOG) { + SCOPE_CATLOG = sCOPE_CATLOG; + } + + public String getSCOPE_SCHEMA() { + return SCOPE_SCHEMA; + } + + public void setSCOPE_SCHEMA(String sCOPE_SCHEMA) { + SCOPE_SCHEMA = sCOPE_SCHEMA; + } + + public String getSCOPE_TABLE() { + return SCOPE_TABLE; + } + + public void setSCOPE_TABLE(String sCOPE_TABLE) { + SCOPE_TABLE = sCOPE_TABLE; + } + + public short getSOURCE_DATA_TYPE() { + return SOURCE_DATA_TYPE; + } + + public void setSOURCE_DATA_TYPE(short sOURCE_DATA_TYPE) { + SOURCE_DATA_TYPE = sOURCE_DATA_TYPE; + } + + public String getIS_AUTOINCREMENT() { + return IS_AUTOINCREMENT; + } + + public void setIS_AUTOINCREMENT(String iS_AUTOINCREMENT) { + this.IS_AUTOINCREMENT = iS_AUTOINCREMENT; + } + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultSslProtocolSocketFactory.java b/jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultSslProtocolSocketFactory.java new file mode 100644 index 0000000..a9fb61b --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultSslProtocolSocketFactory.java @@ -0,0 +1,148 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.util; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.HttpClientError; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author xduo + * + */ +public class DefaultSslProtocolSocketFactory implements SecureProtocolSocketFactory { + /** Log object for this class. */ + private static Logger LOG = LoggerFactory.getLogger(DefaultSslProtocolSocketFactory.class); + private SSLContext sslcontext = null; + + /** + * Constructor for DefaultSslProtocolSocketFactory. + */ + public DefaultSslProtocolSocketFactory() { + super(); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort); + } + + /** + * Attempts to get a new socket connection to the given host within the + * given time limit. + * + *

    + * To circumvent the limitations of older JREs that do not support connect + * timeout a controller thread is executed. The controller thread attempts + * to create a new socket within the given limit of time. If socket + * constructor does not return until the timeout expires, the controller + * terminates and throws an {@link ConnectTimeoutException} + *

    + * + * @param host + * the host name/IP + * @param port + * the port on the host + * @param localAddress + * the local host name/IP to bind the socket to + * @param localPort + * the port on the local machine + * @param params + * {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException + * if an I/O error occurs while creating the socket + * @throws UnknownHostException + * if the IP address of the host cannot be determined + * @throws ConnectTimeoutException + * DOCUMENT ME! + * @throws IllegalArgumentException + * DOCUMENT ME! + */ + public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + + int timeout = params.getConnectionTimeout(); + + if (timeout == 0) { + return createSocket(host, port, localAddress, localPort); + } else { + // To be eventually deprecated when migrated to Java 1.4 or above + return ControllerThreadSocketFactory.createSocket(this, host, port, localAddress, localPort, timeout); + } + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket(host, port); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose); + } + + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(DefaultX509TrustManager.class)); + } + + public int hashCode() { + return DefaultX509TrustManager.class.hashCode(); + } + + private static SSLContext createEasySSLContext() { + try { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, new TrustManager[] { new DefaultX509TrustManager(null) }, null); + + return context; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new HttpClientError(e.toString()); + } + } + + private SSLContext getSSLContext() { + if (this.sslcontext == null) { + this.sslcontext = createEasySSLContext(); + } + + return this.sslcontext; + } +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultX509TrustManager.java b/jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultX509TrustManager.java new file mode 100644 index 0000000..89b8f23 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/util/DefaultX509TrustManager.java @@ -0,0 +1,112 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.util; + +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author xduo + * + */ +public class DefaultX509TrustManager implements X509TrustManager { + + /** Log object for this class. */ + private static Logger LOG = LoggerFactory.getLogger(DefaultX509TrustManager.class); + private X509TrustManager standardTrustManager = null; + + /** + * Constructor for DefaultX509TrustManager. + * + */ + public DefaultX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { + super(); + + TrustManagerFactory factory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + factory.init(keystore); + + TrustManager[] trustmanagers = factory.getTrustManagers(); + + if (trustmanagers.length == 0) { + throw new NoSuchAlgorithmException("SunX509 trust manager not supported"); + } + + this.standardTrustManager = (X509TrustManager) trustmanagers[0]; + } + + public X509Certificate[] getAcceptedIssuers() { + return this.standardTrustManager.getAcceptedIssuers(); + } + + public boolean isClientTrusted(X509Certificate[] certificates) { + return true; + // return this.standardTrustManager.isClientTrusted(certificates); + } + + public boolean isServerTrusted(X509Certificate[] certificates) { + if ((certificates != null) && LOG.isDebugEnabled()) { + LOG.debug("Server certificate chain:"); + + for (int i = 0; i < certificates.length; i++) { + if (LOG.isDebugEnabled()) { + LOG.debug("X509Certificate[" + i + "]=" + certificates[i]); + } + } + } + + if ((certificates != null) && (certificates.length == 1)) { + X509Certificate certificate = certificates[0]; + + try { + certificate.checkValidity(); + } catch (CertificateException e) { + LOG.error(e.toString()); + + return false; + } + + return true; + } else { + return true; + // return this.standardTrustManager.isServerTrusted(certificates); + } + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // TODO Auto-generated method stub + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + // TODO Auto-generated method stub + + } + +} diff --git a/jdbc/src/main/java/com/kylinolap/jdbc/util/SQLTypeMap.java b/jdbc/src/main/java/com/kylinolap/jdbc/util/SQLTypeMap.java new file mode 100644 index 0000000..12eff56 --- /dev/null +++ b/jdbc/src/main/java/com/kylinolap/jdbc/util/SQLTypeMap.java @@ -0,0 +1,179 @@ +/* + * Copyright 2013-2014 eBay Software Foundation + * + * Licensed 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.kylinolap.jdbc.util; + +import java.math.BigDecimal; +import java.sql.Date; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.HashMap; +import java.util.Map; + +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.avatica.ColumnMetaData.Rep; + +import com.kylinolap.jdbc.stub.KylinColumnMetaData; + +/** + * Util class to handle type gap between sql types and java types. + * + * @author xduo + * + */ +public class SQLTypeMap { + + public final static Map schemaMetaTypeMapping = new HashMap(); + + public final static Map columnMetaTypeMapping = new HashMap(); + + public final static Map tableMetaTypeMapping = new HashMap(); + + static { + schemaMetaTypeMapping.put("TABLE_CAT", KylinColumnMetaData.dummy(0, "TABLE_SCHEM", "TABLE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + schemaMetaTypeMapping.put("TABLE_SCHEM", KylinColumnMetaData.dummy(1, "TABLE_CATALOG", "TABLE_CATALOG", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + + tableMetaTypeMapping.put("TABLE_CAT", KylinColumnMetaData.dummy(0, "TABLE_CAT", "TABLE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("TABLE_SCHEM", KylinColumnMetaData.dummy(1, "TABLE_SCHEM", "TABLE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("TABLE_NAME", KylinColumnMetaData.dummy(2, "TABLE_NAME", "TABLE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("TABLE_TYPE", KylinColumnMetaData.dummy(3, "TABLE_TYPE", "TABLE_TYPE", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("REMARKS", KylinColumnMetaData.dummy(4, "REMARKS", "REMARKS", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("TYPE_CAT", KylinColumnMetaData.dummy(5, "TYPE_CAT", "TYPE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("TYPE_SCHEM", KylinColumnMetaData.dummy(6, "TYPE_SCHEM", "TYPE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("TYPE_NAME", KylinColumnMetaData.dummy(7, "TYPE_NAME", "TYPE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("SELF_REFERENCING_COL_NAME", KylinColumnMetaData.dummy(8, "SELF_REFERENCING_COL_NAME", "SELF_REFERENCING_COL_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + tableMetaTypeMapping.put("REF_GENERATION", KylinColumnMetaData.dummy(9, "REF_GENERATION", "REF_GENERATION", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + + columnMetaTypeMapping.put("TABLE_CAT", KylinColumnMetaData.dummy(0, "TABLE_CAT", "TABLE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("TABLE_SCHEM", KylinColumnMetaData.dummy(1, "TABLE_SCHEM", "TABLE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("TABLE_NAME", KylinColumnMetaData.dummy(2, "TABLE_NAME", "TABLE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("COLUMN_NAME", KylinColumnMetaData.dummy(3, "COLUMN_NAME", "COLUMN_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("DATA_TYPE", KylinColumnMetaData.dummy(4, "DATA_TYPE", "DATA_TYPE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("TYPE_NAME", KylinColumnMetaData.dummy(5, "TYPE_NAME", "TYPE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("COLUMN_SIZE", KylinColumnMetaData.dummy(6, "COLUMN_SIZE", "COLUMN_SIZE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("BUFFER_LENGTH", KylinColumnMetaData.dummy(7, "BUFFER_LENGTH", "BUFFER_LENGTH", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("DECIMAL_DIGITS", KylinColumnMetaData.dummy(8, "DECIMAL_DIGITS", "DECIMAL_DIGITS", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("NUM_PREC_RADIX", KylinColumnMetaData.dummy(9, "NUM_PREC_RADIX", "NUM_PREC_RADIX", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("NULLABLE", KylinColumnMetaData.dummy(10, "NULLABLE", "NULLABLE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("REMARKS", KylinColumnMetaData.dummy(11, "REMARKS", "REMARKS", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("COLUMN_DEF", KylinColumnMetaData.dummy(12, "COLUMN_DEF", "COLUMN_DEF", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("SQL_DATA_TYPE", KylinColumnMetaData.dummy(13, "SQL_DATA_TYPE", "SQL_DATA_TYPE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("SQL_DATETIME_SUB", KylinColumnMetaData.dummy(14, "SQL_DATETIME_SUB", "SQL_DATETIME_SUB", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("CHAR_OCTET_LENGTH", KylinColumnMetaData.dummy(15, "CHAR_OCTET_LENGTH", "CHAR_OCTET_LENGTH", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("ORDINAL_POSITION", KylinColumnMetaData.dummy(16, "ORDINAL_POSITION", "ORDINAL_POSITION", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("IS_NULLABLE", KylinColumnMetaData.dummy(17, "IS_NULLABLE", "IS_NULLABLE", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("SCOPE_CATALOG", KylinColumnMetaData.dummy(18, "SCOPE_CATALOG", "SCOPE_CATALOG", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("SCOPE_TABLE", KylinColumnMetaData.dummy(19, "SCOPE_TABLE", "SCOPE_TABLE", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("SOURCE_DATA_TYPE", KylinColumnMetaData.dummy(20, "SOURCE_DATA_TYPE", "SOURCE_DATA_TYPE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); + columnMetaTypeMapping.put("IS_AUTOINCREMENT", KylinColumnMetaData.dummy(21, "IS_AUTOINCREMENT", "IS_AUTOINCREMENT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + columnMetaTypeMapping.put("IS_GENERATEDCOLUMN", KylinColumnMetaData.dummy(22, "IS_GENERATEDCOLUMN", "IS_GENERATEDCOLUMN", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + } + + @SuppressWarnings("rawtypes") + public static Class convert(int sqlType) { + Class result = Object.class; + + switch (sqlType) { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + result = String.class; + break; + case Types.NUMERIC: + case Types.DECIMAL: + result = BigDecimal.class; + break; + case Types.BIT: + result = Boolean.class; + break; + case Types.TINYINT: + result = Byte.class; + break; + case Types.SMALLINT: + result = Short.class; + break; + case Types.INTEGER: + result = Integer.class; + break; + case Types.BIGINT: + result = Long.class; + break; + case Types.REAL: + case Types.FLOAT: + case Types.DOUBLE: + result = Double.class; + break; + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + result = Byte[].class; + break; + case Types.DATE: + result = Date.class; + break; + case Types.TIME: + result = Time.class; + break; + case Types.TIMESTAMP: + result = Timestamp.class; + break; + } + + return result; + } + + public static Object wrapObject(String value, int sqlType) { + if (null == value) { + return null; + } + + switch (sqlType) { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + return value; + case Types.NUMERIC: + case Types.DECIMAL: + return new BigDecimal(value); + case Types.BIT: + return Boolean.parseBoolean(value); + case Types.TINYINT: + return Byte.valueOf(value); + case Types.SMALLINT: + return Short.valueOf(value); + case Types.INTEGER: + return Integer.parseInt(value); + case Types.BIGINT: + case Types.REAL: + case Types.FLOAT: + case Types.DOUBLE: + return Long.parseLong(value); + case Types.BINARY: + case Types.VARBINARY: + case Types.LONGVARBINARY: + return value.getBytes(); + case Types.DATE: + return Date.valueOf(value); + case Types.TIME: + return Time.valueOf(value); + case Types.TIMESTAMP: + return Timestamp.valueOf(value); + } + + return value; + } +} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/Driver.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/Driver.java deleted file mode 100644 index 0430ade..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/Driver.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.sql.SQLException; - -import net.hydromatic.avatica.AvaticaConnection; -import net.hydromatic.avatica.AvaticaStatement; -import net.hydromatic.avatica.DriverVersion; -import net.hydromatic.avatica.Handler; -import net.hydromatic.avatica.HandlerImpl; -import net.hydromatic.avatica.UnregisteredDriver; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.kylinolap.kylin.jdbc.stub.ConnectionException; -import com.kylinolap.kylin.jdbc.stub.RemoteClient; - -/** - *

    - * Kylin JDBC Driver based on optiq avatica and kylin restful api.
    - * Supported versions: - *

    - *
      - *
    • jdbc 4.0
    • - *
    • jdbc 4.1
    • - *
    - * - *

    - * Supported Statements: - *

    - *
      - *
    • {@link KylinStatementImpl}
    • - *
    • {@link KylinPrepareStatementImpl}
    • - *
    - * - *

    - * Supported properties: - *

      - *
    • user: username
    • - *
    • password: password
    • - *
    • ssl: true/false
    • - *
    - *

    - * - *

    - * Driver init code sample:
    - * - *

    - * Driver driver = (Driver) Class.forName("com.kylinolap.kylin.jdbc.Driver").newInstance();
    - * Properties info = new Properties();
    - * info.put("user", "user");
    - * info.put("password", "password");
    - * info.put("ssl", true);
    - * Connection conn = driver.connect("jdbc:kylin://{domain}/{project}", info);
    - * 
    - * - *

    - * - * @author xduo - * - */ -public class Driver extends UnregisteredDriver { - private static final Logger logger = LoggerFactory.getLogger(Driver.class); - - public static final String CONNECT_STRING_PREFIX = "jdbc:kylin:"; - - @Override - protected DriverVersion createDriverVersion() { - return DriverVersion.load(Driver.class, "com-kylinolap-kylin-jdbc.properties", "Kylin JDBC Driver", "unknown version", "Kylin", "unknown version"); - } - - @Override - protected String getFactoryClassName(JdbcVersion jdbcVersion) { - switch (jdbcVersion) { - case JDBC_30: - throw new UnsupportedOperationException(); - case JDBC_40: - return "com.kylinolap.kylin.jdbc.KylinJdbc40Factory"; - case JDBC_41: - default: - return "com.kylinolap.kylin.jdbc.KylinJdbc41Factory"; - } - } - - @Override - protected Handler createHandler() { - return new HandlerImpl() { - @Override - public void onConnectionInit(AvaticaConnection connection_) throws SQLException { - KylinConnectionImpl kylinConn = (KylinConnectionImpl) connection_; - RemoteClient runner = ((KylinJdbc41Factory) factory).newRemoteClient(kylinConn); - try { - runner.connect(); - kylinConn.setMetaProject(runner.getMetadata(kylinConn.getProject())); - logger.debug("Connection inited."); - } catch (ConnectionException e) { - logger.error(e.getLocalizedMessage(), e); - throw new SQLException(e.getLocalizedMessage()); - } - } - - public void onConnectionClose(AvaticaConnection connection) { - logger.debug("Connection closed."); - } - - public void onStatementExecute(AvaticaStatement statement, ResultSink resultSink) { - logger.debug("statement executed."); - } - - public void onStatementClose(AvaticaStatement statement) { - logger.debug("statement closed."); - } - }; - } - - @Override - protected String getConnectStringPrefix() { - return CONNECT_STRING_PREFIX; - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinConnectionImpl.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinConnectionImpl.java deleted file mode 100644 index 480a8dc..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinConnectionImpl.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import javax.xml.bind.DatatypeConverter; - -import net.hydromatic.avatica.AvaticaConnection; -import net.hydromatic.avatica.AvaticaFactory; -import net.hydromatic.avatica.AvaticaPreparedStatement; -import net.hydromatic.avatica.AvaticaStatement; -import net.hydromatic.avatica.Meta; -import net.hydromatic.avatica.UnregisteredDriver; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaProject; -import com.kylinolap.kylin.jdbc.KylinPrepare.PrepareResult; - -/** - * Kylin connection implementation - * - * @author xduo - * - */ -public abstract class KylinConnectionImpl extends AvaticaConnection { - private static final Logger logger = LoggerFactory.getLogger(KylinConnectionImpl.class); - - private final String baseUrl; - private final String project; - private MetaProject metaProject; - public final List statements; - static final Trojan TROJAN = createTrojan(); - - protected KylinConnectionImpl(UnregisteredDriver driver, AvaticaFactory factory, String url, Properties info) { - super(driver, factory, url, info); - - String odbcUrl = url; - odbcUrl = odbcUrl.replace(Driver.CONNECT_STRING_PREFIX + "//", ""); - String[] temps = odbcUrl.split("/"); - - assert temps.length == 2; - - this.baseUrl = temps[0]; - this.project = temps[1]; - - logger.debug("Kylin base url " + this.baseUrl + ", project name " + this.project); - - statements = new ArrayList(); - } - - @Override - protected Meta createMeta() { - return new KylinMetaImpl(this, (KylinJdbc41Factory) factory); - } - - @Override - public AvaticaStatement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - AvaticaStatement statement = super.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); - statements.add(statement); - - return statement; - } - - @Override - public PreparedStatement prepareStatement(String sql) throws SQLException { - PrepareResult pr = new KylinPrepareImpl().prepare(sql); - AvaticaPreparedStatement statement = ((KylinJdbc41Factory) factory).newPreparedStatement(this, pr, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, this.getHoldability()); - statements.add(statement); - - return statement; - } - - // ~ kylin specified implements - - public String getBasicAuthHeader() { - String username = this.info.getProperty("user"); - String password = this.info.getProperty("password"); - - return DatatypeConverter.printBase64Binary((username + ":" + password).getBytes()); - } - - public String getConnectUrl() { - boolean isSsl = Boolean.parseBoolean((this.info.getProperty("ssl", "false"))); - return (isSsl ? "https://" : "http://") + this.baseUrl + ":" + (isSsl ? 443 : 80) + "/kylin/api/user/authentication"; - } - - public String getMetaProjectUrl(String project) { - assert project != null; - boolean isSsl = Boolean.parseBoolean((this.info.getProperty("ssl", "false"))); - return (isSsl ? "https://" : "http://") + this.baseUrl + ":" + (isSsl ? 443 : 80) + "/kylin/api/tables_and_columns?project=" + project; - } - - public String getQueryUrl() { - boolean isSsl = Boolean.parseBoolean((this.info.getProperty("ssl", "false"))); - return (isSsl ? "https://" : "http://") + this.baseUrl + ":" + (isSsl ? 443 : 80) + "/kylin/api/query"; - } - - public String getProject() { - return this.project; - } - - public Meta getMeta() { - return this.meta; - } - - public AvaticaFactory getFactory() { - return this.factory; - } - - public UnregisteredDriver getDriver() { - return this.driver; - } - - public MetaProject getMetaProject() { - return metaProject; - } - - public void setMetaProject(MetaProject metaProject) { - this.metaProject = metaProject; - } - - @Override - public void close() throws SQLException { - super.close(); - - this.metaProject = null; - this.statements.clear(); - } - - @Override - public String toString() { - return "KylinConnectionImpl [baseUrl=" + baseUrl + ", project=" + project + ", metaProject=" + metaProject + "]"; - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinEnumerator.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinEnumerator.java deleted file mode 100644 index 41f633a..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinEnumerator.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.util.Collection; -import java.util.Iterator; - -import net.hydromatic.linq4j.Enumerator; - -/** - * Query results enumerator - * - * @author xduo - * - */ -public class KylinEnumerator implements Enumerator { - - /** - * current row - */ - private E current; - - /** - * data collection - */ - private Collection dataCollection; - - /** - * result iterator - */ - private Iterator cursor; - - public KylinEnumerator(Collection dataCollection) { - this.dataCollection = dataCollection; - this.cursor = this.dataCollection.iterator(); - - if (null == this.cursor) { - throw new RuntimeException("Cursor can't be null"); - } - } - - @Override - public E current() { - return current; - } - - @Override - public boolean moveNext() { - if (!cursor.hasNext()) { - this.reset(); - - return false; - } - - current = cursor.next(); - - return true; - } - - @Override - public void reset() { - this.cursor = this.dataCollection.iterator(); - } - - @Override - public void close() { - this.cursor = null; - this.dataCollection = null; - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc40Factory.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc40Factory.java deleted file mode 100644 index b45b497..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc40Factory.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -/** - * @author xduo - * - */ -public class KylinJdbc40Factory extends KylinJdbc41Factory { - - public KylinJdbc40Factory() { - super(4, 0); - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc41Factory.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc41Factory.java deleted file mode 100644 index 8a27246..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinJdbc41Factory.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.util.List; -import java.util.Properties; -import java.util.TimeZone; - -import net.hydromatic.avatica.AvaticaConnection; -import net.hydromatic.avatica.AvaticaDatabaseMetaData; -import net.hydromatic.avatica.AvaticaFactory; -import net.hydromatic.avatica.AvaticaPrepareResult; -import net.hydromatic.avatica.AvaticaPreparedStatement; -import net.hydromatic.avatica.AvaticaResultSet; -import net.hydromatic.avatica.AvaticaResultSetMetaData; -import net.hydromatic.avatica.AvaticaStatement; -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.avatica.UnregisteredDriver; - -import com.kylinolap.kylin.jdbc.stub.KylinClient; -import com.kylinolap.kylin.jdbc.stub.RemoteClient; - -/** - * Kylin JDBC factory. - * - * @author xduo - * - */ -public class KylinJdbc41Factory implements AvaticaFactory { - private final int major; - private final int minor; - - /** Creates a JDBC factory. */ - public KylinJdbc41Factory() { - this(4, 1); - } - - /** Creates a JDBC factory with given major/minor version number. */ - protected KylinJdbc41Factory(int major, int minor) { - this.major = major; - this.minor = minor; - } - - public int getJdbcMajorVersion() { - return major; - } - - public int getJdbcMinorVersion() { - return minor; - } - - public AvaticaConnection newConnection(UnregisteredDriver driver, AvaticaFactory factory, String url, Properties info) { - return new KylinJdbc41Connection(driver, factory, url, info); - } - - public AvaticaDatabaseMetaData newDatabaseMetaData(AvaticaConnection connection) { - return new AvaticaJdbc41DatabaseMetaData(connection); - } - - public AvaticaStatement newStatement(AvaticaConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { - return new KylinJdbc41Statement(connection, resultSetType, resultSetConcurrency, resultSetHoldability); - } - - public AvaticaPreparedStatement newPreparedStatement(AvaticaConnection connection, AvaticaPrepareResult prepareResult, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return new KylinJdbc41PreparedStatement(connection, prepareResult, resultSetType, resultSetConcurrency, resultSetHoldability); - } - - public AvaticaResultSet newResultSet(AvaticaStatement statement, AvaticaPrepareResult prepareResult, TimeZone timeZone) { - final ResultSetMetaData metaData = newResultSetMetaData(statement, prepareResult.getColumnList()); - return new KylinResultSet(statement, prepareResult, metaData, timeZone); - } - - public AvaticaResultSetMetaData newResultSetMetaData(AvaticaStatement statement, List columnMetaDataList) { - return new AvaticaResultSetMetaData(statement, null, columnMetaDataList); - } - - // ~ kylin sepcified - public RemoteClient newRemoteClient(KylinConnectionImpl connection) { - return new KylinClient(connection); - } - - /** Implementation of Connection for JDBC 4.1. */ - private static class KylinJdbc41Connection extends KylinConnectionImpl { - KylinJdbc41Connection(UnregisteredDriver driver, AvaticaFactory factory, String url, Properties info) { - super(driver, (KylinJdbc41Factory) factory, url, info); - } - } - - /** Implementation of Statement for JDBC 4.1. */ - public static class KylinJdbc41Statement extends KylinStatementImpl { - public KylinJdbc41Statement(AvaticaConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { - super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); - } - } - - /** Implementation of PreparedStatement for JDBC 4.1. */ - public static class KylinJdbc41PreparedStatement extends KylinPrepareStatementImpl { - KylinJdbc41PreparedStatement(AvaticaConnection connection, AvaticaPrepareResult sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - super(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability); - } - } - - /** Implementation of DatabaseMetaData for JDBC 4.1. */ - private static class AvaticaJdbc41DatabaseMetaData extends AvaticaDatabaseMetaData { - AvaticaJdbc41DatabaseMetaData(AvaticaConnection connection) { - super(connection); - } - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinMetaImpl.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinMetaImpl.java deleted file mode 100644 index 712e53f..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinMetaImpl.java +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.lang.reflect.Field; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -import net.hydromatic.avatica.AvaticaPrepareResult; -import net.hydromatic.avatica.AvaticaResultSet; -import net.hydromatic.avatica.AvaticaStatement; -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.avatica.ColumnMetaData.Rep; -import net.hydromatic.avatica.Cursor; -import net.hydromatic.avatica.Meta; -import net.hydromatic.linq4j.Enumerator; -import net.hydromatic.optiq.runtime.EnumeratorCursor; - -import org.eigenbase.sql.SqlJdbcFunctionCall; -import org.eigenbase.sql.parser.SqlParser; -import org.eigenbase.util.Util; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.kylinolap.kylin.jdbc.stub.DataSet; -import com.kylinolap.kylin.jdbc.stub.KylinColumnMetaData; -import com.kylinolap.kylin.jdbc.stub.RemoteClient; -import com.kylinolap.kylin.jdbc.util.SQLTypeMap; - -/** - * Implementation of avatica interface - * - * @author xduo - */ -public class KylinMetaImpl implements Meta { - - private static final Logger logger = LoggerFactory.getLogger(KylinMetaImpl.class); - - private final KylinConnectionImpl conn; - - private final KylinJdbc41Factory factory; - - /** - * @param conn - */ - public KylinMetaImpl(KylinConnectionImpl conn, KylinJdbc41Factory factory) { - super(); - this.conn = conn; - this.factory = factory; - } - - private ResultSet mockEmptyResultSet() { - AvaticaResultSet resultSet = null; - try { - List columnMetas = new ArrayList(); - List data = new ArrayList(); - resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, new KylinEnumerator(data), ColumnMetaData.struct(columnMetas)), this.conn.getTimeZone()); - KylinConnectionImpl.TROJAN.execute(resultSet); - } catch (SQLException e) { - logger.error(e.getLocalizedMessage(), e); - } - - return resultSet; - } - - public String getSqlKeywords() { - return SqlParser.create("").getMetadata().getJdbcKeywords(); - } - - public String getNumericFunctions() { - return SqlJdbcFunctionCall.getNumericFunctions(); - } - - public String getStringFunctions() { - return SqlJdbcFunctionCall.getStringFunctions(); - } - - public String getSystemFunctions() { - return SqlJdbcFunctionCall.getSystemFunctions(); - } - - public String getTimeDateFunctions() { - return SqlJdbcFunctionCall.getTimeDateFunctions(); - } - - public ResultSet getTables(String catalog, Pat schemaPattern, Pat tableNamePattern, List typeList) { - logger.debug("Get tables with conn " + conn); - MetaProject metaProject = conn.getMetaProject(); - - if (null != metaProject) { - final DataSet tables = metaProject.getMetaTables(catalog, schemaPattern, tableNamePattern); - final NamedFieldGetter tableGetter = new NamedFieldGetter(MetaTable.class, tables.getMeta(), "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS", "TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "SELF_REFERENCING_COL_NAME", "REF_GENERATION"); - - AvaticaResultSet resultSet = null; - try { - resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, tableGetter.structType) { - @Override - public Cursor createCursor() { - return tableGetter.cursor(tables.getEnumerator()); - } - }, this.conn.getTimeZone()); - KylinConnectionImpl.TROJAN.execute(resultSet); - } catch (SQLException e) { - logger.error(e.getLocalizedMessage(), e); - } - - return resultSet; - } else { - return mockEmptyResultSet(); - } - } - - public ResultSet getColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { - logger.debug("Get columns with conn " + conn); - MetaProject metaProject = conn.getMetaProject(); - - if (null != metaProject) { - final DataSet columns = metaProject.getMetaColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); - final NamedFieldGetter columnGetter = new NamedFieldGetter(MetaColumn.class, columns.getMeta(), "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS", "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATALOG", "SCOPE_TABLE", "SOURCE_DATA_TYPE", "IS_AUTOINCREMENT", "IS_GENERATEDCOLUMN"); - - AvaticaResultSet resultSet = null; - try { - resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, columnGetter.structType) { - @Override - public Cursor createCursor() { - return columnGetter.cursor(columns.getEnumerator()); - } - }, this.conn.getTimeZone()); - - KylinConnectionImpl.TROJAN.execute(resultSet); - } catch (SQLException e) { - logger.error(e.getLocalizedMessage(), e); - } - - return resultSet; - } else { - return mockEmptyResultSet(); - } - } - - public ResultSet getSchemas(String catalog, Pat schemaPattern) { - logger.debug("Get schemas with conn " + conn); - MetaProject metaProject = conn.getMetaProject(); - - if (null != metaProject) { - final DataSet schemas = metaProject.getMetaSchemas(catalog, schemaPattern); - final NamedFieldGetter schemaGetter = new NamedFieldGetter(MetaSchema.class, schemas.getMeta(), "TABLE_SCHEM", "TABLE_CATALOG"); - - AvaticaResultSet resultSet = null; - try { - resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, schemaGetter.structType) { - @Override - public Cursor createCursor() { - return schemaGetter.cursor(schemas.getEnumerator()); - } - }, this.conn.getTimeZone()); - - KylinConnectionImpl.TROJAN.execute(resultSet); - } catch (SQLException e) { - logger.error(e.getLocalizedMessage(), e); - } - - return resultSet; - } else { - return mockEmptyResultSet(); - } - } - - public ResultSet getCatalogs() { - MetaProject metaProject = conn.getMetaProject(); - - if (null != metaProject) { - final DataSet catalogs = metaProject.getMetaCatalogs(); - final NamedFieldGetter catalogGetter = new NamedFieldGetter(MetaCatalog.class, catalogs.getMeta(), "TABLE_CATALOG"); - - AvaticaResultSet resultSet = null; - try { - resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, null, catalogGetter.structType) { - @Override - public Cursor createCursor() { - return catalogGetter.cursor(catalogs.getEnumerator()); - } - }, this.conn.getTimeZone()); - - KylinConnectionImpl.TROJAN.execute(resultSet); - } catch (SQLException e) { - logger.error(e.getLocalizedMessage(), e); - } - - return resultSet; - } else { - return mockEmptyResultSet(); - } - } - - public ResultSet getTableTypes() { - List tableTypeMeta = new ArrayList(); - tableTypeMeta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), false)); - List data = new ArrayList(); - Object[] row = new Object[1]; - row[0] = "TABLE"; - data.add(row); - - AvaticaResultSet resultSet = null; - try { - resultSet = this.conn.getFactory().newResultSet(this.conn.createStatement(), new KylinPrepare.PrepareResult(null, null, new KylinEnumerator(data), ColumnMetaData.struct(tableTypeMeta)), this.conn.getTimeZone()); - KylinConnectionImpl.TROJAN.execute(resultSet); - } catch (SQLException e) { - logger.error(e.getLocalizedMessage(), e); - } - - return resultSet; - } - - public ResultSet getProcedures(String catalog, Pat schemaPattern, Pat procedureNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getProcedureColumns(String catalog, Pat schemaPattern, Pat procedureNamePattern, Pat columnNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getColumnPrivileges(String catalog, String schema, String table, Pat columnNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getTablePrivileges(String catalog, Pat schemaPattern, Pat tableNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) { - return mockEmptyResultSet(); - } - - public ResultSet getVersionColumns(String catalog, String schema, String table) { - return mockEmptyResultSet(); - } - - public ResultSet getPrimaryKeys(String catalog, String schema, String table) { - return mockEmptyResultSet(); - } - - public ResultSet getImportedKeys(String catalog, String schema, String table) { - return mockEmptyResultSet(); - } - - public ResultSet getExportedKeys(String catalog, String schema, String table) { - return mockEmptyResultSet(); - } - - public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) { - return mockEmptyResultSet(); - } - - public ResultSet getTypeInfo() { - return mockEmptyResultSet(); - } - - public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) { - return mockEmptyResultSet(); - } - - public ResultSet getUDTs(String catalog, Pat schemaPattern, Pat typeNamePattern, int[] types) { - return mockEmptyResultSet(); - } - - public ResultSet getSuperTypes(String catalog, Pat schemaPattern, Pat typeNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getSuperTables(String catalog, Pat schemaPattern, Pat tableNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getAttributes(String catalog, Pat schemaPattern, Pat typeNamePattern, Pat attributeNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getClientInfoProperties() { - return mockEmptyResultSet(); - } - - public ResultSet getFunctions(String catalog, Pat schemaPattern, Pat functionNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getFunctionColumns(String catalog, Pat schemaPattern, Pat functionNamePattern, Pat columnNamePattern) { - return mockEmptyResultSet(); - } - - public ResultSet getPseudoColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { - return mockEmptyResultSet(); - } - - public Cursor createCursor(AvaticaResultSet resultSet) { - - if (!(resultSet instanceof KylinResultSet)) - throw new IllegalStateException("resultSet is not KylinResultSet"); - - KylinPrepare.PrepareResult result = ((KylinResultSet) resultSet).getPrepareResult(); - - return result.createCursor(); - } - - /* - * Client could request metadata after prepare - * - * (non-Javadoc) - * @see net.hydromatic.avatica.Meta#prepare(net.hydromatic.avatica.AvaticaStatement, java.lang.String) - */ - public AvaticaPrepareResult prepare(AvaticaStatement statement, String sql) { - RemoteClient client = factory.newRemoteClient(conn); - DataSet result = null; - - try { - result = (DataSet) client.query(statement, sql); - } catch (Exception e) { - logger.error(e.getLocalizedMessage(), e); - throw new RuntimeException("Failed to query kylin server with exception " + e.getLocalizedMessage()); - } - - return new KylinPrepare.PrepareResult(sql, null, (Enumerator) result.getEnumerator(), ColumnMetaData.struct(result.getMeta())); - } - - /** - * Tree node used by project tree-like structure - * - * @author xduo - */ - interface Node { - /** - * Get the node name - * - * @return - */ - public String getName(); - - /** - * Get direct children of the node. - * - * @return - */ - public List getChildren(); - - /** - * Search the subtree of the node with patterns. One pattern, one level. - * - * @param patterns - * @return - */ - public List searchByPatterns(Pat... patterns); - } - - /** - * Abstract of the tree-like structure - * - * @author xduo - */ - public static abstract class AbstractNode implements Node { - - public List searchByPatterns(Pat... patterns) { - if (patterns.length == 1) { - return findChildren(patterns[0]); - } else { - List children = new ArrayList(); - - for (Node child : this.findChildren(patterns[0])) { - children.addAll(child.searchByPatterns(Arrays.copyOfRange(patterns, 1, patterns.length))); - } - - return children; - } - } - - private List findChildren(Pat pattern) { - if (null == pattern.s || pattern.s.equals("%")) { - return this.getChildren(); - } - - List list = new ArrayList(); - - for (Node c : this.getChildren()) { - if (likeToRegex(pattern).matcher(c.getName()).matches()) { - list.add(c); - } - } - - return list; - } - - ; - - /** - * Converts a LIKE-style pattern (where '%' represents a wild-card, - * escaped using '\') to a Java regex. - */ - private Pattern likeToRegex(Pat pattern) { - StringBuilder buf = new StringBuilder("^"); - char[] charArray = pattern.s.toCharArray(); - int slash = -2; - for (int i = 0; i < charArray.length; i++) { - char c = charArray[i]; - if (slash == i - 1) { - buf.append('[').append(c).append(']'); - } else { - switch (c) { - case '\\': - slash = i; - break; - case '%': - buf.append(".*"); - break; - case '[': - buf.append("\\["); - break; - case ']': - buf.append("\\]"); - break; - default: - buf.append('[').append(c).append(']'); - } - } - } - buf.append("$"); - - return Pattern.compile(buf.toString()); - } - } - - public static class MetaProject extends AbstractNode { - public final String project; - public final List catalogs; - - public MetaProject(String project, List catalogs) { - super(); - this.project = project; - this.catalogs = catalogs; - } - - public DataSet getMetaCatalogs() { - return new DataSet(MetaCatalog.meta, new KylinEnumerator(catalogs)); - } - - /** - * facade method to search schemas in current project. - * - * @param catalog - * @param schemaPattern - * @return - */ - @SuppressWarnings("unchecked") - public DataSet getMetaSchemas(String catalog, Pat schemaPattern) { - List metaSchemas = this.searchByPatterns(Pat.of(catalog), schemaPattern); - - return new DataSet(MetaSchema.meta, new KylinEnumerator((Collection) metaSchemas)); - } - - /** - * facade method to search tables in current project - * - * @param catalog - * @param schemaPattern - * @param tableNamePattern - * @return - */ - @SuppressWarnings("unchecked") - public DataSet getMetaTables(String catalog, Pat schemaPattern, Pat tableNamePattern) { - logger.debug("getMetaTables with catalog:" + catalog + ", schema:" + schemaPattern.s + ", table:" + tableNamePattern.s); - List tables = this.searchByPatterns(Pat.of(catalog), schemaPattern, tableNamePattern); - - return new DataSet(MetaTable.meta, new KylinEnumerator((Collection) tables)); - } - - /** - * facade method to search columns in current project - * - * @param catalog - * @param schemaPattern - * @param tableNamePattern - * @param columnNamePattern - * @return - */ - @SuppressWarnings("unchecked") - public DataSet getMetaColumns(String catalog, Pat schemaPattern, Pat tableNamePattern, Pat columnNamePattern) { - logger.debug("getMetaColumns with catalog:" + catalog + ", schema:" + schemaPattern.s + ", table:" + tableNamePattern.s + ", column:" + columnNamePattern.s); - List columns = this.searchByPatterns(Pat.of(catalog), schemaPattern, tableNamePattern, columnNamePattern); - - return new DataSet(MetaColumn.meta, new KylinEnumerator((Collection) columns)); - } - - @Override - public String getName() { - return project; - } - - @Override - public List getChildren() { - return this.catalogs; - } - } - - /** - * Metadata describing a catalog. - */ - public static class MetaCatalog extends AbstractNode { - public static final List meta = new ArrayList(); - public final String tableCatalog; - public final List schemas; - - static { - meta.add(KylinColumnMetaData.dummy(0, "TABLE_CAT", "TABLE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - } - - public MetaCatalog(String tableCatalog, List schemas) { - this.tableCatalog = tableCatalog; - this.schemas = schemas; - } - - public String getName() { - return tableCatalog; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((tableCatalog == null) ? 0 : tableCatalog.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MetaCatalog other = (MetaCatalog) obj; - if (tableCatalog == null) { - if (other.tableCatalog != null) - return false; - } else if (!tableCatalog.equals(other.tableCatalog)) - return false; - return true; - } - - @Override - public List getChildren() { - return schemas; - } - - } - - /** - * Metadata describing a schema. - */ - public static class MetaSchema extends AbstractNode { - public static final List meta = new ArrayList(); - public final String tableCatalog; - public final String tableSchem; - public final List tables; - - static { - for (ColumnMetaData cmd : SQLTypeMap.schemaMetaTypeMapping.values()) { - meta.add(cmd); - } - } - - public MetaSchema(String tableCatalog, String tableSchem, List tables) { - this.tableCatalog = tableCatalog; - this.tableSchem = tableSchem; - this.tables = tables; - } - - public String getName() { - return tableSchem; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((tableCatalog == null) ? 0 : tableCatalog.hashCode()); - result = prime * result + ((tableSchem == null) ? 0 : tableSchem.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - MetaSchema other = (MetaSchema) obj; - if (tableCatalog == null) { - if (other.tableCatalog != null) - return false; - } else if (!tableCatalog.equals(other.tableCatalog)) - return false; - if (tableSchem == null) { - if (other.tableSchem != null) - return false; - } else if (!tableSchem.equals(other.tableSchem)) - return false; - return true; - } - - @Override - public List getChildren() { - return this.tables; - } - } - - /** - * Metadata describing a table type. - */ - public static class MetaTableType { - public final String tableType; - - public MetaTableType(String tableType) { - this.tableType = tableType; - } - } - - /** - * Metadata describing a table. - */ - public static class MetaTable extends AbstractNode { - public static final List meta = new ArrayList(); - public final String tableCat; - public final String tableSchem; - public final String tableName; - public final String tableType; - public final String remarks; - public final String typeCat; - public final String typeSchem; - public final String typeName; - public final String selfReferencingColName; - public final String refGeneration; - public final List columns; - - static { - for (ColumnMetaData cmd : SQLTypeMap.tableMetaTypeMapping.values()) { - meta.add(cmd); - } - } - - public MetaTable(String tableCat, String tableSchem, String tableName, String tableType, String remarks, String typeCat, String typeSchem, String typeName, String selfReferencingColName, String refGeneration, List columns) { - this.tableCat = tableCat; - this.tableSchem = tableSchem; - this.tableName = tableName; - this.tableType = tableType; - this.remarks = remarks; - this.typeCat = typeCat; - this.typeSchem = typeSchem; - this.typeName = typeName; - this.selfReferencingColName = selfReferencingColName; - this.refGeneration = refGeneration; - this.columns = columns; - } - - public String getName() { - return tableName; - } - - @Override - public List getChildren() { - return this.columns; - } - } - - /** - * Metadata describing a column. - */ - public static class MetaColumn implements Node { - public static final List meta = new ArrayList(); - public final String tableCat; - public final String tableSchem; - public final String tableName; - public final String columnName; - public final int dataType; - public final String typeName; - public final int columnSize; - public final int bufferLength; - public final int decimalDigits; - public final int numPrecRadix; - public final int nullable; - public final String remarks; - public final String columnDef; - public final int sqlDataType; - public final int sqlDatetimeSub; - public final int charOctetLength; - public final int ordinalPosition; - public final String isNullable; - public final String scopeCatalog; - public final String scopeTable; - public final int sourceDataType; - public final String isAutoincrement; - public final String isGeneratedcolumn; - - static { - for (ColumnMetaData cmd : SQLTypeMap.columnMetaTypeMapping.values()) { - meta.add(cmd); - } - } - - public MetaColumn(String tableCat, String tableSchem, String tableName, String columnName, int dataType, String typeName, int columnSize, int bufferLength, int decimalDigits, int numPrecRadix, int nullable, String remarks, String columnDef, int sqlDataType, int sqlDatetimeSub, int charOctetLength, int ordinalPosition, String isNullable, String scopeCatalog, String scopeTable, int sourceDataType, String isAutoincrement, String isGeneratedcolumn) { - super(); - this.tableCat = tableCat; - this.tableSchem = tableSchem; - this.tableName = tableName; - this.columnName = columnName; - this.dataType = dataType; - this.typeName = typeName; - this.columnSize = columnSize; - this.bufferLength = bufferLength; - this.decimalDigits = decimalDigits; - this.numPrecRadix = numPrecRadix; - this.nullable = nullable; - this.remarks = remarks; - this.columnDef = columnDef; - this.sqlDataType = sqlDataType; - this.sqlDatetimeSub = sqlDatetimeSub; - this.charOctetLength = charOctetLength; - this.ordinalPosition = ordinalPosition; - this.isNullable = isNullable; - this.scopeCatalog = scopeCatalog; - this.scopeTable = scopeTable; - this.sourceDataType = sourceDataType; - this.isAutoincrement = isAutoincrement; - this.isGeneratedcolumn = isGeneratedcolumn; - } - - public String getName() { - return columnName; - } - - @Override - public List getChildren() { - return Collections.emptyList(); - } - - @Override - public List searchByPatterns(Pat... patterns) { - return Collections.emptyList(); - } - } - - /** - * Accesses fields by name. - */ - private static class NamedFieldGetter { - private final List fields = new ArrayList(); - private final ColumnMetaData.StructType structType; - - public NamedFieldGetter(Class clazz, List columns, String... names) { - init(clazz, names, fields); - structType = ColumnMetaData.struct(columns); - } - - private void init(Class clazz, String[] names, List fields) { - for (String name : names) { - final String fieldName = Util.toCamelCase(name); - final Field field; - try { - field = clazz.getField(fieldName); - } catch (NoSuchFieldException e) { - throw new RuntimeException(e); - } - fields.add(field); - } - } - - Object get(Object o, int columnIndex) { - try { - return fields.get(columnIndex).get(o); - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - public Cursor cursor(Enumerator enumerator) { - // noinspection unchecked - return new EnumeratorCursor(enumerator) { - protected Getter createGetter(final int ordinal) { - return new Getter() { - public Object getObject() { - return get(current(), ordinal); - } - - public boolean wasNull() { - return getObject() == null; - } - }; - } - }; - } - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepare.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepare.java deleted file mode 100644 index da13cbf..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepare.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.util.List; - -import net.hydromatic.avatica.AvaticaParameter; -import net.hydromatic.avatica.AvaticaPrepareResult; -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.avatica.Cursor; -import net.hydromatic.linq4j.Enumerator; -import net.hydromatic.optiq.runtime.EnumeratorCursor; - -/** - * Interface of kylin prepare statement implementation - * - * @author xduo - * - */ -public interface KylinPrepare { - - PrepareResult prepare(String sql); - - /** - * The result of preparing a query. It gives the Avatica driver framework - * the information it needs to create a prepared statement, or to execute a - * statement directly, without an explicit prepare step. - */ - public static class PrepareResult implements AvaticaPrepareResult { - public final String sql; // for debug - public final ColumnMetaData.StructType structType; - public final Enumerator enumerator; - public final List parameterList; - - public PrepareResult(String sql, List parameterList, Enumerator enumerator, ColumnMetaData.StructType structType) { - super(); - this.sql = sql; - this.parameterList = parameterList; - this.enumerator = enumerator; - this.structType = structType; - } - - public Cursor createCursor() { - return new EnumeratorCursor(enumerator) { - @Override - protected Getter createGetter(int ordinal) { - return new ArrayEnumeratorGetter(ordinal); - } - - /** - * Row field accessor via index - */ - class ArrayEnumeratorGetter extends AbstractGetter { - protected final int field; - - public ArrayEnumeratorGetter(int field) { - this.field = field; - } - - public Object getObject() { - Object o = current()[field]; - wasNull[0] = o == null; - return o; - } - } - }; - } - - public List getColumnList() { - return structType.columns; - } - - public List getParameterList() { - return parameterList; - } - - public String getSql() { - return sql; - } - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareImpl.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareImpl.java deleted file mode 100644 index b435adf..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareImpl.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.util.ArrayList; -import java.util.List; - -import net.hydromatic.avatica.AvaticaParameter; -import net.hydromatic.avatica.ColumnMetaData; - -/** - * @author xduo - * - */ -public class KylinPrepareImpl implements KylinPrepare { - - @Override - public PrepareResult prepare(String sql) { - List aps = new ArrayList(); - - int startIndex = 0; - while (sql.indexOf("?", startIndex) >= 0) { - AvaticaParameter ap = new AvaticaParameter(false, 0, 0, 0, null, null, null); - aps.add(ap); - startIndex = sql.indexOf("?", startIndex) + 1; - } - - return new KylinPrepare.PrepareResult(sql, aps, null, ColumnMetaData.struct(new ArrayList())); - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareStatementImpl.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareStatementImpl.java deleted file mode 100644 index b65705d..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinPrepareStatementImpl.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.io.InputStream; -import java.io.Reader; -import java.sql.NClob; -import java.sql.ResultSet; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLXML; -import java.util.Collections; -import java.util.List; - -import net.hydromatic.avatica.AvaticaConnection; -import net.hydromatic.avatica.AvaticaPrepareResult; -import net.hydromatic.avatica.AvaticaPreparedStatement; -import net.hydromatic.avatica.AvaticaResultSet; - -/** - * Kylin prepare statement.
    - * Supported operations: - *
      - *
    • setString
    • - *
    • setInt
    • - *
    • setShort
    • - *
    • setLong
    • - *
    • setFloat
    • - *
    • setDouble
    • - *
    • setBoolean
    • - *
    • setByte
    • - *
    • setDate
    • - *
    • setTime
    • - *
    • setTimestamp
    • - *
    - * - * @author xduo - * - */ -public abstract class KylinPrepareStatementImpl extends AvaticaPreparedStatement { - - /** - * Before real query, - */ - protected AvaticaPrepareResult prequeryResult; - - protected KylinPrepareStatementImpl(AvaticaConnection connection, AvaticaPrepareResult prepareResult, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - super(connection, prepareResult, resultSetType, resultSetConcurrency, resultSetHoldability); - - this.prequeryResult = prepareResult; - } - - @Override - public ResultSet executeQuery() throws SQLException { - AvaticaPrepareResult queriedResult = ((KylinConnectionImpl) this.connection).getMeta().prepare(this, this.prequeryResult.getSql()); - - return executeQueryInternal(queriedResult); - } - - @Override - protected void close_() { - if (!closed) { - closed = true; - final KylinConnectionImpl connection_ = (KylinConnectionImpl) connection; - connection_.statements.remove(this); - if (openResultSet != null) { - AvaticaResultSet c = openResultSet; - openResultSet = null; - c.close(); - } - // If onStatementClose throws, this method will throw an - // exception (later - // converted to SQLException), but this statement still gets - // closed. - connection_.getDriver().handler.onStatementClose(this); - } - } - - public List getParameterValues() { - return (List) Collections.unmodifiableList(super.getParameterValues()); - } - - public void setRowId(int parameterIndex, RowId x) throws SQLException { - getParameter(parameterIndex).setRowId(x); - } - - public void setNString(int parameterIndex, String value) throws SQLException { - getParameter(parameterIndex).setNString(value); - } - - public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { - getParameter(parameterIndex).setNCharacterStream(value, length); - } - - public void setNClob(int parameterIndex, NClob value) throws SQLException { - getParameter(parameterIndex).setNClob(value); - } - - public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { - getParameter(parameterIndex).setClob(reader, length); - } - - public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { - getParameter(parameterIndex).setBlob(inputStream, length); - } - - public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { - getParameter(parameterIndex).setNClob(reader, length); - } - - public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - getParameter(parameterIndex).setSQLXML(xmlObject); - } - - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - getParameter(parameterIndex).setAsciiStream(x, length); - } - - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - getParameter(parameterIndex).setBinaryStream(x, length); - } - - public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { - getParameter(parameterIndex).setCharacterStream(reader, length); - } - - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - getParameter(parameterIndex).setAsciiStream(x); - } - - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - getParameter(parameterIndex).setBinaryStream(x); - } - - public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { - getParameter(parameterIndex).setCharacterStream(reader); - } - - public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - getParameter(parameterIndex).setNCharacterStream(value); - } - - public void setClob(int parameterIndex, Reader reader) throws SQLException { - getParameter(parameterIndex).setClob(reader); - } - - public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { - getParameter(parameterIndex).setBlob(inputStream); - } - - public void setNClob(int parameterIndex, Reader reader) throws SQLException { - getParameter(parameterIndex).setNClob(reader); - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinResultSet.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinResultSet.java deleted file mode 100644 index 081eafa..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinResultSet.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc; - -import java.sql.ResultSetMetaData; -import java.util.TimeZone; - -import net.hydromatic.avatica.AvaticaPrepareResult; -import net.hydromatic.avatica.AvaticaResultSet; -import net.hydromatic.avatica.AvaticaStatement; - -import com.kylinolap.kylin.jdbc.KylinPrepare.PrepareResult; - -/** - * Kylin query result set - * - * @author xduo - * - */ -public class KylinResultSet extends AvaticaResultSet { - - public KylinResultSet(AvaticaStatement statement, AvaticaPrepareResult prepareResult, ResultSetMetaData resultSetMetaData, TimeZone timeZone) { - super(statement, prepareResult, resultSetMetaData, timeZone); - } - - public KylinPrepare.PrepareResult getPrepareResult() { - return (PrepareResult) prepareResult; - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinStatementImpl.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinStatementImpl.java deleted file mode 100644 index 47b7986..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/KylinStatementImpl.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013-2014 eBay Softwarimport net.hydromatic.avatica.AvaticaConnection; -import net.hydromatic.avatica.AvaticaResultSet; -import net.hydromatic.avatica.AvaticaStatement; -ense. - * 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.kylinolap.kylin.jdbc; - -import net.hydromatic.avatica.AvaticaConnection; -import net.hydromatic.avatica.AvaticaResultSet; -import net.hydromatic.avatica.AvaticaStatement; - -/** - * Kylin statement implementation - * - * @author xduo - * - */ -public abstract class KylinStatementImpl extends AvaticaStatement { - - protected KylinStatementImpl(AvaticaConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability) { - super(connection, resultSetType, resultSetConcurrency, resultSetHoldability); - } - - @Override - protected void close_() { - if (!closed) { - closed = true; - final KylinConnectionImpl connection_ = (KylinConnectionImpl) connection; - connection_.statements.remove(this); - if (openResultSet != null) { - AvaticaResultSet c = openResultSet; - openResultSet = null; - c.close(); - } - // If onStatementClose throws, this method will throw an exception - // (later - // converted to SQLException), but this statement still gets closed. - connection_.getDriver().handler.onStatementClose(this); - } - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/ConnectionException.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/ConnectionException.java deleted file mode 100644 index 48c7be3..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/ConnectionException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.stub; - -/** - * @author xduo - * - */ -public class ConnectionException extends Exception { - - private static final long serialVersionUID = 1L; - - public ConnectionException() { - super(); - } - - /** - * @param message - * @param cause - */ - public ConnectionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * @param message - */ - public ConnectionException(String message) { - super(message); - } - - /** - * @param cause - */ - public ConnectionException(Throwable cause) { - super(cause); - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/DataSet.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/DataSet.java deleted file mode 100644 index 1f2775f..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/DataSet.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.stub; - -import java.util.List; - -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.linq4j.Enumerator; - -/** - * Data set wrapper. - * - * @author xduo - * - */ -public class DataSet { - - private final List meta; - - private final Enumerator enumerator; - - /** - * @param meta - * @param enumerator - */ - public DataSet(List meta, Enumerator enumerator) { - this.meta = meta; - this.enumerator = enumerator; - } - - public List getMeta() { - return meta; - } - - public Enumerator getEnumerator() { - return enumerator; - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinClient.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinClient.java deleted file mode 100644 index 43f4aee..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinClient.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.stub; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import net.hydromatic.avatica.AvaticaStatement; -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.avatica.ColumnMetaData.Rep; -import net.hydromatic.avatica.ColumnMetaData.ScalarType; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethodBase; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.StringRequestEntity; -import org.apache.commons.httpclient.protocol.Protocol; -import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.HashMultimap; -import com.kylinolap.kylin.jdbc.KylinConnectionImpl; -import com.kylinolap.kylin.jdbc.KylinEnumerator; -import com.kylinolap.kylin.jdbc.KylinJdbc41Factory.KylinJdbc41PreparedStatement; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaCatalog; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaColumn; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaProject; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaSchema; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaTable; -import com.kylinolap.kylin.jdbc.stub.TableMetaStub.ColumnMetaStub; -import com.kylinolap.kylin.jdbc.util.DefaultSslProtocolSocketFactory; -import com.kylinolap.kylin.jdbc.util.SQLTypeMap; - -/** - * @author xduo - * - */ -public class KylinClient implements RemoteClient { - private static final Logger logger = LoggerFactory.getLogger(KylinClient.class); - - private final KylinConnectionImpl conn; - - public KylinClient(KylinConnectionImpl conn) { - this.conn = conn; - } - - @Override - public void connect() throws ConnectionException { - PostMethod post = new PostMethod(conn.getConnectUrl()); - HttpClient httpClient = new HttpClient(); - - if (conn.getConnectUrl().toLowerCase().startsWith("https://")) { - registerSsl(); - } - addPostHeaders(post); - - try { - StringRequestEntity requestEntity = new StringRequestEntity("{}", "application/json", "UTF-8"); - post.setRequestEntity(requestEntity); - httpClient.executeMethod(post); - - if (post.getStatusCode() != 200 && post.getStatusCode() != 201) { - logger.error("Authentication Failed with error code " + post.getStatusCode() + " and message:\n" + post.getResponseBodyAsString()); - - throw new ConnectionException("Authentication Failed."); - } - } catch (HttpException e) { - logger.error(e.getLocalizedMessage(), e); - throw new ConnectionException(e.getLocalizedMessage()); - } catch (IOException e) { - logger.error(e.getLocalizedMessage(), e); - throw new ConnectionException(e.getLocalizedMessage()); - } - } - - @Override - public MetaProject getMetadata(String project) throws ConnectionException { - GetMethod get = new GetMethod(conn.getMetaProjectUrl(project)); - HttpClient httpClient = new HttpClient(); - - if (conn.getConnectUrl().toLowerCase().startsWith("https://")) { - registerSsl(); - } - addPostHeaders(get); - - List tableMetaStubs = null; - try { - httpClient.executeMethod(get); - - if (get.getStatusCode() != 200 && get.getStatusCode() != 201) { - logger.error("Authentication Failed with error code " + get.getStatusCode() + " and message:\n" + get.getResponseBodyAsString()); - - throw new ConnectionException("Authentication Failed."); - } - - tableMetaStubs = new ObjectMapper().readValue(get.getResponseBodyAsString(), new TypeReference>() { - }); - - List tables = new ArrayList(); - HashMultimap schemasMap = HashMultimap.create(); - - for (TableMetaStub tableMetaStub : tableMetaStubs) { - List columns = new ArrayList(); - - for (ColumnMetaStub columnMetaStub : tableMetaStub.getColumns()) { - MetaColumn column = createNewColumn(columnMetaStub); - columns.add(column); - } - - MetaTable table = createNewTable(tableMetaStub, columns); - tables.add(table); - schemasMap.put(tableMetaStub.getTABLE_CAT() + "#" + tableMetaStub.getTABLE_SCHEM(), table); - } - - HashMultimap catalogMap = HashMultimap.create(); - List schemas = new ArrayList(); - for (String key : schemasMap.keySet()) { - String cat = key.split("#")[0]; - String schema = key.split("#")[1]; - MetaSchema metaSchema = new MetaSchema(cat, schema, new ArrayList(schemasMap.get(key))); - schemas.add(metaSchema); - catalogMap.put(cat, metaSchema); - } - - List catalogs = new ArrayList(); - for (String key : catalogMap.keySet()) { - MetaCatalog metaCatalog = new MetaCatalog(key, new ArrayList(catalogMap.get(key))); - catalogs.add(metaCatalog); - } - - return new MetaProject(project, catalogs); - } catch (HttpException e) { - logger.error(e.getLocalizedMessage(), e); - throw new ConnectionException(e.getLocalizedMessage()); - } catch (IOException e) { - logger.error(e.getLocalizedMessage(), e); - throw new ConnectionException(e.getLocalizedMessage()); - } - } - - private MetaTable createNewTable(TableMetaStub tableMetaStub, List columns) { - MetaTable table = new MetaTable(tableMetaStub.getTABLE_CAT(), tableMetaStub.getTABLE_SCHEM(), tableMetaStub.getTABLE_NAME(), tableMetaStub.getTABLE_TYPE(), tableMetaStub.getREMARKS(), tableMetaStub.getTYPE_CAT(), tableMetaStub.getTYPE_SCHEM(), tableMetaStub.getTYPE_NAME(), tableMetaStub.getSELF_REFERENCING_COL_NAME(), tableMetaStub.getREF_GENERATION(), columns); - return table; - } - - private MetaColumn createNewColumn(ColumnMetaStub columnMetaStub) { - MetaColumn column = new MetaColumn(columnMetaStub.getTABLE_CAT(), columnMetaStub.getTABLE_SCHEM(), columnMetaStub.getTABLE_NAME(), columnMetaStub.getCOLUMN_NAME(), columnMetaStub.getDATA_TYPE(), columnMetaStub.getTYPE_NAME(), columnMetaStub.getCOLUMN_SIZE(), columnMetaStub.getBUFFER_LENGTH(), columnMetaStub.getDECIMAL_DIGITS(), columnMetaStub.getNUM_PREC_RADIX(), columnMetaStub.getNULLABLE(), columnMetaStub.getREMARKS(), columnMetaStub.getCOLUMN_DEF(), columnMetaStub.getSQL_DATA_TYPE(), columnMetaStub.getSQL_DATETIME_SUB(), columnMetaStub.getCHAR_OCTET_LENGTH(), columnMetaStub.getORDINAL_POSITION(), columnMetaStub.getIS_NULLABLE(), columnMetaStub.getSCOPE_CATLOG(), columnMetaStub.getSCOPE_TABLE(), columnMetaStub.getSOURCE_DATA_TYPE(), columnMetaStub.getIS_AUTOINCREMENT(), columnMetaStub.getSCOPE_SCHEMA()); - return column; - } - - @Override - public DataSet query(AvaticaStatement statement, String sql) throws SQLException { - SQLResponseStub queryRes = null; - - List params = null; - if (statement instanceof KylinJdbc41PreparedStatement) { - params = genPrestateStates(statement); - } - - queryRes = runKylinQuery(sql, params); - - List metas = genColumnMeta(queryRes); - List data = genResultData(queryRes, metas); - - return new DataSet(metas, new KylinEnumerator(data)); - } - - /** - * @param queryRes - * @param metas - * @return - */ - private List genResultData(SQLResponseStub queryRes, List metas) { - List data = new ArrayList(); - for (String[] result : queryRes.getResults()) { - Object[] row = new Object[result.length]; - - for (int i = 0; i < result.length; i++) { - ColumnMetaData meta = metas.get(i); - row[i] = SQLTypeMap.wrapObject(result[i], meta.type.type); - } - - data.add(row); - } - return data; - } - - /** - * @param statement - * @param params - */ - private List genPrestateStates(AvaticaStatement statement) { - List params = new ArrayList(); - List values = ((KylinJdbc41PreparedStatement) statement).getParameterValues(); - - for (int i = 0; i < values.size(); i++) { - Object value = values.get(i); - params.add(new StateParam(value.getClass().getCanonicalName(), String.valueOf(value))); - } - - return params; - } - - /** - * @param queryRes - * @return - */ - private List genColumnMeta(SQLResponseStub queryRes) { - List metas = new ArrayList(); - for (int i = 0; i < queryRes.getColumnMetas().size(); i++) { - SQLResponseStub.ColumnMetaStub scm = queryRes.getColumnMetas().get(i); - ScalarType type = ColumnMetaData.scalar(scm.getColumnType(), scm.getColumnTypeName(), Rep.of(SQLTypeMap.convert(scm.getColumnType()))); - - ColumnMetaData meta = new ColumnMetaData(i, scm.isAutoIncrement(), scm.isCaseSensitive(), scm.isSearchable(), scm.isCurrency(), scm.getIsNullable(), scm.isSigned(), scm.getDisplaySize(), scm.getLabel(), scm.getName(), scm.getSchemaName(), scm.getPrecision(), scm.getScale(), scm.getTableName(), scm.getSchemaName(), type, scm.isReadOnly(), scm.isWritable(), scm.isWritable(), null); - - metas.add(meta); - } - - return metas; - } - - /** - * @param sql - * @return - * @throws IOException - */ - private SQLResponseStub runKylinQuery(String sql, List params) throws SQLException { - String url = conn.getQueryUrl(); - String project = conn.getProject(); - QueryRequest request = null; - - if (null != params) { - request = new PreQueryRequest(); - ((PreQueryRequest) request).setParams(params); - url += "/prestate"; - } else { - request = new QueryRequest(); - } - request.setSql(sql); - request.setProject(project); - - PostMethod post = new PostMethod(url); - addPostHeaders(post); - HttpClient httpClient = new HttpClient(); - if (conn.getQueryUrl().toLowerCase().startsWith("https://")) { - registerSsl(); - } - - String postBody = null; - ObjectMapper mapper = new ObjectMapper(); - try { - postBody = mapper.writeValueAsString(request); - logger.debug("Post body:\n " + postBody); - } catch (JsonProcessingException e) { - logger.error(e.getLocalizedMessage(), e); - } - String response = null; - SQLResponseStub queryRes = null; - - try { - StringRequestEntity requestEntity = new StringRequestEntity(postBody, "application/json", "UTF-8"); - post.setRequestEntity(requestEntity); - - httpClient.executeMethod(post); - response = post.getResponseBodyAsString(); - - if (post.getStatusCode() != 200 && post.getStatusCode() != 201) { - logger.error("Failed to query", response); - throw new SQLException(response); - } - - queryRes = new ObjectMapper().readValue(response, SQLResponseStub.class); - - } catch (HttpException e) { - logger.error(e.getLocalizedMessage(), e); - throw new SQLException(e.getLocalizedMessage()); - } catch (IOException e) { - logger.error(e.getLocalizedMessage(), e); - throw new SQLException(e.getLocalizedMessage()); - } - - return queryRes; - } - - private void addPostHeaders(HttpMethodBase method) { - method.addRequestHeader("Accept", "application/json, text/plain, */*"); - method.addRequestHeader("Content-Type", "application/json"); - method.addRequestHeader("Authorization", "Basic " + conn.getBasicAuthHeader()); - } - - private void registerSsl() { - Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) new DefaultSslProtocolSocketFactory(), 443)); - } - - public class QueryRequest { - private String sql; - private String project; - - public String getSql() { - return sql; - } - - public void setSql(String sql) { - this.sql = sql; - } - - public String getProject() { - return project; - } - - public void setProject(String project) { - this.project = project; - } - } - - public class PreQueryRequest extends QueryRequest { - private List params; - - public List getParams() { - return params; - } - - public void setParams(List params) { - this.params = params; - } - } - - public class StateParam { - private String className; - private String value; - - public StateParam(String className, String value) { - super(); - this.className = className; - this.value = value; - } - - public String getClassName() { - return className; - } - - public void setClazz(String className) { - this.className = className; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinColumnMetaData.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinColumnMetaData.java deleted file mode 100644 index 32d0e14..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/KylinColumnMetaData.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.stub; - -import java.sql.DatabaseMetaData; - -import net.hydromatic.avatica.ColumnMetaData; - -/** - * @author xduo - * - */ -public class KylinColumnMetaData extends ColumnMetaData { - - public KylinColumnMetaData(int ordinal, boolean autoIncrement, boolean caseSensitive, boolean searchable, boolean currency, int nullable, boolean signed, int displaySize, String label, String columnName, String schemaName, int precision, int scale, String tableName, String catalogName, AvaticaType type, boolean readOnly, boolean writable, boolean definitelyWritable, String columnClassName) { - super(ordinal, autoIncrement, caseSensitive, searchable, currency, nullable, signed, displaySize, label, columnName, schemaName, precision, scale, tableName, catalogName, type, readOnly, writable, definitelyWritable, columnClassName); - } - - public static ColumnMetaData dummy(int ordinal, String label, String columnName, AvaticaType type, boolean nullable) { - return new ColumnMetaData(ordinal, false, true, false, false, nullable ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls, true, -1, label, columnName, null, -1, -1, null, null, type, true, false, false, null); - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/RemoteClient.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/RemoteClient.java deleted file mode 100644 index daa9d9d..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/RemoteClient.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.stub; - -import java.sql.SQLException; - -import net.hydromatic.avatica.AvaticaStatement; - -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaProject; - -/** - * Remote query stub of kylin restful service - * - * @author xduo - * - */ -public interface RemoteClient { - - /** - * Connect to kylin restful service. ConnectionException will be thrown if - * authentication failed. - * - * @throws ConnectionException - */ - public void connect() throws ConnectionException; - - /** - * @param project - * @return - */ - public MetaProject getMetadata(String project) throws ConnectionException; - - /** - * Run query - * - * @param statement - * @param sql - * @return - * @throws SQLException - */ - public DataSet query(AvaticaStatement statement, String sql) throws SQLException; - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/SQLResponseStub.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/SQLResponseStub.java deleted file mode 100644 index 24b5783..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/SQLResponseStub.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.stub; - -import java.io.Serializable; -import java.util.List; - -/** - * @author xduo - * - */ -public class SQLResponseStub implements Serializable { - private static final long serialVersionUID = 1L; - - // private static final Logger logger = - // LoggerFactory.getLogger(SQLResponse.class); - - // the data type for each column - private List columnMetas; - - // the results rows, each row contains several columns - private List results; - - private String cube; - - // if not select query, only return affected row count - private int affectedRowCount; - - // if isException, the detailed exception message - private String exceptionMessage; - - private boolean isException; - - private long duration; - - private boolean isPartial = false; - - private long totalScanCount; - - private boolean hitCache = false; - - public SQLResponseStub() { - } - - public List getColumnMetas() { - return columnMetas; - } - - public void setColumnMetas(List columnMetas) { - this.columnMetas = columnMetas; - } - - public List getResults() { - return results; - } - - public void setResults(List results) { - this.results = results; - } - - public String getCube() { - return cube; - } - - public void setCube(String cube) { - this.cube = cube; - } - - public int getAffectedRowCount() { - return affectedRowCount; - } - - public void setAffectedRowCount(int affectedRowCount) { - this.affectedRowCount = affectedRowCount; - } - - public boolean getIsException() { - return isException; - } - - public void setIsException(boolean isException) { - this.isException = isException; - } - - public String getExceptionMessage() { - return exceptionMessage; - } - - public void setExceptionMessage(String exceptionMessage) { - this.exceptionMessage = exceptionMessage; - } - - public long getDuration() { - return duration; - } - - public void setDuration(long duration) { - this.duration = duration; - } - - public boolean isPartial() { - return isPartial; - } - - public void setPartial(boolean isPartial) { - this.isPartial = isPartial; - } - - public long getTotalScanCount() { - return totalScanCount; - } - - public void setTotalScanCount(long totalScanCount) { - this.totalScanCount = totalScanCount; - } - - public boolean isHitCache() { - return hitCache; - } - - public void setHitCache(boolean hitCache) { - this.hitCache = hitCache; - } - - public static long getSerialversionuid() { - return serialVersionUID; - } - - public static class ColumnMetaStub { - - private boolean isAutoIncrement; - private boolean isCaseSensitive; - private boolean isSearchable; - private boolean isCurrency; - private int isNullable;// 0:nonull, 1:nullable, 2: nullableunknown - private boolean isSigned; - private int displaySize; - private String label;// AS keyword - private String name; - private String schemaName; - private String catelogName; - private String tableName; - private int precision; - private int scale; - private int columnType;// as defined in java.sql.Types - private String columnTypeName; - private boolean isReadOnly; - private boolean isWritable; - private boolean isDefinitelyWritable; - - public ColumnMetaStub() { - } - - public boolean isAutoIncrement() { - return isAutoIncrement; - } - - public void setAutoIncrement(boolean isAutoIncrement) { - this.isAutoIncrement = isAutoIncrement; - } - - public boolean isCaseSensitive() { - return isCaseSensitive; - } - - public void setCaseSensitive(boolean isCaseSensitive) { - this.isCaseSensitive = isCaseSensitive; - } - - public boolean isSearchable() { - return isSearchable; - } - - public void setSearchable(boolean isSearchable) { - this.isSearchable = isSearchable; - } - - public boolean isCurrency() { - return isCurrency; - } - - public void setCurrency(boolean isCurrency) { - this.isCurrency = isCurrency; - } - - public int getIsNullable() { - return isNullable; - } - - public void setIsNullable(int isNullable) { - this.isNullable = isNullable; - } - - public boolean isSigned() { - return isSigned; - } - - public void setSigned(boolean isSigned) { - this.isSigned = isSigned; - } - - public int getDisplaySize() { - return displaySize; - } - - public void setDisplaySize(int displaySize) { - this.displaySize = displaySize; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getSchemaName() { - return schemaName; - } - - public void setSchemaName(String schemaName) { - this.schemaName = schemaName; - } - - public String getCatelogName() { - return catelogName; - } - - public void setCatelogName(String catelogName) { - this.catelogName = catelogName; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(String tableName) { - this.tableName = tableName; - } - - public int getPrecision() { - return precision; - } - - public void setPrecision(int precision) { - this.precision = precision; - } - - public int getScale() { - return scale; - } - - public void setScale(int scale) { - this.scale = scale; - } - - public int getColumnType() { - return columnType; - } - - public void setColumnType(int columnType) { - this.columnType = columnType; - } - - public String getColumnTypeName() { - return columnTypeName; - } - - public void setColumnTypeName(String columnTypeName) { - this.columnTypeName = columnTypeName; - } - - public boolean isReadOnly() { - return isReadOnly; - } - - public void setReadOnly(boolean isReadOnly) { - this.isReadOnly = isReadOnly; - } - - public boolean isWritable() { - return isWritable; - } - - public void setWritable(boolean isWritable) { - this.isWritable = isWritable; - } - - public boolean isDefinitelyWritable() { - return isDefinitelyWritable; - } - - public void setDefinitelyWritable(boolean isDefinitelyWritable) { - this.isDefinitelyWritable = isDefinitelyWritable; - } - - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/TableMetaStub.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/TableMetaStub.java deleted file mode 100644 index 7225cf0..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/stub/TableMetaStub.java +++ /dev/null @@ -1,329 +0,0 @@ -package com.kylinolap.kylin.jdbc.stub; - -import java.util.ArrayList; -import java.util.List; - -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * @author xduo - * - */ -public class TableMetaStub { - - private static final long serialVersionUID = 1L; - private String TABLE_CAT; - private String TABLE_SCHEM; - private String TABLE_NAME; - private String TABLE_TYPE; - private String REMARKS; - private String TYPE_CAT; - private String TYPE_SCHEM; - private String TYPE_NAME; - private String SELF_REFERENCING_COL_NAME; - private String REF_GENERATION; - @JsonProperty("columns") - private List columns = new ArrayList(); - - public String getTABLE_CAT() { - return TABLE_CAT; - } - - public void setTABLE_CAT(String tABLE_CAT) { - TABLE_CAT = tABLE_CAT; - } - - public String getTABLE_SCHEM() { - return TABLE_SCHEM; - } - - public void setTABLE_SCHEM(String tABLE_SCHEM) { - TABLE_SCHEM = tABLE_SCHEM; - } - - public String getTABLE_NAME() { - return TABLE_NAME; - } - - public void setTABLE_NAME(String tABLE_NAME) { - TABLE_NAME = tABLE_NAME; - } - - public String getTABLE_TYPE() { - return TABLE_TYPE; - } - - public void setTABLE_TYPE(String tABLE_TYPE) { - TABLE_TYPE = tABLE_TYPE; - } - - public String getREMARKS() { - return REMARKS; - } - - public void setREMARKS(String rEMARKS) { - REMARKS = rEMARKS; - } - - public String getTYPE_CAT() { - return TYPE_CAT; - } - - public void setTYPE_CAT(String tYPE_CAT) { - TYPE_CAT = tYPE_CAT; - } - - public String getTYPE_SCHEM() { - return TYPE_SCHEM; - } - - public void setTYPE_SCHEM(String tYPE_SCHEM) { - TYPE_SCHEM = tYPE_SCHEM; - } - - public String getTYPE_NAME() { - return TYPE_NAME; - } - - public void setTYPE_NAME(String tYPE_NAME) { - TYPE_NAME = tYPE_NAME; - } - - public String getSELF_REFERENCING_COL_NAME() { - return SELF_REFERENCING_COL_NAME; - } - - public void setSELF_REFERENCING_COL_NAME(String sELF_REFERENCING_COL_NAME) { - SELF_REFERENCING_COL_NAME = sELF_REFERENCING_COL_NAME; - } - - public String getREF_GENERATION() { - return REF_GENERATION; - } - - public void setREF_GENERATION(String rEF_GENERATION) { - REF_GENERATION = rEF_GENERATION; - } - - public List getColumns() { - return columns; - } - - public void setColumns(List columns) { - this.columns = columns; - } - - public static long getSerialversionuid() { - return serialVersionUID; - } - - public static class ColumnMetaStub { - private String TABLE_CAT; - private String TABLE_SCHEM; - private String TABLE_NAME; - private String COLUMN_NAME; - private int DATA_TYPE; - private String TYPE_NAME; - private int COLUMN_SIZE; - private int BUFFER_LENGTH; - private int DECIMAL_DIGITS; - private int NUM_PREC_RADIX; - private int NULLABLE; - private String REMARKS; - private String COLUMN_DEF; - private int SQL_DATA_TYPE; - private int SQL_DATETIME_SUB; - private int CHAR_OCTET_LENGTH; - private int ORDINAL_POSITION; - private String IS_NULLABLE; - private String SCOPE_CATLOG; - private String SCOPE_SCHEMA; - private String SCOPE_TABLE; - private short SOURCE_DATA_TYPE; - private String IS_AUTOINCREMENT; - - public String getTABLE_CAT() { - return TABLE_CAT; - } - - public void setTABLE_CAT(String tABLE_CAT) { - TABLE_CAT = tABLE_CAT; - } - - public String getTABLE_SCHEM() { - return TABLE_SCHEM; - } - - public void setTABLE_SCHEM(String tABLE_SCHEM) { - TABLE_SCHEM = tABLE_SCHEM; - } - - public String getTABLE_NAME() { - return TABLE_NAME; - } - - public void setTABLE_NAME(String tABLE_NAME) { - TABLE_NAME = tABLE_NAME; - } - - public String getCOLUMN_NAME() { - return COLUMN_NAME; - } - - public void setCOLUMN_NAME(String cOLUMN_NAME) { - COLUMN_NAME = cOLUMN_NAME; - } - - public int getDATA_TYPE() { - return DATA_TYPE; - } - - public void setDATA_TYPE(int dATA_TYPE) { - DATA_TYPE = dATA_TYPE; - } - - public String getTYPE_NAME() { - return TYPE_NAME; - } - - public void setTYPE_NAME(String tYPE_NAME) { - TYPE_NAME = tYPE_NAME; - } - - public int getCOLUMN_SIZE() { - return COLUMN_SIZE; - } - - public void setCOLUMN_SIZE(int cOLUMN_SIZE) { - COLUMN_SIZE = cOLUMN_SIZE; - } - - public int getBUFFER_LENGTH() { - return BUFFER_LENGTH; - } - - public void setBUFFER_LENGTH(int bUFFER_LENGTH) { - BUFFER_LENGTH = bUFFER_LENGTH; - } - - public int getDECIMAL_DIGITS() { - return DECIMAL_DIGITS; - } - - public void setDECIMAL_DIGITS(int dECIMAL_DIGITS) { - DECIMAL_DIGITS = dECIMAL_DIGITS; - } - - public int getNUM_PREC_RADIX() { - return NUM_PREC_RADIX; - } - - public void setNUM_PREC_RADIX(int nUM_PREC_RADIX) { - NUM_PREC_RADIX = nUM_PREC_RADIX; - } - - public int getNULLABLE() { - return NULLABLE; - } - - public void setNULLABLE(int nULLABLE) { - NULLABLE = nULLABLE; - } - - public String getREMARKS() { - return REMARKS; - } - - public void setREMARKS(String rEMARKS) { - REMARKS = rEMARKS; - } - - public String getCOLUMN_DEF() { - return COLUMN_DEF; - } - - public void setCOLUMN_DEF(String cOLUMN_DEF) { - COLUMN_DEF = cOLUMN_DEF; - } - - public int getSQL_DATA_TYPE() { - return SQL_DATA_TYPE; - } - - public void setSQL_DATA_TYPE(int sQL_DATA_TYPE) { - SQL_DATA_TYPE = sQL_DATA_TYPE; - } - - public int getSQL_DATETIME_SUB() { - return SQL_DATETIME_SUB; - } - - public void setSQL_DATETIME_SUB(int sQL_DATETIME_SUB) { - SQL_DATETIME_SUB = sQL_DATETIME_SUB; - } - - public int getCHAR_OCTET_LENGTH() { - return CHAR_OCTET_LENGTH; - } - - public void setCHAR_OCTET_LENGTH(int cHAR_OCTET_LENGTH) { - CHAR_OCTET_LENGTH = cHAR_OCTET_LENGTH; - } - - public int getORDINAL_POSITION() { - return ORDINAL_POSITION; - } - - public void setORDINAL_POSITION(int oRDINAL_POSITION) { - ORDINAL_POSITION = oRDINAL_POSITION; - } - - public String getIS_NULLABLE() { - return IS_NULLABLE; - } - - public void setIS_NULLABLE(String iS_NULLABLE) { - IS_NULLABLE = iS_NULLABLE; - } - - public String getSCOPE_CATLOG() { - return SCOPE_CATLOG; - } - - public void setSCOPE_CATLOG(String sCOPE_CATLOG) { - SCOPE_CATLOG = sCOPE_CATLOG; - } - - public String getSCOPE_SCHEMA() { - return SCOPE_SCHEMA; - } - - public void setSCOPE_SCHEMA(String sCOPE_SCHEMA) { - SCOPE_SCHEMA = sCOPE_SCHEMA; - } - - public String getSCOPE_TABLE() { - return SCOPE_TABLE; - } - - public void setSCOPE_TABLE(String sCOPE_TABLE) { - SCOPE_TABLE = sCOPE_TABLE; - } - - public short getSOURCE_DATA_TYPE() { - return SOURCE_DATA_TYPE; - } - - public void setSOURCE_DATA_TYPE(short sOURCE_DATA_TYPE) { - SOURCE_DATA_TYPE = sOURCE_DATA_TYPE; - } - - public String getIS_AUTOINCREMENT() { - return IS_AUTOINCREMENT; - } - - public void setIS_AUTOINCREMENT(String iS_AUTOINCREMENT) { - this.IS_AUTOINCREMENT = iS_AUTOINCREMENT; - } - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultSslProtocolSocketFactory.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultSslProtocolSocketFactory.java deleted file mode 100644 index 48724a7..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultSslProtocolSocketFactory.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.util; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; - -import org.apache.commons.httpclient.ConnectTimeoutException; -import org.apache.commons.httpclient.HttpClientError; -import org.apache.commons.httpclient.params.HttpConnectionParams; -import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory; -import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author xduo - * - */ -public class DefaultSslProtocolSocketFactory implements SecureProtocolSocketFactory { - /** Log object for this class. */ - private static Logger LOG = LoggerFactory.getLogger(DefaultSslProtocolSocketFactory.class); - private SSLContext sslcontext = null; - - /** - * Constructor for DefaultSslProtocolSocketFactory. - */ - public DefaultSslProtocolSocketFactory() { - super(); - } - - /** - * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) - */ - public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException, UnknownHostException { - return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort); - } - - /** - * Attempts to get a new socket connection to the given host within the - * given time limit. - * - *

    - * To circumvent the limitations of older JREs that do not support connect - * timeout a controller thread is executed. The controller thread attempts - * to create a new socket within the given limit of time. If socket - * constructor does not return until the timeout expires, the controller - * terminates and throws an {@link ConnectTimeoutException} - *

    - * - * @param host - * the host name/IP - * @param port - * the port on the host - * @param localAddress - * the local host name/IP to bind the socket to - * @param localPort - * the port on the local machine - * @param params - * {@link HttpConnectionParams Http connection parameters} - * - * @return Socket a new socket - * - * @throws IOException - * if an I/O error occurs while creating the socket - * @throws UnknownHostException - * if the IP address of the host cannot be determined - * @throws ConnectTimeoutException - * DOCUMENT ME! - * @throws IllegalArgumentException - * DOCUMENT ME! - */ - public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort, final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException { - if (params == null) { - throw new IllegalArgumentException("Parameters may not be null"); - } - - int timeout = params.getConnectionTimeout(); - - if (timeout == 0) { - return createSocket(host, port, localAddress, localPort); - } else { - // To be eventually deprecated when migrated to Java 1.4 or above - return ControllerThreadSocketFactory.createSocket(this, host, port, localAddress, localPort, timeout); - } - } - - /** - * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) - */ - public Socket createSocket(String host, int port) throws IOException, UnknownHostException { - return getSSLContext().getSocketFactory().createSocket(host, port); - } - - /** - * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) - */ - public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { - return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose); - } - - public boolean equals(Object obj) { - return ((obj != null) && obj.getClass().equals(DefaultX509TrustManager.class)); - } - - public int hashCode() { - return DefaultX509TrustManager.class.hashCode(); - } - - private static SSLContext createEasySSLContext() { - try { - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, new TrustManager[] { new DefaultX509TrustManager(null) }, null); - - return context; - } catch (Exception e) { - LOG.error(e.getMessage(), e); - throw new HttpClientError(e.toString()); - } - } - - private SSLContext getSSLContext() { - if (this.sslcontext == null) { - this.sslcontext = createEasySSLContext(); - } - - return this.sslcontext; - } -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultX509TrustManager.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultX509TrustManager.java deleted file mode 100644 index 48f2d66..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/DefaultX509TrustManager.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.util; - -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author xduo - * - */ -public class DefaultX509TrustManager implements X509TrustManager { - - /** Log object for this class. */ - private static Logger LOG = LoggerFactory.getLogger(DefaultX509TrustManager.class); - private X509TrustManager standardTrustManager = null; - - /** - * Constructor for DefaultX509TrustManager. - * - */ - public DefaultX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { - super(); - - TrustManagerFactory factory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - factory.init(keystore); - - TrustManager[] trustmanagers = factory.getTrustManagers(); - - if (trustmanagers.length == 0) { - throw new NoSuchAlgorithmException("SunX509 trust manager not supported"); - } - - this.standardTrustManager = (X509TrustManager) trustmanagers[0]; - } - - public X509Certificate[] getAcceptedIssuers() { - return this.standardTrustManager.getAcceptedIssuers(); - } - - public boolean isClientTrusted(X509Certificate[] certificates) { - return true; - // return this.standardTrustManager.isClientTrusted(certificates); - } - - public boolean isServerTrusted(X509Certificate[] certificates) { - if ((certificates != null) && LOG.isDebugEnabled()) { - LOG.debug("Server certificate chain:"); - - for (int i = 0; i < certificates.length; i++) { - if (LOG.isDebugEnabled()) { - LOG.debug("X509Certificate[" + i + "]=" + certificates[i]); - } - } - } - - if ((certificates != null) && (certificates.length == 1)) { - X509Certificate certificate = certificates[0]; - - try { - certificate.checkValidity(); - } catch (CertificateException e) { - LOG.error(e.toString()); - - return false; - } - - return true; - } else { - return true; - // return this.standardTrustManager.isServerTrusted(certificates); - } - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - // TODO Auto-generated method stub - - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - // TODO Auto-generated method stub - - } - -} diff --git a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/SQLTypeMap.java b/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/SQLTypeMap.java deleted file mode 100644 index e083771..0000000 --- a/jdbc/src/main/java/com/kylinolap/kylin/jdbc/util/SQLTypeMap.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2013-2014 eBay Software Foundation - * - * Licensed 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.kylinolap.kylin.jdbc.util; - -import java.math.BigDecimal; -import java.sql.Date; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.HashMap; -import java.util.Map; - -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.avatica.ColumnMetaData.Rep; - -import com.kylinolap.kylin.jdbc.stub.KylinColumnMetaData; - -/** - * Util class to handle type gap between sql types and java types. - * - * @author xduo - * - */ -public class SQLTypeMap { - - public final static Map schemaMetaTypeMapping = new HashMap(); - - public final static Map columnMetaTypeMapping = new HashMap(); - - public final static Map tableMetaTypeMapping = new HashMap(); - - static { - schemaMetaTypeMapping.put("TABLE_CAT", KylinColumnMetaData.dummy(0, "TABLE_SCHEM", "TABLE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - schemaMetaTypeMapping.put("TABLE_SCHEM", KylinColumnMetaData.dummy(1, "TABLE_CATALOG", "TABLE_CATALOG", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - - tableMetaTypeMapping.put("TABLE_CAT", KylinColumnMetaData.dummy(0, "TABLE_CAT", "TABLE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("TABLE_SCHEM", KylinColumnMetaData.dummy(1, "TABLE_SCHEM", "TABLE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("TABLE_NAME", KylinColumnMetaData.dummy(2, "TABLE_NAME", "TABLE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("TABLE_TYPE", KylinColumnMetaData.dummy(3, "TABLE_TYPE", "TABLE_TYPE", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("REMARKS", KylinColumnMetaData.dummy(4, "REMARKS", "REMARKS", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("TYPE_CAT", KylinColumnMetaData.dummy(5, "TYPE_CAT", "TYPE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("TYPE_SCHEM", KylinColumnMetaData.dummy(6, "TYPE_SCHEM", "TYPE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("TYPE_NAME", KylinColumnMetaData.dummy(7, "TYPE_NAME", "TYPE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("SELF_REFERENCING_COL_NAME", KylinColumnMetaData.dummy(8, "SELF_REFERENCING_COL_NAME", "SELF_REFERENCING_COL_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - tableMetaTypeMapping.put("REF_GENERATION", KylinColumnMetaData.dummy(9, "REF_GENERATION", "REF_GENERATION", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - - columnMetaTypeMapping.put("TABLE_CAT", KylinColumnMetaData.dummy(0, "TABLE_CAT", "TABLE_CAT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("TABLE_SCHEM", KylinColumnMetaData.dummy(1, "TABLE_SCHEM", "TABLE_SCHEM", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("TABLE_NAME", KylinColumnMetaData.dummy(2, "TABLE_NAME", "TABLE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("COLUMN_NAME", KylinColumnMetaData.dummy(3, "COLUMN_NAME", "COLUMN_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("DATA_TYPE", KylinColumnMetaData.dummy(4, "DATA_TYPE", "DATA_TYPE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("TYPE_NAME", KylinColumnMetaData.dummy(5, "TYPE_NAME", "TYPE_NAME", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("COLUMN_SIZE", KylinColumnMetaData.dummy(6, "COLUMN_SIZE", "COLUMN_SIZE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("BUFFER_LENGTH", KylinColumnMetaData.dummy(7, "BUFFER_LENGTH", "BUFFER_LENGTH", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("DECIMAL_DIGITS", KylinColumnMetaData.dummy(8, "DECIMAL_DIGITS", "DECIMAL_DIGITS", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("NUM_PREC_RADIX", KylinColumnMetaData.dummy(9, "NUM_PREC_RADIX", "NUM_PREC_RADIX", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("NULLABLE", KylinColumnMetaData.dummy(10, "NULLABLE", "NULLABLE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("REMARKS", KylinColumnMetaData.dummy(11, "REMARKS", "REMARKS", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("COLUMN_DEF", KylinColumnMetaData.dummy(12, "COLUMN_DEF", "COLUMN_DEF", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("SQL_DATA_TYPE", KylinColumnMetaData.dummy(13, "SQL_DATA_TYPE", "SQL_DATA_TYPE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("SQL_DATETIME_SUB", KylinColumnMetaData.dummy(14, "SQL_DATETIME_SUB", "SQL_DATETIME_SUB", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("CHAR_OCTET_LENGTH", KylinColumnMetaData.dummy(15, "CHAR_OCTET_LENGTH", "CHAR_OCTET_LENGTH", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("ORDINAL_POSITION", KylinColumnMetaData.dummy(16, "ORDINAL_POSITION", "ORDINAL_POSITION", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("IS_NULLABLE", KylinColumnMetaData.dummy(17, "IS_NULLABLE", "IS_NULLABLE", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("SCOPE_CATALOG", KylinColumnMetaData.dummy(18, "SCOPE_CATALOG", "SCOPE_CATALOG", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("SCOPE_TABLE", KylinColumnMetaData.dummy(19, "SCOPE_TABLE", "SCOPE_TABLE", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("SOURCE_DATA_TYPE", KylinColumnMetaData.dummy(20, "SOURCE_DATA_TYPE", "SOURCE_DATA_TYPE", ColumnMetaData.scalar(Types.INTEGER, "integer", Rep.INTEGER), true)); - columnMetaTypeMapping.put("IS_AUTOINCREMENT", KylinColumnMetaData.dummy(21, "IS_AUTOINCREMENT", "IS_AUTOINCREMENT", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - columnMetaTypeMapping.put("IS_GENERATEDCOLUMN", KylinColumnMetaData.dummy(22, "IS_GENERATEDCOLUMN", "IS_GENERATEDCOLUMN", ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - } - - @SuppressWarnings("rawtypes") - public static Class convert(int sqlType) { - Class result = Object.class; - - switch (sqlType) { - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - result = String.class; - break; - case Types.NUMERIC: - case Types.DECIMAL: - result = BigDecimal.class; - break; - case Types.BIT: - result = Boolean.class; - break; - case Types.TINYINT: - result = Byte.class; - break; - case Types.SMALLINT: - result = Short.class; - break; - case Types.INTEGER: - result = Integer.class; - break; - case Types.BIGINT: - result = Long.class; - break; - case Types.REAL: - case Types.FLOAT: - case Types.DOUBLE: - result = Double.class; - break; - case Types.BINARY: - case Types.VARBINARY: - case Types.LONGVARBINARY: - result = Byte[].class; - break; - case Types.DATE: - result = Date.class; - break; - case Types.TIME: - result = Time.class; - break; - case Types.TIMESTAMP: - result = Timestamp.class; - break; - } - - return result; - } - - public static Object wrapObject(String value, int sqlType) { - if (null == value) { - return null; - } - - switch (sqlType) { - case Types.CHAR: - case Types.VARCHAR: - case Types.LONGVARCHAR: - return value; - case Types.NUMERIC: - case Types.DECIMAL: - return new BigDecimal(value); - case Types.BIT: - return Boolean.parseBoolean(value); - case Types.TINYINT: - return Byte.valueOf(value); - case Types.SMALLINT: - return Short.valueOf(value); - case Types.INTEGER: - return Integer.parseInt(value); - case Types.BIGINT: - case Types.REAL: - case Types.FLOAT: - case Types.DOUBLE: - return Long.parseLong(value); - case Types.BINARY: - case Types.VARBINARY: - case Types.LONGVARBINARY: - return value.getBytes(); - case Types.DATE: - return Date.valueOf(value); - case Types.TIME: - return Time.valueOf(value); - case Types.TIMESTAMP: - return Timestamp.valueOf(value); - } - - return value; - } -} diff --git a/jdbc/src/test/java/com/kylinolap/jdbc/DriverTest.java b/jdbc/src/test/java/com/kylinolap/jdbc/DriverTest.java new file mode 100644 index 0000000..dbc4551 --- /dev/null +++ b/jdbc/src/test/java/com/kylinolap/jdbc/DriverTest.java @@ -0,0 +1,158 @@ +package com.kylinolap.jdbc; + +import static org.junit.Assert.*; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Properties; + +import org.junit.Ignore; +import org.junit.Test; + +import com.kylinolap.jdbc.Driver; + +/** + * Unit test for Driver. + * + * @author xduo + * + */ +public class DriverTest { + + @Test + public void testStatementWithMockData() throws SQLException { + Driver driver = new DummyDriver(); + + Connection conn = driver.connect("jdbc:kylin://test_url/test_db", null); + + ResultSet tables = conn.getMetaData().getTables(null, null, null, null); + while (tables.next()) { + for (int i = 0; i < 10; i++) { + assertEquals("dummy", tables.getString(i + 1)); + } + } + + Statement state = conn.createStatement(); + ResultSet resultSet = state.executeQuery("select * from test_table"); + + ResultSetMetaData metadata = resultSet.getMetaData(); + assertEquals(12, metadata.getColumnType(1)); + assertEquals("varchar", metadata.getColumnTypeName(1)); + assertEquals(1, metadata.isNullable(1)); + + while (resultSet.next()) { + assertEquals("foo", resultSet.getString(1)); + assertEquals("bar", resultSet.getString(2)); + assertEquals("tool", resultSet.getString(3)); + } + } + + @Test + public void testPreStatementWithMockData() throws SQLException { + Driver driver = new DummyDriver(); + + Connection conn = driver.connect("jdbc:kylin://test_url/test_db", null); + PreparedStatement state = conn.prepareStatement("select * from test_table where id=?"); + state.setInt(1, 10); + ResultSet resultSet = state.executeQuery(); + + ResultSetMetaData metadata = resultSet.getMetaData(); + assertEquals(12, metadata.getColumnType(1)); + assertEquals("varchar", metadata.getColumnTypeName(1)); + assertEquals(1, metadata.isNullable(1)); + + while (resultSet.next()) { + assertEquals("foo", resultSet.getString(1)); + assertEquals("bar", resultSet.getString(2)); + assertEquals("tool", resultSet.getString(3)); + } + } + + @Ignore + @Test + public void testWithCubeData() throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { + Driver driver = (Driver) Class.forName("com.kylinolap.kylin.jdbc.Driver").newInstance(); + Properties info = new Properties(); + info.put("user", ""); + info.put("password", ""); + Connection conn = driver.connect("jdbc:kylin://localhost/default", info); + + ResultSet catalogs = conn.getMetaData().getCatalogs(); + while (catalogs.next()) { + System.out.println(catalogs.getString("TABLE_CAT")); + } + + ResultSet schemas = conn.getMetaData().getSchemas(); + while (schemas.next()) { + System.out.println(schemas.getString(1)); + System.out.println(schemas.getString(2)); + } + + ResultSet tables = conn.getMetaData().getTables(null, null, null, null); + while (tables.next()) { + String tableName = tables.getString(3); + assertEquals(tables.getString("TABLE_NAME"), tableName); + ResultSet columns = conn.getMetaData().getColumns(null, null, tableName, null); + + while (columns.next()) { + System.out.println(columns.getString("COLUMN_NAME")); + String column = ""; + for (int i = 0; i < 23; i++) { + column += columns.getString(i + 1) + ", "; + } + + System.out.println("Column in table " + tableName + ": " + column); + } + } + + for (int j = 0; j < 3; j++) { + Statement state = conn.createStatement(); + ResultSet resultSet = state.executeQuery("select * from test_kylin_fact"); + + ResultSetMetaData metadata = resultSet.getMetaData(); + System.out.println("Metadata:"); + + for (int i = 0; i < metadata.getColumnCount(); i++) { + String metaStr = metadata.getCatalogName(i + 1) + " " + metadata.getColumnClassName(i + 1) + " " + metadata.getColumnDisplaySize(i + 1) + " " + metadata.getColumnLabel(i + 1) + " " + metadata.getColumnName(i + 1) + " " + metadata.getColumnType(i + 1) + " " + metadata.getColumnTypeName(i + 1) + " " + metadata.getPrecision(i + 1) + " " + metadata.getScale(i + 1) + " " + metadata.getSchemaName(i + 1) + " " + metadata.getTableName(i + 1); + System.out.println(metaStr); + } + + System.out.println("Data:"); + while (resultSet.next()) { + String dataStr = resultSet.getFloat(1) + " " + resultSet.getInt(2) + " " + resultSet.getInt(3) + " " + resultSet.getLong(4) + " " + resultSet.getDate(5) + " " + resultSet.getString(6); + System.out.println(dataStr); + } + } + } + + @Ignore + @Test + public void testPreStatementWithCubeData() throws SQLException { + Driver driver = new Driver(); + Properties info = new Properties(); + info.put("user", ""); + info.put("password", ""); + Connection conn = driver.connect("jdbc:kylin://localhost/default", info); + PreparedStatement state = conn.prepareStatement("select * from test_kylin_fact where seller_id=?"); + state.setLong(1, 10000001); + ResultSet resultSet = state.executeQuery(); + + ResultSetMetaData metadata = resultSet.getMetaData(); + System.out.println("Metadata:"); + + for (int i = 0; i < metadata.getColumnCount(); i++) { + String metaStr = metadata.getCatalogName(i + 1) + " " + metadata.getColumnClassName(i + 1) + " " + metadata.getColumnDisplaySize(i + 1) + " " + metadata.getColumnLabel(i + 1) + " " + metadata.getColumnName(i + 1) + " " + metadata.getColumnType(i + 1) + " " + metadata.getColumnTypeName(i + 1) + " " + metadata.getPrecision(i + 1) + " " + metadata.getScale(i + 1) + " " + metadata.getSchemaName(i + 1) + " " + metadata.getTableName(i + 1); + System.out.println(metaStr); + } + + System.out.println("Data:"); + while (resultSet.next()) { + String dataStr = resultSet.getFloat(1) + " " + resultSet.getInt(2) + " " + resultSet.getInt(3) + " " + resultSet.getLong(4) + " " + resultSet.getDate(5) + " " + resultSet.getString(6); + System.out.println(dataStr); + } + } +} diff --git a/jdbc/src/test/java/com/kylinolap/jdbc/DummyClient.java b/jdbc/src/test/java/com/kylinolap/jdbc/DummyClient.java new file mode 100644 index 0000000..5673eaa --- /dev/null +++ b/jdbc/src/test/java/com/kylinolap/jdbc/DummyClient.java @@ -0,0 +1,69 @@ +package com.kylinolap.jdbc; + +import java.sql.Types; +import java.util.ArrayList; +import java.util.List; + +import net.hydromatic.avatica.AvaticaStatement; +import net.hydromatic.avatica.ColumnMetaData; +import net.hydromatic.avatica.ColumnMetaData.Rep; +import net.hydromatic.linq4j.Enumerator; + +import com.kylinolap.jdbc.KylinConnectionImpl; +import com.kylinolap.jdbc.KylinEnumerator; +import com.kylinolap.jdbc.KylinMetaImpl.MetaCatalog; +import com.kylinolap.jdbc.KylinMetaImpl.MetaColumn; +import com.kylinolap.jdbc.KylinMetaImpl.MetaProject; +import com.kylinolap.jdbc.KylinMetaImpl.MetaSchema; +import com.kylinolap.jdbc.KylinMetaImpl.MetaTable; +import com.kylinolap.jdbc.stub.ConnectionException; +import com.kylinolap.jdbc.stub.DataSet; +import com.kylinolap.jdbc.stub.RemoteClient; + +/** + * @author xduo + * + */ +public class DummyClient implements RemoteClient { + + public DummyClient(KylinConnectionImpl conn) { + } + + @Override + public void connect() throws ConnectionException { + } + + @Override + public MetaProject getMetadata(String project) throws ConnectionException { + List meta = new ArrayList(); + for (int i = 0; i < 10; i++) { + meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + } + + List tables = new ArrayList(); + MetaTable table = new MetaTable("dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", new ArrayList()); + tables.add(table); + + List schemas = new ArrayList(); + schemas.add(new MetaSchema("dummy", "dummy", tables)); + List catalogs = new ArrayList(); + catalogs.add(new MetaCatalog("dummy", schemas)); + + return new MetaProject(null, catalogs); + } + + @Override + public DataSet query(AvaticaStatement statement, String sql) { + List data = new ArrayList(); + Object[] row = new Object[] { "foo", "bar", "tool" }; + data.add(row); + Enumerator enumerator = new KylinEnumerator(data); + List meta = new ArrayList(); + meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); + + return new DataSet(meta, enumerator); + } + +} diff --git a/jdbc/src/test/java/com/kylinolap/jdbc/DummyDriver.java b/jdbc/src/test/java/com/kylinolap/jdbc/DummyDriver.java new file mode 100644 index 0000000..04b8593 --- /dev/null +++ b/jdbc/src/test/java/com/kylinolap/jdbc/DummyDriver.java @@ -0,0 +1,16 @@ +package com.kylinolap.jdbc; + +import com.kylinolap.jdbc.Driver; + +/** + * @author xduo + * + */ +public class DummyDriver extends Driver { + + @Override + protected String getFactoryClassName(JdbcVersion jdbcVersion) { + return "com.kylinolap.kylin.jdbc.DummyJdbc41Factory"; + } + +} diff --git a/jdbc/src/test/java/com/kylinolap/jdbc/DummyJdbc41Factory.java b/jdbc/src/test/java/com/kylinolap/jdbc/DummyJdbc41Factory.java new file mode 100644 index 0000000..e4a4b55 --- /dev/null +++ b/jdbc/src/test/java/com/kylinolap/jdbc/DummyJdbc41Factory.java @@ -0,0 +1,19 @@ +package com.kylinolap.jdbc; + +import com.kylinolap.jdbc.KylinConnectionImpl; +import com.kylinolap.jdbc.KylinJdbc41Factory; +import com.kylinolap.jdbc.stub.RemoteClient; + +/** + * @author xduo + * + */ +public class DummyJdbc41Factory extends KylinJdbc41Factory { + + // ~ kylin sepcified + @Override + public RemoteClient newRemoteClient(KylinConnectionImpl connection) { + return new DummyClient(connection); + } + +} diff --git a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DriverTest.java b/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DriverTest.java deleted file mode 100644 index 7239095..0000000 --- a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DriverTest.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.kylinolap.kylin.jdbc; - -import static org.junit.Assert.*; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Properties; - -import org.junit.Ignore; -import org.junit.Test; - -/** - * Unit test for Driver. - * - * @author xduo - * - */ -public class DriverTest { - - @Test - public void testStatementWithMockData() throws SQLException { - Driver driver = new DummyDriver(); - - Connection conn = driver.connect("jdbc:kylin://test_url/test_db", null); - - ResultSet tables = conn.getMetaData().getTables(null, null, null, null); - while (tables.next()) { - for (int i = 0; i < 10; i++) { - assertEquals("dummy", tables.getString(i + 1)); - } - } - - Statement state = conn.createStatement(); - ResultSet resultSet = state.executeQuery("select * from test_table"); - - ResultSetMetaData metadata = resultSet.getMetaData(); - assertEquals(12, metadata.getColumnType(1)); - assertEquals("varchar", metadata.getColumnTypeName(1)); - assertEquals(1, metadata.isNullable(1)); - - while (resultSet.next()) { - assertEquals("foo", resultSet.getString(1)); - assertEquals("bar", resultSet.getString(2)); - assertEquals("tool", resultSet.getString(3)); - } - } - - @Test - public void testPreStatementWithMockData() throws SQLException { - Driver driver = new DummyDriver(); - - Connection conn = driver.connect("jdbc:kylin://test_url/test_db", null); - PreparedStatement state = conn.prepareStatement("select * from test_table where id=?"); - state.setInt(1, 10); - ResultSet resultSet = state.executeQuery(); - - ResultSetMetaData metadata = resultSet.getMetaData(); - assertEquals(12, metadata.getColumnType(1)); - assertEquals("varchar", metadata.getColumnTypeName(1)); - assertEquals(1, metadata.isNullable(1)); - - while (resultSet.next()) { - assertEquals("foo", resultSet.getString(1)); - assertEquals("bar", resultSet.getString(2)); - assertEquals("tool", resultSet.getString(3)); - } - } - - @Ignore - @Test - public void testWithCubeData() throws SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException { - Driver driver = (Driver) Class.forName("com.kylinolap.kylin.jdbc.Driver").newInstance(); - Properties info = new Properties(); - info.put("user", ""); - info.put("password", ""); - Connection conn = driver.connect("jdbc:kylin://localhost/default", info); - - ResultSet catalogs = conn.getMetaData().getCatalogs(); - while (catalogs.next()) { - System.out.println(catalogs.getString("TABLE_CAT")); - } - - ResultSet schemas = conn.getMetaData().getSchemas(); - while (schemas.next()) { - System.out.println(schemas.getString(1)); - System.out.println(schemas.getString(2)); - } - - ResultSet tables = conn.getMetaData().getTables(null, null, null, null); - while (tables.next()) { - String tableName = tables.getString(3); - assertEquals(tables.getString("TABLE_NAME"), tableName); - ResultSet columns = conn.getMetaData().getColumns(null, null, tableName, null); - - while (columns.next()) { - System.out.println(columns.getString("COLUMN_NAME")); - String column = ""; - for (int i = 0; i < 23; i++) { - column += columns.getString(i + 1) + ", "; - } - - System.out.println("Column in table " + tableName + ": " + column); - } - } - - for (int j = 0; j < 3; j++) { - Statement state = conn.createStatement(); - ResultSet resultSet = state.executeQuery("select * from test_kylin_fact"); - - ResultSetMetaData metadata = resultSet.getMetaData(); - System.out.println("Metadata:"); - - for (int i = 0; i < metadata.getColumnCount(); i++) { - String metaStr = metadata.getCatalogName(i + 1) + " " + metadata.getColumnClassName(i + 1) + " " + metadata.getColumnDisplaySize(i + 1) + " " + metadata.getColumnLabel(i + 1) + " " + metadata.getColumnName(i + 1) + " " + metadata.getColumnType(i + 1) + " " + metadata.getColumnTypeName(i + 1) + " " + metadata.getPrecision(i + 1) + " " + metadata.getScale(i + 1) + " " + metadata.getSchemaName(i + 1) + " " + metadata.getTableName(i + 1); - System.out.println(metaStr); - } - - System.out.println("Data:"); - while (resultSet.next()) { - String dataStr = resultSet.getFloat(1) + " " + resultSet.getInt(2) + " " + resultSet.getInt(3) + " " + resultSet.getLong(4) + " " + resultSet.getDate(5) + " " + resultSet.getString(6); - System.out.println(dataStr); - } - } - } - - @Ignore - @Test - public void testPreStatementWithCubeData() throws SQLException { - Driver driver = new Driver(); - Properties info = new Properties(); - info.put("user", ""); - info.put("password", ""); - Connection conn = driver.connect("jdbc:kylin://localhost/default", info); - PreparedStatement state = conn.prepareStatement("select * from test_kylin_fact where seller_id=?"); - state.setLong(1, 10000001); - ResultSet resultSet = state.executeQuery(); - - ResultSetMetaData metadata = resultSet.getMetaData(); - System.out.println("Metadata:"); - - for (int i = 0; i < metadata.getColumnCount(); i++) { - String metaStr = metadata.getCatalogName(i + 1) + " " + metadata.getColumnClassName(i + 1) + " " + metadata.getColumnDisplaySize(i + 1) + " " + metadata.getColumnLabel(i + 1) + " " + metadata.getColumnName(i + 1) + " " + metadata.getColumnType(i + 1) + " " + metadata.getColumnTypeName(i + 1) + " " + metadata.getPrecision(i + 1) + " " + metadata.getScale(i + 1) + " " + metadata.getSchemaName(i + 1) + " " + metadata.getTableName(i + 1); - System.out.println(metaStr); - } - - System.out.println("Data:"); - while (resultSet.next()) { - String dataStr = resultSet.getFloat(1) + " " + resultSet.getInt(2) + " " + resultSet.getInt(3) + " " + resultSet.getLong(4) + " " + resultSet.getDate(5) + " " + resultSet.getString(6); - System.out.println(dataStr); - } - } -} diff --git a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyClient.java b/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyClient.java deleted file mode 100644 index 1c44651..0000000 --- a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyClient.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.kylinolap.kylin.jdbc; - -import java.sql.Types; -import java.util.ArrayList; -import java.util.List; - -import net.hydromatic.avatica.AvaticaStatement; -import net.hydromatic.avatica.ColumnMetaData; -import net.hydromatic.avatica.ColumnMetaData.Rep; -import net.hydromatic.linq4j.Enumerator; - -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaCatalog; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaColumn; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaProject; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaSchema; -import com.kylinolap.kylin.jdbc.KylinMetaImpl.MetaTable; -import com.kylinolap.kylin.jdbc.stub.ConnectionException; -import com.kylinolap.kylin.jdbc.stub.DataSet; -import com.kylinolap.kylin.jdbc.stub.RemoteClient; - -/** - * @author xduo - * - */ -public class DummyClient implements RemoteClient { - - public DummyClient(KylinConnectionImpl conn) { - } - - @Override - public void connect() throws ConnectionException { - } - - @Override - public MetaProject getMetadata(String project) throws ConnectionException { - List meta = new ArrayList(); - for (int i = 0; i < 10; i++) { - meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - } - - List tables = new ArrayList(); - MetaTable table = new MetaTable("dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", new ArrayList()); - tables.add(table); - - List schemas = new ArrayList(); - schemas.add(new MetaSchema("dummy", "dummy", tables)); - List catalogs = new ArrayList(); - catalogs.add(new MetaCatalog("dummy", schemas)); - - return new MetaProject(null, catalogs); - } - - @Override - public DataSet query(AvaticaStatement statement, String sql) { - List data = new ArrayList(); - Object[] row = new Object[] { "foo", "bar", "tool" }; - data.add(row); - Enumerator enumerator = new KylinEnumerator(data); - List meta = new ArrayList(); - meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - meta.add(ColumnMetaData.dummy(ColumnMetaData.scalar(Types.VARCHAR, "varchar", Rep.STRING), true)); - - return new DataSet(meta, enumerator); - } - -} diff --git a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyDriver.java b/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyDriver.java deleted file mode 100644 index af97a32..0000000 --- a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyDriver.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.kylinolap.kylin.jdbc; - -/** - * @author xduo - * - */ -public class DummyDriver extends Driver { - - @Override - protected String getFactoryClassName(JdbcVersion jdbcVersion) { - return "com.kylinolap.kylin.jdbc.DummyJdbc41Factory"; - } - -} diff --git a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyJdbc41Factory.java b/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyJdbc41Factory.java deleted file mode 100644 index 6006a5e..0000000 --- a/jdbc/src/test/java/com/kylinolap/kylin/jdbc/DummyJdbc41Factory.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.kylinolap.kylin.jdbc; - -import com.kylinolap.kylin.jdbc.stub.RemoteClient; - -/** - * @author xduo - * - */ -public class DummyJdbc41Factory extends KylinJdbc41Factory { - - // ~ kylin sepcified - @Override - public RemoteClient newRemoteClient(KylinConnectionImpl connection) { - return new DummyClient(connection); - } - -} From 43fc2ca1d871c831343784c75e5a6e6ea17321c1 Mon Sep 17 00:00:00 2001 From: jiazhong Date: Thu, 13 Nov 2014 19:17:24 +0800 Subject: [PATCH 5/9] reload page after purege --- webapp/app/js/controllers/cubes.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js index f6dca82..708815f 100644 --- a/webapp/app/js/controllers/cubes.js +++ b/webapp/app/js/controllers/cubes.js @@ -121,6 +121,8 @@ KylinApp $scope.purge = function (cube) { if (confirm("Are you sure to purge the cube? ")) { CubeService.purge({cubeId: cube.name}, {}, function (result) { + $scope.cubes=[]; + $scope.reload(); MessageService.sendMsg('Purge job was submitted successfully', 'success', {}); }); } From 9f939ab887acb801a2db09d15ab2043a3cbfe737 Mon Sep 17 00:00:00 2001 From: jiazhong Date: Thu, 13 Nov 2014 20:18:55 +0800 Subject: [PATCH 6/9] show link in admin page --- webapp/app/partials/admin/admin.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/app/partials/admin/admin.html b/webapp/app/partials/admin/admin.html index 86efe9f..c3c3e5b 100644 --- a/webapp/app/partials/admin/admin.html +++ b/webapp/app/partials/admin/admin.html @@ -50,8 +50,8 @@

    Links

    From 0e9e152f12243f7c9861245ec6e1faa6f26d2dd2 Mon Sep 17 00:00:00 2001 From: honma Date: Thu, 13 Nov 2014 21:06:15 +0800 Subject: [PATCH 7/9] clean unused hbases --- .../kylinolap/job/hadoop/cube/StorageCleanupJob.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/job/src/main/java/com/kylinolap/job/hadoop/cube/StorageCleanupJob.java b/job/src/main/java/com/kylinolap/job/hadoop/cube/StorageCleanupJob.java index a87f05c..9e9738b 100644 --- a/job/src/main/java/com/kylinolap/job/hadoop/cube/StorageCleanupJob.java +++ b/job/src/main/java/com/kylinolap/job/hadoop/cube/StorageCleanupJob.java @@ -18,11 +18,16 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import com.kylinolap.common.util.StringUtil; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.Options; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; @@ -103,13 +108,23 @@ private void cleanUnusedHBaseTables(Configuration conf) throws MasterNotRunningE HBaseAdmin hbaseAdmin = new HBaseAdmin(conf); String tableNamePrefix = CubeManager.getHBaseStorageLocationPrefix(); HTableDescriptor[] tableDescriptors = hbaseAdmin.listTables(tableNamePrefix + ".*"); + + int count = 0; List allTablesNeedToBeDropped = new ArrayList(); for (HTableDescriptor desc : tableDescriptors) { String host = desc.getValue(CubeManager.getHtableMetadataKey()); - if (KylinConfig.getInstanceFromEnv().getMetadataUrlPrefix().equalsIgnoreCase(host)) { - //only take care htables that belongs to self + + if (StringUtils.isEmpty(host)) { allTablesNeedToBeDropped.add(desc.getTableName().getNameAsString()); + } else { + System.out.println("Htable " + desc.getTableName() + " is excluded because its host is " + host + " id is " + (++count)); } + + +// if (KylinConfig.getInstanceFromEnv().getMetadataUrlPrefix().equalsIgnoreCase(host)) { +// //only take care htables that belongs to self +// allTablesNeedToBeDropped.add(desc.getTableName().getNameAsString()); +// } } // remove every segment htable from drop list From f4a97ce9b37f561faa859231e0c3358007b6fa18 Mon Sep 17 00:00:00 2001 From: qhzhou Date: Fri, 14 Nov 2014 17:28:43 +0800 Subject: [PATCH 8/9] refactor JobInstanceBuilder to make creating JobInstance more clear --- .../com/kylinolap/dict/TrieDictionaryBuilder.java | 2 +- job/src/main/java/com/kylinolap/job/JobDAO.java | 7 +- .../main/java/com/kylinolap/job/JobInstance.java | 5 + .../java/com/kylinolap/job/JobInstanceBuilder.java | 124 +++++++++------------ .../main/java/com/kylinolap/job/JobManager.java | 2 +- 5 files changed, 66 insertions(+), 74 deletions(-) diff --git a/dictionary/src/main/java/com/kylinolap/dict/TrieDictionaryBuilder.java b/dictionary/src/main/java/com/kylinolap/dict/TrieDictionaryBuilder.java index 9af679a..9a6e2ce 100644 --- a/dictionary/src/main/java/com/kylinolap/dict/TrieDictionaryBuilder.java +++ b/dictionary/src/main/java/com/kylinolap/dict/TrieDictionaryBuilder.java @@ -65,7 +65,7 @@ void reset(byte[] value, boolean isEndOfValue, ArrayList children) { } } - public interface Visitor { + public static interface Visitor { void visit(Node n, int level); } diff --git a/job/src/main/java/com/kylinolap/job/JobDAO.java b/job/src/main/java/com/kylinolap/job/JobDAO.java index 47f380d..19b7c7c 100644 --- a/job/src/main/java/com/kylinolap/job/JobDAO.java +++ b/job/src/main/java/com/kylinolap/job/JobDAO.java @@ -180,9 +180,10 @@ public void updateJobInstance(JobInstance jobInstance) throws IOException { updatedJob.setType(jobInstance.getType()); updatedJob.clearSteps(); - for (int i = 0; i < jobInstance.getSteps().size(); i++) { - updatedJob.addStep(i, jobInstance.getSteps().get(i)); - } + updatedJob.addSteps(jobInstance.getSteps()); +// for (int i = 0; i < jobInstance.getSteps().size(); i++) { +// updatedJob.addSteps(i, jobInstance.getSteps().get(i)); +// } saveJob(updatedJob); } catch (IOException e) { diff --git a/job/src/main/java/com/kylinolap/job/JobInstance.java b/job/src/main/java/com/kylinolap/job/JobInstance.java index d484d68..b4d92ea 100644 --- a/job/src/main/java/com/kylinolap/job/JobInstance.java +++ b/job/src/main/java/com/kylinolap/job/JobInstance.java @@ -15,6 +15,7 @@ */ package com.kylinolap.job; +import java.util.Collection; import java.util.Iterator; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; @@ -239,6 +240,10 @@ public void clearSteps() { return steps.iterator(); } + public void addSteps(Collection steps) { + this.getSteps().addAll(steps); + } + public void addSteps(JobStep step) { getSteps().add(step); } diff --git a/job/src/main/java/com/kylinolap/job/JobInstanceBuilder.java b/job/src/main/java/com/kylinolap/job/JobInstanceBuilder.java index 5dff81a..b995619 100644 --- a/job/src/main/java/com/kylinolap/job/JobInstanceBuilder.java +++ b/job/src/main/java/com/kylinolap/job/JobInstanceBuilder.java @@ -16,7 +16,10 @@ package com.kylinolap.job; import java.io.IOException; +import java.util.Collections; +import java.util.List; +import com.google.common.collect.Lists; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -57,15 +60,15 @@ public JobInstanceBuilder(JobEngineConfig engineCfg) { this.engineConfig = engineCfg; } - public void buildSteps(JobInstance jobInstance) throws IOException { + public List buildSteps(JobInstance jobInstance) throws IOException { init(jobInstance); switch (jobInstance.getType()) { case BUILD: - createBuildCubeSegmentSteps(jobInstance); - break; + return buildCreateBuildCubeSegmentSteps(jobInstance); case MERGE: - createMergeCubeSegmentsSteps(jobInstance); - break; + return buildCreateMergeCubeSegmentsSteps(jobInstance); + default: + throw new IllegalArgumentException("job type:" + jobInstance.getType() + " not supported"); } } @@ -142,12 +145,13 @@ private String getRowkeyDistributionOutputPath() { return jobWorkingDir + "/" + cubeName + "/rowkey_stats"; } - private void createMergeCubeSegmentsSteps(JobInstance jobInstance) throws IOException { + private List buildCreateMergeCubeSegmentsSteps(JobInstance jobInstance) throws IOException { if (cube.getMergingSegments() == null || cube.getMergingSegments().size() < 2) { throw new IllegalArgumentException("Merging segments count should be more than 2"); } + String[] cuboidPaths = new String[cube.getMergingSegments().size()]; for (int i = 0; i < cube.getMergingSegments().size(); i++) { CubeSegment seg = cube.getMergingSegments().get(i); @@ -156,103 +160,90 @@ private void createMergeCubeSegmentsSteps(JobInstance jobInstance) throws IOExce String formattedPath = formatPaths(cuboidPaths); // clear existing steps - jobInstance.clearSteps(); +// jobInstance.clearSteps(); int stepSeqNum = 0; + List result = Lists.newArrayList(); // merge cuboid data of ancestor segments - addMergeCuboidDataStep(jobInstance, stepSeqNum, formattedPath); - stepSeqNum++; + result.add(createMergeCuboidDataStep(jobInstance, stepSeqNum++, formattedPath)); // get output distribution step - addRangeRowkeyDistributionStep(jobInstance, stepSeqNum, jobWorkingDir + "/" + cubeName + "/merged_cuboid"); - stepSeqNum++; + result.add(createRangeRowkeyDistributionStep(jobInstance, stepSeqNum++, jobWorkingDir + "/" + cubeName + "/merged_cuboid")); // create htable step - addCreateHTableStep(jobInstance, stepSeqNum); - stepSeqNum++; + result.add(createCreateHTableStep(jobInstance, stepSeqNum++)); // generate hfiles step - addConvertCuboidToHfileStep(jobInstance, stepSeqNum, jobWorkingDir + "/" + cubeName + "/merged_cuboid"); - stepSeqNum++; + result.add(createConvertCuboidToHfileStep(jobInstance, stepSeqNum++, jobWorkingDir + "/" + cubeName + "/merged_cuboid")); // bulk load step - addBulkLoadStep(jobInstance, stepSeqNum); - stepSeqNum++; + result.add(createBulkLoadStep(jobInstance, stepSeqNum++)); try { log.debug(JsonUtil.writeValueAsIndentString(jobInstance)); } catch (Exception e) { log.error(e.getMessage()); } + return result; } - private void createBuildCubeSegmentSteps(JobInstance jobInstance) throws IOException { + private List buildCreateBuildCubeSegmentSteps(JobInstance jobInstance) throws IOException { // clear existing steps - jobInstance.clearSteps(); +// jobInstance.clearSteps(); - int stepSeqNum = 0; int groupRowkeyColumnsCount = cube.getDescriptor().getRowkey().getNCuboidBuildLevels(); int totalRowkeyColumnsCount = cube.getDescriptor().getRowkey().getRowKeyColumns().length; String[] cuboidOutputTempPath = getCuboidOutputPaths(cubeName, totalRowkeyColumnsCount, groupRowkeyColumnsCount); + int stepSeqNum = 0; + List result = Lists.newArrayList(); if (this.engineConfig.isFlatTableByHive()) { // by default in here // flat hive table step - addIntermediateHiveTableStep(jobInstance, stepSeqNum, cuboidOutputTempPath); - stepSeqNum++; + result.add(createIntermediateHiveTableStep(jobInstance, stepSeqNum++, cuboidOutputTempPath)); } // fact distinct columns step - addFactDistinctColumnsStep(jobInstance, stepSeqNum, cuboidOutputTempPath); - stepSeqNum++; + result.add(createFactDistinctColumnsStep(jobInstance, stepSeqNum++, cuboidOutputTempPath)); // build dictionary step - addBuildDictionaryStep(jobInstance, stepSeqNum); - stepSeqNum++; + result.add(createBuildDictionaryStep(jobInstance, stepSeqNum++)); // base cuboid step - addBaseCuboidStep(jobInstance, stepSeqNum, cuboidOutputTempPath); - stepSeqNum++; + result.add(createBaseCuboidStep(jobInstance, stepSeqNum++, cuboidOutputTempPath)); // n dim cuboid steps for (int i = 1; i <= groupRowkeyColumnsCount; i++) { int dimNum = totalRowkeyColumnsCount - i; - addNDimensionCuboidStep(jobInstance, stepSeqNum, cuboidOutputTempPath, dimNum, totalRowkeyColumnsCount); - stepSeqNum++; + result.add(createNDimensionCuboidStep(jobInstance, stepSeqNum++, cuboidOutputTempPath, dimNum, totalRowkeyColumnsCount)); } // get output distribution step - addRangeRowkeyDistributionStep(jobInstance, stepSeqNum, jobWorkingDir + "/" + cubeName + "/cuboid/*"); - stepSeqNum++; + result.add(createRangeRowkeyDistributionStep(jobInstance, stepSeqNum++, jobWorkingDir + "/" + cubeName + "/cuboid/*")); // create htable step - addCreateHTableStep(jobInstance, stepSeqNum); - stepSeqNum++; + result.add(createCreateHTableStep(jobInstance, stepSeqNum++)); // generate hfiles step - addConvertCuboidToHfileStep(jobInstance, stepSeqNum, jobWorkingDir + "/" + cubeName + "/cuboid/*"); - stepSeqNum++; + result.add(createConvertCuboidToHfileStep(jobInstance, stepSeqNum++, jobWorkingDir + "/" + cubeName + "/cuboid/*")); // bulk load step - addBulkLoadStep(jobInstance, stepSeqNum); - stepSeqNum++; + result.add(createBulkLoadStep(jobInstance, stepSeqNum++)); try { log.debug(JsonUtil.writeValueAsIndentString(jobInstance)); } catch (Exception e) { log.error(e.getMessage()); } + return result; } private String formatPaths(String[] paths) { - String retVal = ArrayUtils.toString(paths); - retVal = StringUtils.remove(retVal, "{"); - retVal = StringUtils.remove(retVal, "}"); - return retVal; + return StringUtils.join(paths, ","); } - private void addBuildDictionaryStep(JobInstance jobInstance, int stepSeqNum) { + private JobStep createBuildDictionaryStep(JobInstance jobInstance, int stepSeqNum) { // base cuboid job JobStep buildDictionaryStep = new JobStep(); buildDictionaryStep.setName(JobConstants.STEP_NAME_BUILD_DICTIONARY); @@ -266,11 +257,10 @@ private void addBuildDictionaryStep(JobInstance jobInstance, int stepSeqNum) { buildDictionaryStep.setStatus(JobStepStatusEnum.PENDING); buildDictionaryStep.setRunAsync(false); buildDictionaryStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_NO_MR_DICTIONARY); - - jobInstance.addStep(stepSeqNum, buildDictionaryStep); + return buildDictionaryStep; } - private void addIntermediateHiveTableStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath) throws IOException { + private JobStep createIntermediateHiveTableStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath) throws IOException { JoinedFlatTableDesc intermediateTableDesc = new JoinedFlatTableDesc(cube.getDescriptor(), this.cubeSegment); String dropTableHql = JoinedFlatTable.generateDropTableStatement(intermediateTableDesc, jobUUID); String createTableHql = JoinedFlatTable.generateCreateTableStatement(intermediateTableDesc, jobWorkingDir, jobUUID); @@ -291,11 +281,10 @@ private void addIntermediateHiveTableStep(JobInstance jobInstance, int stepSeqNu intermediateHiveTableStep.setStatus(JobStepStatusEnum.PENDING); intermediateHiveTableStep.setRunAsync(false); intermediateHiveTableStep.setCmdType(JobStepCmdTypeEnum.SHELL_CMD_HADOOP); - - jobInstance.addStep(stepSeqNum, intermediateHiveTableStep); + return intermediateHiveTableStep; } - private void addFactDistinctColumnsStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath) throws IOException { + private JobStep createFactDistinctColumnsStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath) throws IOException { // base cuboid job JobStep factDistinctColumnsStep = new JobStep(); @@ -317,11 +306,10 @@ private void addFactDistinctColumnsStep(JobInstance jobInstance, int stepSeqNum, factDistinctColumnsStep.setStatus(JobStepStatusEnum.PENDING); factDistinctColumnsStep.setRunAsync(true); factDistinctColumnsStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_FACTDISTINCT); - - jobInstance.addStep(stepSeqNum, factDistinctColumnsStep); + return factDistinctColumnsStep; } - private void addBaseCuboidStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath) throws IOException { + private JobStep createBaseCuboidStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath) throws IOException { // base cuboid job JobStep baseCuboidStep = new JobStep(); @@ -352,11 +340,10 @@ private void addBaseCuboidStep(JobInstance jobInstance, int stepSeqNum, String[] baseCuboidStep.setStatus(JobStepStatusEnum.PENDING); baseCuboidStep.setRunAsync(true); baseCuboidStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_BASECUBOID); - - jobInstance.addStep(stepSeqNum, baseCuboidStep); + return baseCuboidStep; } - private void addNDimensionCuboidStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath, int dimNum, int totalRowkeyColumnCount) throws IOException { + private JobStep createNDimensionCuboidStep(JobInstance jobInstance, int stepSeqNum, String[] cuboidOutputTempPath, int dimNum, int totalRowkeyColumnCount) throws IOException { // ND cuboid job JobStep ndCuboidStep = new JobStep(); @@ -376,11 +363,10 @@ private void addNDimensionCuboidStep(JobInstance jobInstance, int stepSeqNum, St ndCuboidStep.setStatus(JobStepStatusEnum.PENDING); ndCuboidStep.setRunAsync(true); ndCuboidStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_NDCUBOID); - - jobInstance.addStep(stepSeqNum, ndCuboidStep); + return ndCuboidStep; } - private void addRangeRowkeyDistributionStep(JobInstance jobInstance, int stepSeqNum, String inputPath) throws IOException { + private JobStep createRangeRowkeyDistributionStep(JobInstance jobInstance, int stepSeqNum, String inputPath) throws IOException { JobStep rowkeyDistributionStep = new JobStep(); rowkeyDistributionStep.setName(JobConstants.STEP_NAME_GET_CUBOID_KEY_DISTRIBUTION); String cmd = ""; @@ -396,11 +382,10 @@ private void addRangeRowkeyDistributionStep(JobInstance jobInstance, int stepSeq rowkeyDistributionStep.setStatus(JobStepStatusEnum.PENDING); rowkeyDistributionStep.setRunAsync(true); rowkeyDistributionStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_RANGEKEYDISTRIBUTION); - - jobInstance.addStep(stepSeqNum, rowkeyDistributionStep); + return rowkeyDistributionStep; } - private void addMergeCuboidDataStep(JobInstance jobInstance, int stepSeqNum, String inputPath) throws IOException { + private JobStep createMergeCuboidDataStep(JobInstance jobInstance, int stepSeqNum, String inputPath) throws IOException { JobStep mergeCuboidDataStep = new JobStep(); mergeCuboidDataStep.setName(JobConstants.STEP_NAME_MERGE_CUBOID); String cmd = ""; @@ -417,11 +402,10 @@ private void addMergeCuboidDataStep(JobInstance jobInstance, int stepSeqNum, Str mergeCuboidDataStep.setStatus(JobStepStatusEnum.PENDING); mergeCuboidDataStep.setRunAsync(true); mergeCuboidDataStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_MERGECUBOID); - - jobInstance.addStep(stepSeqNum, mergeCuboidDataStep); + return mergeCuboidDataStep; } - private void addCreateHTableStep(JobInstance jobInstance, int stepSeqNum) { + private JobStep createCreateHTableStep(JobInstance jobInstance, int stepSeqNum) { JobStep createHtableStep = new JobStep(); createHtableStep.setName(JobConstants.STEP_NAME_CREATE_HBASE_TABLE); String cmd = ""; @@ -435,10 +419,10 @@ private void addCreateHTableStep(JobInstance jobInstance, int stepSeqNum) { createHtableStep.setRunAsync(false); createHtableStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADDOP_NO_MR_CREATEHTABLE); - jobInstance.addStep(stepSeqNum, createHtableStep); + return createHtableStep; } - private void addConvertCuboidToHfileStep(JobInstance jobInstance, int stepSeqNum, String inputPath) throws IOException { + private JobStep createConvertCuboidToHfileStep(JobInstance jobInstance, int stepSeqNum, String inputPath) throws IOException { JobStep createHFilesStep = new JobStep(); createHFilesStep.setName(JobConstants.STEP_NAME_CONVERT_CUBOID_TO_HFILE); String cmd = ""; @@ -456,10 +440,11 @@ private void addConvertCuboidToHfileStep(JobInstance jobInstance, int stepSeqNum createHFilesStep.setRunAsync(true); createHFilesStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_CONVERTHFILE); - jobInstance.addStep(stepSeqNum, createHFilesStep); + return createHFilesStep; + } - private void addBulkLoadStep(JobInstance jobInstance, int stepSeqNum) { + private JobStep createBulkLoadStep(JobInstance jobInstance, int stepSeqNum) { JobStep bulkLoadStep = new JobStep(); bulkLoadStep.setName(JobConstants.STEP_NAME_BULK_LOAD_HFILE); @@ -474,6 +459,7 @@ private void addBulkLoadStep(JobInstance jobInstance, int stepSeqNum) { bulkLoadStep.setRunAsync(false); bulkLoadStep.setCmdType(JobStepCmdTypeEnum.JAVA_CMD_HADOOP_NO_MR_BULKLOAD); - jobInstance.addStep(stepSeqNum, bulkLoadStep); + return bulkLoadStep; + } } diff --git a/job/src/main/java/com/kylinolap/job/JobManager.java b/job/src/main/java/com/kylinolap/job/JobManager.java index 2f1acf7..ce1bc58 100644 --- a/job/src/main/java/com/kylinolap/job/JobManager.java +++ b/job/src/main/java/com/kylinolap/job/JobManager.java @@ -78,7 +78,7 @@ public JobInstance createJob(String cubeName, String segmentName, CubeBuildTypeE // create job steps based on job type JobInstanceBuilder stepBuilder = new JobInstanceBuilder(this.engineConfig); - stepBuilder.buildSteps(jobInstance); + jobInstance.addSteps(stepBuilder.buildSteps(jobInstance)); return jobInstance; } From 9a7da883bf2ad21bac99deb1b5c0e26041165aa1 Mon Sep 17 00:00:00 2001 From: qhzhou Date: Fri, 14 Nov 2014 18:07:09 +0800 Subject: [PATCH 9/9] refactor JobInstance to return JobSteps on List not Vector, and change its accessibility --- job/src/main/java/com/kylinolap/job/JobInstance.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/job/src/main/java/com/kylinolap/job/JobInstance.java b/job/src/main/java/com/kylinolap/job/JobInstance.java index b4d92ea..7f270f4 100644 --- a/job/src/main/java/com/kylinolap/job/JobInstance.java +++ b/job/src/main/java/com/kylinolap/job/JobInstance.java @@ -17,6 +17,7 @@ import java.util.Collection; import java.util.Iterator; +import java.util.List; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; @@ -26,6 +27,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.collect.Lists; import com.kylinolap.common.persistence.RootPersistentEntity; import com.kylinolap.cube.CubeBuildTypeEnum; import com.kylinolap.job.constant.JobStatusEnum; @@ -83,7 +85,7 @@ public static String getJobWorkingDir(String jobUuid, String hdfsWorkdingDir) { @JsonManagedReference @JsonProperty("steps") - private Vector steps; + private List steps; public JobStep getRunningStep() { for (JobStep step : this.getSteps()) { @@ -222,9 +224,9 @@ public void setMrWaiting(long mrWaiting) { this.mrWaiting = mrWaiting; } - public Vector getSteps() { + List getSteps() { if (steps == null) { - steps = new Vector(); + steps = Lists.newArrayList(); } return steps; } @@ -233,18 +235,11 @@ public void clearSteps() { getSteps().clear(); } - public Iterator getStepsIterator() { - if (steps == null) { - steps = new Vector(); - } - return steps.iterator(); - } - public void addSteps(Collection steps) { this.getSteps().addAll(steps); } - public void addSteps(JobStep step) { + public void addStep(JobStep step) { getSteps().add(step); }