You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/03/30 14:29:02 UTC
[1/3] ignite git commit: IGNITE-1786: ODBC: Implemented ODBC support
on Java side.
Repository: ignite
Updated Branches:
refs/heads/ignite-1786 43bc846d0 -> e19049050
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
new file mode 100644
index 0000000..9aba295
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequestHandler.java
@@ -0,0 +1,362 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
+import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.lang.IgniteProductVersion;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.apache.ignite.internal.processors.odbc.OdbcRequest.*;
+
+/**
+ * SQL query handler.
+ */
+public class OdbcRequestHandler {
+ /** Query ID sequence. */
+ private static final AtomicLong QRY_ID_GEN = new AtomicLong();
+
+ /** Kernel context. */
+ private final GridKernalContext ctx;
+
+ /** Busy lock. */
+ private final GridSpinBusyLock busyLock;
+
+ /** Current queries cursors. */
+ private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCursors = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor.
+ *
+ * @param ctx Context.
+ * @param busyLock Shutdown latch.
+ */
+ public OdbcRequestHandler(final GridKernalContext ctx, final GridSpinBusyLock busyLock) {
+ this.ctx = ctx;
+ this.busyLock = busyLock;
+ }
+
+ /**
+ * Handle request.
+ *
+ * @param req Request.
+ * @return Response.
+ */
+ public OdbcResponse handle(OdbcRequest req) {
+ assert req != null;
+
+ if (!busyLock.enterBusy())
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED,
+ "Failed to handle ODBC request because node is stopping: " + req);
+
+ try {
+ switch (req.command()) {
+ case HANDSHAKE:
+ return performHandshake((OdbcHandshakeRequest) req);
+
+ case EXECUTE_SQL_QUERY:
+ return executeQuery((OdbcQueryExecuteRequest) req);
+
+ case FETCH_SQL_QUERY:
+ return fetchQuery((OdbcQueryFetchRequest) req);
+
+ case CLOSE_SQL_QUERY:
+ return closeQuery((OdbcQueryCloseRequest) req);
+
+ case GET_COLUMNS_META:
+ return getColumnsMeta((OdbcQueryGetColumnsMetaRequest) req);
+
+ case GET_TABLES_META:
+ return getTablesMeta((OdbcQueryGetTablesMetaRequest) req);
+ }
+
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, "Unsupported ODBC request: " + req);
+ }
+ finally {
+ busyLock.leaveBusy();
+ }
+ }
+
+ /**
+ * {@link OdbcHandshakeRequest} command handler.
+ *
+ * @param req Handshake request.
+ * @return Response.
+ */
+ private OdbcResponse performHandshake(OdbcHandshakeRequest req) {
+ OdbcHandshakeResult res;
+
+ if (req.version() == OdbcMessageParser.PROTO_VER)
+ res = new OdbcHandshakeResult(true, null, null);
+ else {
+ IgniteProductVersion ver = ctx.grid().version();
+
+ String verStr = Byte.toString(ver.major()) + '.' + ver.minor() + '.' + ver.maintenance();
+
+ res = new OdbcHandshakeResult(false, OdbcMessageParser.PROTO_VER_SINCE, verStr);
+ }
+
+ return new OdbcResponse(res);
+ }
+
+ /**
+ * {@link OdbcQueryExecuteRequest} command handler.
+ *
+ * @param req Execute query request.
+ * @return Response.
+ */
+ private OdbcResponse executeQuery(OdbcQueryExecuteRequest req) {
+ OdbcConfiguration cfg = ctx.config().getOdbcConfiguration();
+
+ assert cfg != null;
+
+ int cursorCnt = qryCursors.size();
+
+ if (cursorCnt >= cfg.getMaxOpenCursors())
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, "Too many opened cursors (either close other " +
+ "opened cursors or increase the limit through OdbcConfiguration.setMaxOpenCursors()) " +
+ "[maximum=" + cfg.getMaxOpenCursors() + ", current=" + cursorCnt + ']');
+
+ long qryId = QRY_ID_GEN.getAndIncrement();
+
+ try {
+ SqlFieldsQuery qry = new SqlFieldsQuery(req.sqlQuery());
+
+ qry.setArgs(req.arguments());
+
+ IgniteCache<Object, Object> cache = ctx.grid().cache(req.cacheName());
+
+ if (cache == null)
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED,
+ "Cache doesn't exist (did you configure it?): " + req.cacheName());
+
+ QueryCursor qryCur = cache.query(qry);
+
+ Iterator iter = qryCur.iterator();
+
+ qryCursors.put(qryId, new IgniteBiTuple<>(qryCur, iter));
+
+ List<?> fieldsMeta = ((QueryCursorImpl) qryCur).fieldsMeta();
+
+ OdbcQueryExecuteResult res = new OdbcQueryExecuteResult(qryId, convertMetadata(fieldsMeta));
+
+ return new OdbcResponse(res);
+ }
+ catch (Exception e) {
+ qryCursors.remove(qryId);
+
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, e.getMessage());
+ }
+ }
+
+ /**
+ * {@link OdbcQueryCloseRequest} command handler.
+ *
+ * @param req Execute query request.
+ * @return Response.
+ */
+ private OdbcResponse closeQuery(OdbcQueryCloseRequest req) {
+ try {
+ QueryCursor cur = qryCursors.get(req.queryId()).get1();
+
+ if (cur == null)
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, "Failed to find query with ID: " + req.queryId());
+
+ cur.close();
+
+ qryCursors.remove(req.queryId());
+
+ OdbcQueryCloseResult res = new OdbcQueryCloseResult(req.queryId());
+
+ return new OdbcResponse(res);
+ }
+ catch (Exception e) {
+ qryCursors.remove(req.queryId());
+
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, e.getMessage());
+ }
+ }
+
+ /**
+ * {@link OdbcQueryFetchRequest} command handler.
+ *
+ * @param req Execute query request.
+ * @return Response.
+ */
+ private OdbcResponse fetchQuery(OdbcQueryFetchRequest req) {
+ try {
+ Iterator cur = qryCursors.get(req.queryId()).get2();
+
+ if (cur == null)
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, "Failed to find query with ID: " + req.queryId());
+
+ List<Object> items = new ArrayList<>();
+
+ for (int i = 0; i < req.pageSize() && cur.hasNext(); ++i)
+ items.add(cur.next());
+
+ OdbcQueryFetchResult res = new OdbcQueryFetchResult(req.queryId(), items, !cur.hasNext());
+
+ return new OdbcResponse(res);
+ }
+ catch (Exception e) {
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, e.getMessage());
+ }
+ }
+
+ /**
+ * {@link OdbcQueryGetColumnsMetaRequest} command handler.
+ *
+ * @param req Get columns metadata request.
+ * @return Response.
+ */
+ private OdbcResponse getColumnsMeta(OdbcQueryGetColumnsMetaRequest req) {
+ try {
+ List<OdbcColumnMeta> meta = new ArrayList<>();
+
+ String cacheName;
+ String tableName;
+
+ if (req.tableName().contains(".")) {
+ // Parsing two-part table name.
+ String[] parts = req.tableName().split("\\.");
+
+ cacheName = OdbcUtils.removeQuotationMarksIfNeeded(parts[0]);
+
+ tableName = parts[1];
+ }
+ else {
+ cacheName = OdbcUtils.removeQuotationMarksIfNeeded(req.cacheName());
+
+ tableName = req.tableName();
+ }
+
+ Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
+
+ for (GridQueryTypeDescriptor table : tablesMeta) {
+ if (!matches(table.name(), tableName))
+ continue;
+
+ for (Map.Entry<String, Class<?>> field : table.fields().entrySet()) {
+ if (!matches(field.getKey(), req.columnName()))
+ continue;
+
+ OdbcColumnMeta columnMeta = new OdbcColumnMeta(req.cacheName(), table.name(),
+ field.getKey(), field.getValue());
+
+ if (!meta.contains(columnMeta))
+ meta.add(columnMeta);
+ }
+ }
+
+ OdbcQueryGetColumnsMetaResult res = new OdbcQueryGetColumnsMetaResult(meta);
+
+ return new OdbcResponse(res);
+ }
+ catch (Exception e) {
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, e.getMessage());
+ }
+ }
+
+ /**
+ * {@link OdbcQueryGetTablesMetaRequest} command handler.
+ *
+ * @param req Get tables metadata request.
+ * @return Response.
+ */
+ private OdbcResponse getTablesMeta(OdbcQueryGetTablesMetaRequest req) {
+ try {
+ List<OdbcTableMeta> meta = new ArrayList<>();
+
+ String realSchema = OdbcUtils.removeQuotationMarksIfNeeded(req.schema());
+
+ for (String cacheName : ctx.cache().cacheNames())
+ {
+ if (!matches(cacheName, realSchema))
+ continue;
+
+ Collection<GridQueryTypeDescriptor> tablesMeta = ctx.query().types(cacheName);
+
+ for (GridQueryTypeDescriptor table : tablesMeta) {
+ if (!matches(table.name(), req.table()))
+ continue;
+
+ if (!matches("TABLE", req.tableType()))
+ continue;
+
+ OdbcTableMeta tableMeta = new OdbcTableMeta(req.catalog(), cacheName, table.name(), "TABLE");
+
+ if (!meta.contains(tableMeta))
+ meta.add(tableMeta);
+ }
+ }
+
+ OdbcQueryGetTablesMetaResult res = new OdbcQueryGetTablesMetaResult(meta);
+
+ return new OdbcResponse(res);
+ }
+ catch (Exception e) {
+ return new OdbcResponse(OdbcResponse.STATUS_FAILED, e.getMessage());
+ }
+ }
+
+ /**
+ * Convert metadata in collection from {@link GridQueryFieldMetadata} to
+ * {@link OdbcColumnMeta}.
+ *
+ * @param meta Internal query field metadata.
+ * @return Odbc query field metadata.
+ */
+ private static Collection<OdbcColumnMeta> convertMetadata(Collection<?> meta) {
+ List<OdbcColumnMeta> res = new ArrayList<>();
+
+ if (meta != null) {
+ for (Object info : meta) {
+ assert info instanceof GridQueryFieldMetadata;
+
+ res.add(new OdbcColumnMeta((GridQueryFieldMetadata)info));
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * Checks whether string matches SQL pattern.
+ *
+ * @param str String.
+ * @param ptrn Pattern.
+ * @return Whether string matches pattern.
+ */
+ private static boolean matches(String str, String ptrn) {
+ return str != null && (F.isEmpty(ptrn) ||
+ str.toUpperCase().matches(ptrn.toUpperCase().replace("%", ".*").replace("_", ".")));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcResponse.java
new file mode 100644
index 0000000..12ac4bc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcResponse.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC protocol response.
+ */
+public class OdbcResponse {
+ /** Command succeeded. */
+ public static final int STATUS_SUCCESS = 0;
+
+ /** Command failed. */
+ public static final int STATUS_FAILED = 1;
+
+ /** Success status. */
+ private final int status;
+
+ /** Error. */
+ private final String err;
+
+ /** Response object. */
+ @GridToStringInclude
+ private final Object obj;
+
+ /**
+ * Constructs successful rest response.
+ *
+ * @param obj Response object.
+ */
+ public OdbcResponse(Object obj) {
+ this.status = STATUS_SUCCESS;
+
+ this.obj = obj;
+ this.err = null;
+ }
+
+ /**
+ * Constructs failed rest response.
+ *
+ * @param status Response status.
+ * @param err Error, {@code null} if success is {@code true}.
+ */
+ public OdbcResponse(int status, @Nullable String err) {
+ assert status != STATUS_SUCCESS;
+
+ this.status = status;
+
+ this.obj = null;
+ this.err = err;
+ }
+
+ /**
+ * @return Success flag.
+ */
+ public int status() {
+ return status;
+ }
+
+ /**
+ * @return Response object.
+ */
+ public Object response() {
+ return obj;
+ }
+
+ /**
+ * @return Error.
+ */
+ public String error() {
+ return err;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcResponse.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java
new file mode 100644
index 0000000..fb7df50
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcTableMeta.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+
+/**
+ * ODBC table-related metadata.
+ */
+public class OdbcTableMeta {
+ /** Catalog name. */
+ private final String catalog;
+
+ /** Schema name. */
+ private final String schema;
+
+ /** Table name. */
+ private final String table;
+
+ /** Table type. */
+ private final String tableType;
+
+ /**
+ * @param catalog Catalog name.
+ * @param schema Schema name.
+ * @param table Table name.
+ * @param tableType Table type.
+ */
+ public OdbcTableMeta(String catalog, String schema, String table, String tableType) {
+ this.catalog = catalog;
+ this.schema = OdbcUtils.addQuotationMarksIfNeeded(schema);
+ this.table = table;
+ this.tableType = tableType;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int hash = catalog.hashCode();
+
+ hash = 31 * hash + schema.hashCode();
+ hash = 31 * hash + table.hashCode();
+ hash = 31 * hash + tableType.hashCode();
+
+ return hash;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (o instanceof OdbcTableMeta) {
+ OdbcTableMeta other = (OdbcTableMeta) o;
+
+ return this == other || catalog.equals(other.catalog) && schema.equals(other.schema) &&
+ table.equals(other.table) && tableType.equals(other.tableType);
+ }
+
+ return false;
+ }
+
+ /**
+ * Write in a binary format.
+ *
+ * @param writer Binary writer.
+ */
+ public void writeBinary(BinaryRawWriterEx writer) {
+ writer.writeString(catalog);
+ writer.writeString(schema);
+ writer.writeString(table);
+ writer.writeString(tableType);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java
new file mode 100644
index 0000000..300b079
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcUtils.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+/**
+ * Various ODBC utility methods.
+ */
+public class OdbcUtils {
+ /**
+ * Add quotation marks at the beginning and end of the string.
+ *
+ * @param str Input string.
+ * @return String surrounded with quotation marks.
+ */
+ public static String addQuotationMarksIfNeeded(String str) {
+ if (!str.startsWith("\"") && !str.isEmpty())
+ return "\"" + str + "\"";
+
+ return str;
+ }
+
+ /**
+ * Remove quotation marks at the beginning and end of the string if present.
+ *
+ * @param str Input string.
+ * @return String without leading and trailing quotation marks.
+ */
+ public static String removeQuotationMarksIfNeeded(String str) {
+ if (str.startsWith("\"") && str.endsWith("\""))
+ return str.substring(1, str.length() - 1);
+
+ return str;
+ }
+
+ /**
+ * Private constructor.
+ */
+ private OdbcUtils() {
+ // No-op.
+ }
+}
[3/3] ignite git commit: Merge branch 'master' into ignite-1786
Posted by vo...@apache.org.
Merge branch 'master' into ignite-1786
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e1904905
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e1904905
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e1904905
Branch: refs/heads/ignite-1786
Commit: e190490509f53a788a6cd6ab8f64dc40b90cdaeb
Parents: 43bc846 bae8615
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Mar 30 15:28:55 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Mar 30 15:28:55 2016 +0300
----------------------------------------------------------------------
----------------------------------------------------------------------
[2/3] ignite git commit: IGNITE-1786: ODBC: Implemented ODBC support
on Java side.
Posted by vo...@apache.org.
IGNITE-1786: ODBC: Implemented ODBC support on Java side.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/bae86159
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/bae86159
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/bae86159
Branch: refs/heads/ignite-1786
Commit: bae86159c437b66e3cf79d295efa6e35f633d43a
Parents: bbe5258
Author: isapego <is...@gridgain.com>
Authored: Wed Mar 30 15:28:24 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Mar 30 15:28:24 2016 +0300
----------------------------------------------------------------------
.../configuration/IgniteConfiguration.java | 25 ++
.../ignite/configuration/OdbcConfiguration.java | 319 ++++++++++++++++
.../ignite/internal/GridKernalContext.java | 8 +
.../ignite/internal/GridKernalContextImpl.java | 12 +
.../apache/ignite/internal/IgniteKernal.java | 2 +
.../processors/odbc/OdbcBufferedParser.java | 81 +++++
.../processors/odbc/OdbcColumnMeta.java | 110 ++++++
.../processors/odbc/OdbcHandshakeRequest.java | 49 +++
.../processors/odbc/OdbcHandshakeResult.java | 66 ++++
.../processors/odbc/OdbcMessageParser.java | 277 ++++++++++++++
.../processors/odbc/OdbcNioListener.java | 171 +++++++++
.../processors/odbc/OdbcNioServerBuffer.java | 114 ++++++
.../internal/processors/odbc/OdbcProcessor.java | 116 ++++++
.../processors/odbc/OdbcQueryCloseRequest.java | 49 +++
.../processors/odbc/OdbcQueryCloseResult.java | 40 ++
.../odbc/OdbcQueryExecuteRequest.java | 78 ++++
.../processors/odbc/OdbcQueryExecuteResult.java | 54 +++
.../processors/odbc/OdbcQueryFetchRequest.java | 61 ++++
.../processors/odbc/OdbcQueryFetchResult.java | 66 ++++
.../odbc/OdbcQueryGetColumnsMetaRequest.java | 74 ++++
.../odbc/OdbcQueryGetColumnsMetaResult.java | 42 +++
.../odbc/OdbcQueryGetTablesMetaRequest.java | 85 +++++
.../odbc/OdbcQueryGetTablesMetaResult.java | 42 +++
.../internal/processors/odbc/OdbcRequest.java | 58 +++
.../processors/odbc/OdbcRequestHandler.java | 362 +++++++++++++++++++
.../internal/processors/odbc/OdbcResponse.java | 96 +++++
.../internal/processors/odbc/OdbcTableMeta.java | 85 +++++
.../internal/processors/odbc/OdbcUtils.java | 56 +++
28 files changed, 2598 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
index 758a2b4..e06978f 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java
@@ -411,6 +411,9 @@ public class IgniteConfiguration {
/** Client access configuration. */
private ConnectorConfiguration connectorCfg = new ConnectorConfiguration();
+ /** ODBC configuration. */
+ private OdbcConfiguration odbcCfg;
+
/** Warmup closure. Will be invoked before actual grid start. */
private IgniteInClosure<IgniteConfiguration> warmupClos;
@@ -510,6 +513,7 @@ public class IgniteConfiguration {
mgmtPoolSize = cfg.getManagementThreadPoolSize();
netTimeout = cfg.getNetworkTimeout();
nodeId = cfg.getNodeId();
+ odbcCfg = cfg.getOdbcConfiguration();
p2pEnabled = cfg.isPeerClassLoadingEnabled();
p2pLocClsPathExcl = cfg.getPeerClassLoadingLocalClassPathExclude();
p2pMissedCacheSize = cfg.getPeerClassLoadingMissedResourcesCacheSize();
@@ -2298,6 +2302,27 @@ public class IgniteConfiguration {
}
/**
+ * Gets configuration for ODBC.
+ *
+ * @return ODBC configuration.
+ */
+ public OdbcConfiguration getOdbcConfiguration() {
+ return odbcCfg;
+ }
+
+ /**
+ * Sets configuration for ODBC.
+ *
+ * @param odbcCfg ODBC configuration.
+ * @return {@code this} for chaining.
+ */
+ public IgniteConfiguration setOdbcConfiguration(OdbcConfiguration odbcCfg) {
+ this.odbcCfg = odbcCfg;
+
+ return this;
+ }
+
+ /**
* Gets configurations for services to be deployed on the grid.
*
* @return Configurations for services to be deployed on the grid.
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
new file mode 100644
index 0000000..8f0a0fb
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/OdbcConfiguration.java
@@ -0,0 +1,319 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.configuration;
+
+import java.net.Socket;
+
+/**
+ * ODBC configuration.
+ */
+public class OdbcConfiguration {
+ /** Default TCP server port. */
+ public static final int DFLT_TCP_PORT = 11443;
+
+ /** Default TCP_NODELAY flag. */
+ public static final boolean DFLT_TCP_NODELAY = true;
+
+ /** Default TCP direct buffer flag. */
+ public static final boolean DFLT_TCP_DIRECT_BUF = false;
+
+ /** Default ODBC idle timeout. */
+ public static final int DFLT_IDLE_TIMEOUT = 7000;
+
+ /** Default socket send and receive buffer size. */
+ public static final int DFLT_SOCK_BUF_SIZE = 32 * 1024;
+
+ /** Default max number of open cursors per connection. */
+ public static final int DFLT_MAX_OPEN_CURSORS = 128;
+
+ /** TCP port. */
+ private int port = DFLT_TCP_PORT;
+
+ /** TCP host. */
+ private String host;
+
+ /** TCP no delay flag. */
+ private boolean noDelay = DFLT_TCP_NODELAY;
+
+ /** ODBC TCP direct buffer flag. */
+ private boolean directBuf = DFLT_TCP_DIRECT_BUF;
+
+ /** ODBC TCP send buffer size. */
+ private int sndBufSize = DFLT_SOCK_BUF_SIZE;
+
+ /** ODBC TCP receive buffer size. */
+ private int rcvBufSize = DFLT_SOCK_BUF_SIZE;
+
+ /** ODBC TCP send queue limit. */
+ private int sndQueueLimit;
+
+ /** ODBC TCP selector count. */
+ private int selectorCnt = Math.min(4, Runtime.getRuntime().availableProcessors());
+
+ /** Idle timeout. */
+ private long idleTimeout = DFLT_IDLE_TIMEOUT;
+
+ /** Max number of opened cursors per connection. */
+ private int maxOpenCursors = DFLT_MAX_OPEN_CURSORS;
+
+ /**
+ * Creates ODBC server configuration with all default values.
+ */
+ public OdbcConfiguration() {
+ // No-op.
+ }
+
+ /**
+ * Creates ODBC server configuration by copying all properties from
+ * given configuration.
+ *
+ * @param cfg ODBC server configuration.
+ */
+ public OdbcConfiguration(OdbcConfiguration cfg) {
+ assert cfg != null;
+
+ directBuf = cfg.isDirectBuffer();
+ host = cfg.getHost();
+ idleTimeout = cfg.getIdleTimeout();
+ maxOpenCursors = cfg.getMaxOpenCursors();
+ noDelay = cfg.isNoDelay();
+ port = cfg.getPort();
+ rcvBufSize = cfg.getReceiveBufferSize();
+ selectorCnt = cfg.getSelectorCount();
+ sndBufSize = cfg.getSendBufferSize();
+ sndQueueLimit = cfg.getSendQueueLimit();
+ }
+
+ /**
+ * Gets port for TCP ODBC server.
+ * <p>
+ * Default is {@link #DFLT_TCP_PORT}.
+ *
+ * @return TCP port.
+ */
+ public int getPort() {
+ return port;
+ }
+
+ /**
+ * Sets port for TCP ODBC server.
+ *
+ * @param port TCP port.
+ */
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ /**
+ * Gets host for TCP ODBC server. This can be either an
+ * IP address or a domain name.
+ * <p>
+ * If not defined, system-wide local address will be used
+ * (see {@link IgniteConfiguration#getLocalHost()}.
+ * <p>
+ * You can also use {@code 0.0.0.0} value to bind to all
+ * locally-available IP addresses.
+ *
+ * @return TCP host.
+ */
+ public String getHost() {
+ return host;
+ }
+
+ /**
+ * Sets host for TCP ODBC server.
+ *
+ * @param host TCP host.
+ */
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ /**
+ * Gets flag indicating whether {@code TCP_NODELAY} option should be set for accepted client connections.
+ * Setting this option reduces network latency and should be set to {@code true} in majority of cases.
+ * For more information, see {@link Socket#setTcpNoDelay(boolean)}
+ * <p/>
+ * If not specified, default value is {@link #DFLT_TCP_NODELAY}.
+ *
+ * @return Whether {@code TCP_NODELAY} option should be enabled.
+ */
+ public boolean isNoDelay() {
+ return noDelay;
+ }
+
+ /**
+ * Sets whether {@code TCP_NODELAY} option should be set for all accepted ODBC client connections.
+ *
+ * @param noDelay {@code True} if option should be enabled.
+ * @see #isNoDelay()
+ */
+ public void setNoDelay(boolean noDelay) {
+ this.noDelay = noDelay;
+ }
+
+ /**
+ * Gets flag indicating whether ODBC TCP server should use direct buffers. A direct buffer is a buffer
+ * that is allocated and accessed using native system calls, without using JVM heap. Enabling direct
+ * buffer <em>may</em> improve performance and avoid memory issues (long GC pauses due to huge buffer
+ * size).
+ * <p/>
+ * If not specified, default value is {@link #DFLT_TCP_DIRECT_BUF}.
+ *
+ * @return Whether direct buffer should be used.
+ */
+ public boolean isDirectBuffer() {
+ return directBuf;
+ }
+
+ /**
+ * Sets whether to use direct buffer for ODBC TCP server.
+ *
+ * @param directBuf {@code True} if option should be enabled.
+ * @see #isDirectBuffer()
+ */
+ public void setDirectBuffer(boolean directBuf) {
+ this.directBuf = directBuf;
+ }
+
+ /**
+ * Gets ODBC TCP server send buffer size.
+ * <p/>
+ * If not specified, default value is {@link #DFLT_SOCK_BUF_SIZE}.
+ *
+ * @return ODBC TCP server send buffer size (0 for default).
+ */
+ public int getSendBufferSize() {
+ return sndBufSize;
+ }
+
+ /**
+ * Sets ODBC TCP server send buffer size.
+ *
+ * @param sndBufSize Send buffer size.
+ * @see #getSendBufferSize()
+ */
+ public void setSendBufferSize(int sndBufSize) {
+ this.sndBufSize = sndBufSize;
+ }
+
+ /**
+ * Gets ODBC TCP server receive buffer size.
+ * <p/>
+ * If not specified, default value is {@link #DFLT_SOCK_BUF_SIZE}.
+ *
+ * @return ODBC TCP server receive buffer size (0 for default).
+ */
+ public int getReceiveBufferSize() {
+ return rcvBufSize;
+ }
+
+ /**
+ * Sets ODBC TCP server receive buffer size.
+ *
+ * @param rcvBufSize Receive buffer size.
+ * @see #getReceiveBufferSize()
+ */
+ public void setReceiveBufferSize(int rcvBufSize) {
+ this.rcvBufSize = rcvBufSize;
+ }
+
+ /**
+ * Gets ODBC TCP server send queue limit. If the limit exceeds, all successive writes will
+ * block until the queue has enough capacity.
+ *
+ * @return ODBC TCP server send queue limit (0 for unlimited).
+ */
+ public int getSendQueueLimit() {
+ return sndQueueLimit;
+ }
+
+ /**
+ * Sets ODBC TCP server send queue limit.
+ *
+ * @param sndQueueLimit ODBC TCP server send queue limit (0 for unlimited).
+ * @see #getSendQueueLimit()
+ */
+ public void setSendQueueLimit(int sndQueueLimit) {
+ this.sndQueueLimit = sndQueueLimit;
+ }
+
+ /**
+ * Gets number of selector threads in ODBC TCP server. Higher value for this parameter
+ * may increase throughput, but also increases context switching.
+ *
+ * @return Number of selector threads for ODBC TCP server.
+ */
+ public int getSelectorCount() {
+ return selectorCnt;
+ }
+
+ /**
+ * Sets number of selector threads for ODBC TCP server.
+ *
+ * @param selectorCnt Number of selector threads for ODBC TCP server.
+ * @see #getSelectorCount()
+ */
+ public void setSelectorCount(int selectorCnt) {
+ this.selectorCnt = selectorCnt;
+ }
+
+ /**
+ * Gets idle timeout for ODBC TCP server.
+ * <p>
+ * This setting is used to reject half-opened sockets. If no packets
+ * come within idle timeout, the connection is closed.
+ * <p/>
+ * If not specified, default value is {@link #DFLT_IDLE_TIMEOUT}.
+ *
+ * @return Idle timeout in milliseconds.
+ */
+ public long getIdleTimeout() {
+ return idleTimeout;
+ }
+
+ /**
+ * Sets idle timeout for ODBC TCP server.
+ *
+ * @param idleTimeout Idle timeout in milliseconds.
+ * @see #getIdleTimeout()
+ */
+ public void setIdleTimeout(long idleTimeout) {
+ this.idleTimeout = idleTimeout;
+ }
+
+ /**
+ * Gets maximum number of opened cursors per connection.
+ * <p>
+ * Defaults to {@link #DFLT_MAX_OPEN_CURSORS}.
+ *
+ * @return Maximum number of opened cursors.
+ */
+ public int getMaxOpenCursors() {
+ return maxOpenCursors;
+ }
+
+ /**
+ * Sets maximum number of opened cursors per connection. See {@link #getMaxOpenCursors()}.
+ *
+ * @param maxOpenCursors Maximum number of opened cursors.
+ */
+ public void setMaxOpenCursors(int maxOpenCursors) {
+ this.maxOpenCursors = maxOpenCursors;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
index c0b50a2..b95d595 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContext.java
@@ -48,6 +48,7 @@ import org.apache.ignite.internal.processors.igfs.IgfsHelper;
import org.apache.ignite.internal.processors.igfs.IgfsProcessorAdapter;
import org.apache.ignite.internal.processors.job.GridJobProcessor;
import org.apache.ignite.internal.processors.jobmetrics.GridJobMetricsProcessor;
+import org.apache.ignite.internal.processors.odbc.OdbcProcessor;
import org.apache.ignite.internal.processors.offheap.GridOffHeapProcessor;
import org.apache.ignite.internal.processors.platform.PlatformProcessor;
import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
@@ -311,6 +312,13 @@ public interface GridKernalContext extends Iterable<GridComponent> {
public GridQueryProcessor query();
/**
+ * Gets ODBC processor.
+ *
+ * @return ODBC processor.
+ */
+ public OdbcProcessor odbc();
+
+ /**
* @return Plugin processor.
*/
public IgnitePluginProcessor plugins();
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
index 22fd96c..753dbe8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridKernalContextImpl.java
@@ -65,6 +65,7 @@ import org.apache.ignite.internal.processors.igfs.IgfsProcessorAdapter;
import org.apache.ignite.internal.processors.job.GridJobProcessor;
import org.apache.ignite.internal.processors.jobmetrics.GridJobMetricsProcessor;
import org.apache.ignite.internal.processors.nodevalidation.DiscoveryNodeValidationProcessor;
+import org.apache.ignite.internal.processors.odbc.OdbcProcessor;
import org.apache.ignite.internal.processors.offheap.GridOffHeapProcessor;
import org.apache.ignite.internal.processors.platform.PlatformProcessor;
import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
@@ -160,6 +161,10 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
/** */
@GridToStringInclude
+ private OdbcProcessor odbcProc;
+
+ /** */
+ @GridToStringInclude
private GridQueryProcessor qryProc;
/** */
@@ -506,6 +511,8 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
pluginProc = (IgnitePluginProcessor)comp;
else if (comp instanceof GridQueryProcessor)
qryProc = (GridQueryProcessor)comp;
+ else if (comp instanceof OdbcProcessor)
+ odbcProc = (OdbcProcessor)comp;
else if (comp instanceof DataStructuresProcessor)
dataStructuresProc = (DataStructuresProcessor)comp;
else if (comp instanceof ClusterProcessor)
@@ -749,6 +756,11 @@ public class GridKernalContextImpl implements GridKernalContext, Externalizable
}
/** {@inheritDoc} */
+ @Override public OdbcProcessor odbc() {
+ return odbcProc;
+ }
+
+ /** {@inheritDoc} */
@Override public DataStructuresProcessor dataStructures() {
return dataStructuresProc;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 8df89f3..21fbc47 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -117,6 +117,7 @@ import org.apache.ignite.internal.processors.job.GridJobProcessor;
import org.apache.ignite.internal.processors.jobmetrics.GridJobMetricsProcessor;
import org.apache.ignite.internal.processors.nodevalidation.DiscoveryNodeValidationProcessor;
import org.apache.ignite.internal.processors.nodevalidation.OsDiscoveryNodeValidationProcessor;
+import org.apache.ignite.internal.processors.odbc.OdbcProcessor;
import org.apache.ignite.internal.processors.offheap.GridOffHeapProcessor;
import org.apache.ignite.internal.processors.platform.PlatformNoopProcessor;
import org.apache.ignite.internal.processors.platform.PlatformProcessor;
@@ -849,6 +850,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
startProcessor(createComponent(IgniteCacheObjectProcessor.class, ctx));
startProcessor(new GridCacheProcessor(ctx));
startProcessor(new GridQueryProcessor(ctx));
+ startProcessor(new OdbcProcessor(ctx));
startProcessor(new GridServiceProcessor(ctx));
startProcessor(new GridTaskSessionProcessor(ctx));
startProcessor(new GridJobProcessor(ctx));
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcBufferedParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcBufferedParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcBufferedParser.java
new file mode 100644
index 0000000..0d43aec
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcBufferedParser.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.util.nio.GridNioParser;
+import org.apache.ignite.internal.util.nio.GridNioSession;
+import org.apache.ignite.internal.util.nio.GridNioSessionMetaKey;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * This class implements stream parser based on {@link OdbcNioServerBuffer}.
+ * <p>
+ * The rule for this parser is that every message sent over the stream is prepended with
+ * 4-byte integer header containing message size. So, the stream structure is as follows:
+ * <pre>
+ * +--+--+--+--+--+--+...+--+--+--+--+--+--+--+...+--+
+ * | MSG_SIZE | MESSAGE | MSG_SIZE | MESSAGE |
+ * +--+--+--+--+--+--+...+--+--+--+--+--+--+--+...+--+
+ * </pre>
+ */
+public class OdbcBufferedParser implements GridNioParser {
+ /** Buffer metadata key. */
+ private static final int BUF_META_KEY = GridNioSessionMetaKey.nextUniqueKey();
+
+ /** {@inheritDoc} */
+ @Override public byte[] decode(GridNioSession ses, ByteBuffer buf) throws IOException, IgniteCheckedException {
+ OdbcNioServerBuffer nioBuf = ses.meta(BUF_META_KEY);
+
+ // Decode for a given session is called per one thread, so there should not be any concurrency issues.
+ // However, we make some additional checks.
+ if (nioBuf == null) {
+ nioBuf = new OdbcNioServerBuffer();
+
+ OdbcNioServerBuffer old = ses.addMeta(BUF_META_KEY, nioBuf);
+
+ assert old == null;
+ }
+
+ return nioBuf.read(buf);
+ }
+
+ /** {@inheritDoc} */
+ @Override public ByteBuffer encode(GridNioSession ses, Object msg) throws IOException, IgniteCheckedException {
+ byte[] msg0 = (byte[])msg;
+
+ ByteBuffer res = ByteBuffer.allocate(msg0.length + 4);
+
+ res.order(ByteOrder.LITTLE_ENDIAN);
+
+ res.putInt(msg0.length);
+ res.put(msg0);
+
+ res.flip();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return OdbcBufferedParser.class.getSimpleName();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcColumnMeta.java
new file mode 100644
index 0000000..0edfabc
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcColumnMeta.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+
+/**
+ * ODBC column-related metadata.
+ */
+public class OdbcColumnMeta {
+ /** Cache name. */
+ private final String schemaName;
+
+ /** Table name. */
+ private final String tableName;
+
+ /** Column name. */
+ private final String columnName;
+
+ /** Data type. */
+ private final Class<?> dataType;
+
+ /**
+ * @param schemaName Cache name.
+ * @param tableName Table name.
+ * @param columnName Column name.
+ * @param dataType Data type.
+ */
+ public OdbcColumnMeta(String schemaName, String tableName, String columnName, Class<?> dataType) {
+ this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(schemaName);
+ this.tableName = tableName;
+ this.columnName = columnName;
+ this.dataType = dataType;
+ }
+
+ /**
+ * @param info Field metadata.
+ */
+ public OdbcColumnMeta(GridQueryFieldMetadata info) {
+ this.schemaName = OdbcUtils.addQuotationMarksIfNeeded(info.schemaName());
+ this.tableName = info.typeName();
+ this.columnName = info.fieldName();
+
+ Class<?> type;
+
+ try {
+ type = Class.forName(info.fieldTypeName());
+ }
+ catch (Exception ignored) {
+ type = Object.class;
+ }
+
+ this.dataType = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int hash = schemaName.hashCode();
+
+ hash = 31 * hash + tableName.hashCode();
+ hash = 31 * hash + columnName.hashCode();
+ hash = 31 * hash + dataType.hashCode();
+
+ return hash;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (o instanceof OdbcColumnMeta) {
+ OdbcColumnMeta other = (OdbcColumnMeta) o;
+
+ return this == other || schemaName.equals(other.schemaName) && tableName.equals(other.tableName) &&
+ columnName.equals(other.columnName) && dataType.equals(other.dataType);
+ }
+
+ return false;
+ }
+
+ /**
+ * Write in a binary format.
+ *
+ * @param writer Binary writer.
+ */
+ public void write(BinaryRawWriter writer) {
+ writer.writeString(schemaName);
+ writer.writeString(tableName);
+ writer.writeString(columnName);
+
+ byte typeId = BinaryUtils.typeByClass(dataType);
+
+ writer.writeByte(typeId);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java
new file mode 100644
index 0000000..5e09041
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeRequest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC handshake request.
+ */
+public class OdbcHandshakeRequest extends OdbcRequest {
+ /** Protocol version. */
+ private final long ver;
+
+ /**
+ * @param ver Protocol version.
+ */
+ public OdbcHandshakeRequest(long ver) {
+ super(HANDSHAKE);
+
+ this.ver = ver;
+ }
+
+ /**
+ * @return Protocol version.
+ */
+ public long version() {
+ return ver;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcHandshakeRequest.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java
new file mode 100644
index 0000000..bf1c61e
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcHandshakeResult.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC handshake result.
+ */
+public class OdbcHandshakeResult {
+ /** Handshake accepted. */
+ private final boolean accepted;
+
+ /** Apache Ignite version when protocol version has been introduced. */
+ private final String protoVerSince;
+
+ /** Current Apache Ignite version. */
+ private final String curVer;
+
+ /**
+ * @param accepted Handshake accepted.
+ * @param protoVerSince Apache Ignite version when protocol version has been introduced.
+ * @param curVer Current Apache Ignite version.
+ */
+ public OdbcHandshakeResult(boolean accepted, @Nullable String protoVerSince, @Nullable String curVer) {
+ this.accepted = accepted;
+ this.protoVerSince = protoVerSince;
+ this.curVer = curVer;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public boolean accepted() {
+ return accepted;
+ }
+
+ /**
+ * @return Apache Ignite version when protocol version has been introduced.
+ */
+ @Nullable public String protoVerSince() {
+ return protoVerSince;
+ }
+
+ /**
+ * @return Current Apache Ignite version.
+ */
+ @Nullable public String currentVer() {
+ return curVer;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java
new file mode 100644
index 0000000..d217390
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcMessageParser.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridBinaryMarshaller;
+import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream;
+import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream;
+import org.apache.ignite.internal.binary.streams.BinaryInputStream;
+import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
+
+import java.util.Collection;
+
+/**
+ * ODBC message parser.
+ */
+public class OdbcMessageParser {
+ /** Current ODBC communication protocol version. */
+ public static final long PROTO_VER = 1;
+
+ /** Apache Ignite version when ODBC communication protocol version has been introduced. */
+ public static final String PROTO_VER_SINCE = "1.6.0";
+
+ /** Initial output stream capacity. */
+ private static final int INIT_CAP = 1024;
+
+ /** Marshaller. */
+ private final GridBinaryMarshaller marsh;
+
+ /** Logger. */
+ private final IgniteLogger log;
+
+ /** Protocol version confirmation flag. */
+ private boolean verConfirmed = false;
+
+ /**
+ * @param ctx Context.
+ */
+ public OdbcMessageParser(final GridKernalContext ctx) {
+ CacheObjectBinaryProcessorImpl cacheObjProc = (CacheObjectBinaryProcessorImpl)ctx.cacheObjects();
+
+ this.marsh = cacheObjProc.marshaller();
+
+ this.log = ctx.log(getClass());
+ }
+
+ /**
+ * Decode OdbcRequest from byte array.
+ *
+ * @param msg Message.
+ * @return Assembled ODBC request.
+ */
+ public OdbcRequest decode(byte[] msg) {
+ assert msg != null;
+
+ BinaryInputStream stream = new BinaryHeapInputStream(msg);
+
+ BinaryReaderExImpl reader = new BinaryReaderExImpl(null, stream, null);
+
+ byte cmd = reader.readByte();
+
+ // This is a special case because we can not decode protocol messages until
+ // we has not confirmed that the remote client uses the same protocol version.
+ if (!verConfirmed) {
+ if (cmd == OdbcRequest.HANDSHAKE)
+ return new OdbcHandshakeRequest(reader.readLong());
+ else
+ throw new IgniteException("Unexpected ODBC command (first message is not a handshake request): [cmd=" +
+ cmd + ']');
+ }
+
+ OdbcRequest res;
+
+ switch (cmd) {
+ case OdbcRequest.EXECUTE_SQL_QUERY: {
+ String cache = reader.readString();
+ String sql = reader.readString();
+ int argsNum = reader.readInt();
+
+ Object[] params = new Object[argsNum];
+
+ for (int i = 0; i < argsNum; ++i)
+ params[i] = reader.readObjectDetached();
+
+ res = new OdbcQueryExecuteRequest(cache, sql, params);
+
+ break;
+ }
+
+ case OdbcRequest.FETCH_SQL_QUERY: {
+ long queryId = reader.readLong();
+ int pageSize = reader.readInt();
+
+ res = new OdbcQueryFetchRequest(queryId, pageSize);
+
+ break;
+ }
+
+ case OdbcRequest.CLOSE_SQL_QUERY: {
+ long queryId = reader.readLong();
+
+ res = new OdbcQueryCloseRequest(queryId);
+
+ break;
+ }
+
+ case OdbcRequest.GET_COLUMNS_META: {
+ String cache = reader.readString();
+ String table = reader.readString();
+ String column = reader.readString();
+
+ res = new OdbcQueryGetColumnsMetaRequest(cache, table, column);
+
+ break;
+ }
+
+ case OdbcRequest.GET_TABLES_META: {
+ String catalog = reader.readString();
+ String schema = reader.readString();
+ String table = reader.readString();
+ String tableType = reader.readString();
+
+ res = new OdbcQueryGetTablesMetaRequest(catalog, schema, table, tableType);
+
+ break;
+ }
+
+ default:
+ throw new IgniteException("Unknown ODBC command: [cmd=" + cmd + ']');
+ }
+
+ return res;
+ }
+
+ /**
+ * Encode OdbcResponse to byte array.
+ *
+ * @param msg Message.
+ * @return Byte array.
+ */
+ public byte[] encode(OdbcResponse msg) {
+ assert msg != null;
+
+ // Creating new binary writer
+ BinaryWriterExImpl writer = marsh.writer(new BinaryHeapOutputStream(INIT_CAP));
+
+ // Writing status.
+ writer.writeByte((byte) msg.status());
+
+ if (msg.status() != OdbcResponse.STATUS_SUCCESS) {
+ writer.writeString(msg.error());
+
+ return writer.array();
+ }
+
+ Object res0 = msg.response();
+
+ if (res0 instanceof OdbcHandshakeResult) {
+ OdbcHandshakeResult res = (OdbcHandshakeResult) res0;
+
+ if (log.isDebugEnabled())
+ log.debug("Handshake result: " + (res.accepted() ? "accepted" : "rejected"));
+
+ verConfirmed = res.accepted();
+
+ if (res.accepted()) {
+ verConfirmed = true;
+
+ writer.writeBoolean(true);
+ }
+ else {
+ writer.writeBoolean(false);
+ writer.writeString(res.protoVerSince());
+ writer.writeString(res.currentVer());
+ }
+ }
+ else if (res0 instanceof OdbcQueryExecuteResult) {
+ OdbcQueryExecuteResult res = (OdbcQueryExecuteResult) res0;
+
+ if (log.isDebugEnabled())
+ log.debug("Resulting query ID: " + res.getQueryId());
+
+ writer.writeLong(res.getQueryId());
+
+ Collection<OdbcColumnMeta> metas = res.getColumnsMetadata();
+
+ assert metas != null;
+
+ writer.writeInt(metas.size());
+
+ for (OdbcColumnMeta meta : metas)
+ meta.write(writer);
+ }
+ else if (res0 instanceof OdbcQueryFetchResult) {
+ OdbcQueryFetchResult res = (OdbcQueryFetchResult) res0;
+
+ if (log.isDebugEnabled())
+ log.debug("Resulting query ID: " + res.queryId());
+
+ writer.writeLong(res.queryId());
+
+ Collection<?> items0 = res.items();
+
+ assert items0 != null;
+
+ writer.writeBoolean(res.last());
+
+ writer.writeInt(items0.size());
+
+ for (Object row0 : items0) {
+ if (row0 != null) {
+ Collection<?> row = (Collection<?>)row0;
+
+ writer.writeInt(row.size());
+
+ for (Object obj : row)
+ writer.writeObjectDetached(obj);
+ }
+ }
+ }
+ else if (res0 instanceof OdbcQueryCloseResult) {
+ OdbcQueryCloseResult res = (OdbcQueryCloseResult) res0;
+
+ if (log.isDebugEnabled())
+ log.debug("Resulting query ID: " + res.getQueryId());
+
+ writer.writeLong(res.getQueryId());
+ }
+ else if (res0 instanceof OdbcQueryGetColumnsMetaResult) {
+ OdbcQueryGetColumnsMetaResult res = (OdbcQueryGetColumnsMetaResult) res0;
+
+ Collection<OdbcColumnMeta> columnsMeta = res.meta();
+
+ assert columnsMeta != null;
+
+ writer.writeInt(columnsMeta.size());
+
+ for (OdbcColumnMeta columnMeta : columnsMeta)
+ columnMeta.write(writer);
+ }
+ else if (res0 instanceof OdbcQueryGetTablesMetaResult) {
+ OdbcQueryGetTablesMetaResult res = (OdbcQueryGetTablesMetaResult) res0;
+
+ Collection<OdbcTableMeta> tablesMeta = res.meta();
+
+ assert tablesMeta != null;
+
+ writer.writeInt(tablesMeta.size());
+
+ for (OdbcTableMeta tableMeta : tablesMeta)
+ tableMeta.writeBinary(writer);
+ }
+ else
+ assert false : "Should not reach here.";
+
+ return writer.array();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioListener.java
new file mode 100644
index 0000000..28b2b5a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioListener.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter;
+import org.apache.ignite.internal.util.nio.GridNioSession;
+import org.apache.ignite.internal.util.nio.GridNioSessionMetaKey;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * ODBC message listener.
+ */
+public class OdbcNioListener extends GridNioServerListenerAdapter<byte[]> {
+ /** Connection-related metadata key. */
+ private static final int CONNECTION_DATA_META_KEY = GridNioSessionMetaKey.nextUniqueKey();
+
+ /** Request ID generator. */
+ private static final AtomicLong REQ_ID_GEN = new AtomicLong();
+
+ /** Busy lock. */
+ private final GridSpinBusyLock busyLock;
+
+ /** Kernal context. */
+ private final GridKernalContext ctx;
+
+ /** Logger. */
+ private final IgniteLogger log;
+
+ /**
+ * @param ctx Context.
+ * @param busyLock Shutdown busy lock.
+ */
+ public OdbcNioListener(GridKernalContext ctx, GridSpinBusyLock busyLock) {
+ this.ctx = ctx;
+ this.busyLock = busyLock;
+ this.log = ctx.log(getClass());
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onConnected(GridNioSession ses) {
+ if (log.isDebugEnabled())
+ log.debug("ODBC client connected: " + ses.remoteAddress());
+
+ ses.addMeta(CONNECTION_DATA_META_KEY, new ConnectionData(ctx, busyLock));
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onDisconnected(GridNioSession ses, @Nullable Exception e) {
+ if (log.isDebugEnabled()) {
+ if (e == null)
+ log.debug("ODBC client disconnected: " + ses.remoteAddress());
+ else
+ log.debug("ODBC client disconnected due to an error [addr=" + ses.remoteAddress() + ", err=" + e + ']');
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onMessage(GridNioSession ses, byte[] msg) {
+ assert msg != null;
+
+ long reqId = REQ_ID_GEN.incrementAndGet();
+
+ ConnectionData connData = ses.meta(CONNECTION_DATA_META_KEY);
+
+ assert connData != null;
+
+ OdbcMessageParser parser = connData.getParser();
+
+ OdbcRequest req;
+
+ try {
+ req = parser.decode(msg);
+ }
+ catch (Exception e) {
+ log.error("Failed to parse message [id=" + reqId + ", err=" + e + ']');
+
+ ses.close();
+
+ return;
+ }
+
+ assert req != null;
+
+ try {
+ long startTime = 0;
+
+ if (log.isDebugEnabled()) {
+ startTime = System.nanoTime();
+
+ log.debug("ODBC request received [id=" + reqId + ", addr=" + ses.remoteAddress() +
+ ", req=" + req + ']');
+ }
+
+ OdbcRequestHandler handler = connData.getHandler();
+
+ OdbcResponse resp = handler.handle(req);
+
+ if (log.isDebugEnabled()) {
+ long dur = (System.nanoTime() - startTime) / 1000;
+
+ log.debug("ODBC request processed [id=" + reqId + ", dur(mcs)=" + dur +
+ ", resp=" + resp.status() + ']');
+ }
+
+ byte[] outMsg = parser.encode(resp);
+
+ ses.send(outMsg);
+ }
+ catch (Exception e) {
+ log.error("Failed to process ODBC request [id=" + reqId + ", err=" + e + ']');
+
+ ses.send(parser.encode(new OdbcResponse(OdbcResponse.STATUS_FAILED, e.getMessage())));
+ }
+ }
+
+ /**
+ * Connection-related data.
+ */
+ private static class ConnectionData {
+ /** Request handler. */
+ private final OdbcRequestHandler handler;
+
+ /** Message parser. */
+ private final OdbcMessageParser parser;
+
+ /**
+ * @param ctx Context.
+ * @param busyLock Shutdown busy lock.
+ */
+ public ConnectionData(GridKernalContext ctx, GridSpinBusyLock busyLock) {
+ handler = new OdbcRequestHandler(ctx, busyLock);
+ parser = new OdbcMessageParser(ctx);
+ }
+
+ /**
+ * Handler getter.
+ * @return Request handler for the connection.
+ */
+ public OdbcRequestHandler getHandler() {
+ return handler;
+ }
+
+ /**
+ * Parser getter
+ * @return Message parser for the connection.
+ */
+ public OdbcMessageParser getParser() {
+ return parser;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioServerBuffer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioServerBuffer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioServerBuffer.java
new file mode 100644
index 0000000..d1e6dd9
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcNioServerBuffer.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.ByteBuffer;
+
+/**
+ * NIO server buffer.
+ */
+public class OdbcNioServerBuffer {
+ /** Current message data. */
+ private byte[] data;
+
+ /** Count of received bytes of the current message. */
+ private int cnt = -4;
+
+ /** Current message size. */
+ private int msgSize;
+
+ /**
+ * Reset buffer state.
+ */
+ public void reset() {
+ msgSize = 0;
+ cnt = -4;
+ data = null;
+ }
+
+ /**
+ * Checks whether the byte array is filled.
+ *
+ * @return Flag indicating whether byte array is filled or not.
+ */
+ public boolean isFilled() {
+ return cnt > 0 && cnt == msgSize;
+ }
+
+ /**
+ * Get data withing the buffer.
+ *
+ * @return Data.
+ */
+ public byte[] data() {
+ return data;
+ }
+
+ /**
+ * @param buf Buffer.
+ * @return Message bytes or {@code null} if message is not fully read yet.
+ * @throws IgniteCheckedException If failed to parse message.
+ */
+ @Nullable public byte[] read(ByteBuffer buf) throws IgniteCheckedException {
+ if (cnt < 0) {
+ for (; cnt < 0 && buf.hasRemaining(); cnt++)
+ msgSize |= (buf.get() & 0xFF) << (8*(4 + cnt));
+
+ if (cnt < 0)
+ return null;
+
+ // If count is 0 then message size should be inited.
+ if (msgSize <= 0)
+ throw new IgniteCheckedException("Invalid message size: " + msgSize);
+
+ data = new byte[msgSize];
+ }
+
+ assert msgSize > 0;
+ assert cnt >= 0;
+
+ int remaining = buf.remaining();
+
+ // If there are more bytes in buffer.
+ if (remaining > 0) {
+ int missing = msgSize - cnt;
+
+ // Read only up to message size.
+ if (missing > 0) {
+ int len = missing < remaining ? missing : remaining;
+
+ buf.get(data, cnt, len);
+
+ cnt += len;
+ }
+ }
+
+ if (cnt == msgSize) {
+ byte[] data0 = data;
+
+ reset();
+
+ return data0;
+ }
+ else
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProcessor.java
new file mode 100644
index 0000000..87be686
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcProcessor.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.OdbcConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.GridProcessorAdapter;
+import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.nio.GridNioCodecFilter;
+import org.apache.ignite.internal.util.nio.GridNioServer;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.spi.IgnitePortProtocol;
+
+import java.net.InetAddress;
+import java.nio.ByteOrder;
+
+/**
+ * ODBC processor.
+ */
+public class OdbcProcessor extends GridProcessorAdapter {
+ /** Busy lock. */
+ private final GridSpinBusyLock busyLock = new GridSpinBusyLock();
+
+ /** OBCD TCP Server. */
+ private GridNioServer<byte[]> srv;
+
+ /**
+ * @param ctx Kernal context.
+ */
+ public OdbcProcessor(GridKernalContext ctx) {
+ super(ctx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void start() throws IgniteCheckedException {
+ OdbcConfiguration odbcCfg = ctx.config().getOdbcConfiguration();
+
+ if (odbcCfg != null) {
+ try {
+ Marshaller marsh = ctx.config().getMarshaller();
+
+ if (marsh != null && !(marsh instanceof BinaryMarshaller))
+ throw new IgniteCheckedException("ODBC can only be used with BinaryMarshaller (please set it " +
+ "through IgniteConfiguration.setMarshaller())");
+
+ String hostStr = odbcCfg.getHost();
+
+ if (hostStr == null)
+ hostStr = ctx.config().getLocalHost();
+
+ InetAddress host = U.resolveLocalHost(hostStr);
+
+ int port = odbcCfg.getPort();
+
+ srv = GridNioServer.<byte[]>builder()
+ .address(host)
+ .port(port)
+ .listener(new OdbcNioListener(ctx, busyLock))
+ .logger(log)
+ .selectorCount(odbcCfg.getSelectorCount())
+ .gridName(ctx.gridName())
+ .tcpNoDelay(odbcCfg.isNoDelay())
+ .directBuffer(odbcCfg.isDirectBuffer())
+ .byteOrder(ByteOrder.nativeOrder())
+ .socketSendBufferSize(odbcCfg.getSendBufferSize())
+ .socketReceiveBufferSize(odbcCfg.getReceiveBufferSize())
+ .sendQueueLimit(odbcCfg.getSendQueueLimit())
+ .filters(new GridNioCodecFilter(new OdbcBufferedParser(), log, false))
+ .directMode(false)
+ .idleTimeout(odbcCfg.getIdleTimeout())
+ .build();
+
+ srv.start();
+
+ ctx.ports().registerPort(port, IgnitePortProtocol.TCP, getClass());
+
+ log.info("ODBC processor has started on TCP port " + port);
+ }
+ catch (Exception e) {
+ throw new IgniteCheckedException("Failed to start ODBC processor.", e);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onKernalStop(boolean cancel) {
+ if (srv != null) {
+ busyLock.block();
+
+ srv.stop();
+
+ ctx.ports().deregisterPorts(getClass());
+
+ if (log.isDebugEnabled())
+ log.debug("ODBC processor stopped.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseRequest.java
new file mode 100644
index 0000000..8c081ef
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseRequest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC query close request.
+ */
+public class OdbcQueryCloseRequest extends OdbcRequest {
+ /** Query ID. */
+ private final long queryId;
+
+ /**
+ * @param queryId Query ID.
+ */
+ public OdbcQueryCloseRequest(long queryId) {
+ super(CLOSE_SQL_QUERY);
+
+ this.queryId = queryId;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long queryId() {
+ return queryId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcQueryCloseRequest.class, this);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseResult.java
new file mode 100644
index 0000000..9a85e43
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryCloseResult.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+/**
+ * ODBC query result.
+ */
+public class OdbcQueryCloseResult {
+ /** Query ID. */
+ private final long queryId;
+
+ /**
+ * @param queryId Query ID.
+ */
+ public OdbcQueryCloseResult(long queryId){
+ this.queryId = queryId;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long getQueryId() {
+ return queryId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteRequest.java
new file mode 100644
index 0000000..1bcd41f
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.tostring.GridToStringExclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+
+/**
+ * ODBC query execute request.
+ */
+public class OdbcQueryExecuteRequest extends OdbcRequest {
+ /** Cache name. */
+ private final String cacheName;
+
+ /** Sql query. */
+ private final String sqlQry;
+
+ /** Sql query arguments. */
+ @GridToStringExclude
+ private final Object[] args;
+
+ /**
+ * @param cacheName Cache name.
+ * @param sqlQry SQL query.
+ * @param args Arguments list.
+ */
+ public OdbcQueryExecuteRequest(String cacheName, String sqlQry, Object[] args) {
+ super(EXECUTE_SQL_QUERY);
+
+ this.cacheName = cacheName.isEmpty() ? null : cacheName;
+ this.sqlQry = sqlQry;
+ this.args = args;
+ }
+
+ /**
+ * @return Sql query.
+ */
+ public String sqlQuery() {
+ return sqlQry;
+ }
+
+ /**
+ * @return Sql query arguments.
+ */
+ public Object[] arguments() {
+ return args;
+ }
+
+ /**
+ * @return Cache name.
+ */
+ @Nullable public String cacheName() {
+ return cacheName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcQueryExecuteRequest.class, this, "args", Arrays.toString(args));
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteResult.java
new file mode 100644
index 0000000..a403812
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryExecuteResult.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import java.util.Collection;
+
+/**
+ * Query execute result.
+ */
+public class OdbcQueryExecuteResult {
+ /** Query ID. */
+ private final long queryId;
+
+ /** Fields metadata. */
+ private final Collection<OdbcColumnMeta> columnsMeta;
+
+ /**
+ * @param queryId Query ID.
+ * @param columnsMeta Columns metadata.
+ */
+ public OdbcQueryExecuteResult(long queryId, Collection<OdbcColumnMeta> columnsMeta) {
+ this.queryId = queryId;
+ this.columnsMeta = columnsMeta;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long getQueryId() {
+ return queryId;
+ }
+
+ /**
+ * @return Columns metadata.
+ */
+ public Collection<OdbcColumnMeta> getColumnsMetadata() {
+ return columnsMeta;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchRequest.java
new file mode 100644
index 0000000..58bc43a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchRequest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC query fetch request.
+ */
+public class OdbcQueryFetchRequest extends OdbcRequest {
+ /** Query ID. */
+ private final long queryId;
+
+ /** Page size - maximum number of rows to return. */
+ private final int pageSize;
+
+ /**
+ * @param queryId Query ID.
+ * @param pageSize Page size.
+ */
+ public OdbcQueryFetchRequest(long queryId, int pageSize) {
+ super(FETCH_SQL_QUERY);
+
+ this.queryId = queryId;
+ this.pageSize = pageSize;
+ }
+
+ /**
+ * @return Page size.
+ */
+ public int pageSize() {
+ return pageSize;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long queryId() {
+ return queryId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcQueryFetchRequest.class, this);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchResult.java
new file mode 100644
index 0000000..f72d7e1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryFetchResult.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import java.util.Collection;
+
+/**
+ * Query fetch result.
+ */
+public class OdbcQueryFetchResult {
+ /** Query ID. */
+ private final long queryId;
+
+ /** Query result rows. */
+ private final Collection<?> items;
+
+ /** Flag indicating the query has no unfetched results. */
+ private final boolean last;
+
+ /**
+ * @param queryId Query ID.
+ * @param items Query result rows.
+ * @param last Flag indicating the query has no unfetched results.
+ */
+ public OdbcQueryFetchResult(long queryId, Collection<?> items, boolean last){
+ this.queryId = queryId;
+ this.items = items;
+ this.last = last;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long queryId() {
+ return queryId;
+ }
+
+ /**
+ * @return Query result rows.
+ */
+ public Collection<?> items() {
+ return items;
+ }
+
+ /**
+ * @return Flag indicating the query has no unfetched results.
+ */
+ public boolean last() {
+ return last;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java
new file mode 100644
index 0000000..875be89
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaRequest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * ODBC query get columns meta request.
+ */
+public class OdbcQueryGetColumnsMetaRequest extends OdbcRequest {
+ /** Cache name. */
+ private final String cacheName;
+
+ /** Table name. */
+ private final String tableName;
+
+ /** Column name. */
+ private final String columnName;
+
+ /**
+ * @param cacheName Cache name.
+ * @param tableName Table name.
+ * @param columnName Column name.
+ */
+ public OdbcQueryGetColumnsMetaRequest(String cacheName, String tableName, String columnName) {
+ super(GET_COLUMNS_META);
+
+ this.cacheName = cacheName;
+ this.tableName = tableName;
+ this.columnName = columnName;
+ }
+
+ /**
+ * @return Cache name.
+ */
+ @Nullable public String cacheName() {
+ return cacheName;
+ }
+
+ /**
+ * @return Table name.
+ */
+ public String tableName() {
+ return tableName;
+ }
+
+ /**
+ * @return Column name.
+ */
+ public String columnName() {
+ return columnName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcQueryGetColumnsMetaRequest.class, this);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java
new file mode 100644
index 0000000..256b15b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetColumnsMetaResult.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import java.util.Collection;
+
+/**
+ * Query get columns meta result.
+ */
+public class OdbcQueryGetColumnsMetaResult {
+ /** Query result rows. */
+ private final Collection<OdbcColumnMeta> meta;
+
+ /**
+ * @param meta Column metadata.
+ */
+ public OdbcQueryGetColumnsMetaResult(Collection<OdbcColumnMeta> meta) {
+ this.meta = meta;
+ }
+
+ /**
+ * @return Query result rows.
+ */
+ public Collection<OdbcColumnMeta> meta() {
+ return meta;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java
new file mode 100644
index 0000000..a56aad2
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaRequest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * ODBC query get tables meta request.
+ */
+public class OdbcQueryGetTablesMetaRequest extends OdbcRequest {
+ /** Catalog search pattern. */
+ private final String catalog;
+
+ /** Schema search pattern. */
+ private final String schema;
+
+ /** Table search pattern. */
+ private final String table;
+
+ /** Table type search pattern. */
+ private final String tableType;
+
+ /**
+ * @param catalog Catalog search pattern.
+ * @param schema Schema search pattern.
+ * @param table Table search pattern.
+ * @param tableType Table type search pattern.
+ */
+ public OdbcQueryGetTablesMetaRequest(String catalog, String schema, String table, String tableType) {
+ super(GET_TABLES_META);
+
+ this.catalog = catalog;
+ this.schema = schema;
+ this.table = table;
+ this.tableType = tableType;
+ }
+
+ /**
+ * @return catalog search pattern.
+ */
+ public String catalog() {
+ return catalog;
+ }
+
+ /**
+ * @return Schema search pattern.
+ */
+ public String schema() {
+ return schema;
+ }
+
+ /**
+ * @return Table search pattern.
+ */
+ public String table() {
+ return table;
+ }
+
+ /**
+ * @return Table type search pattern.
+ */
+ public String tableType() {
+ return tableType;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(OdbcQueryGetTablesMetaRequest.class, this);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java
new file mode 100644
index 0000000..27bebd6
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcQueryGetTablesMetaResult.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+import java.util.Collection;
+
+/**
+ * Query get columns meta result.
+ */
+public class OdbcQueryGetTablesMetaResult {
+ /** Query result rows. */
+ private final Collection<OdbcTableMeta> meta;
+
+ /**
+ * @param meta Column metadata.
+ */
+ public OdbcQueryGetTablesMetaResult(Collection<OdbcTableMeta> meta) {
+ this.meta = meta;
+ }
+
+ /**
+ * @return Query result rows.
+ */
+ public Collection<OdbcTableMeta> meta() {
+ return meta;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/bae86159/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequest.java
new file mode 100644
index 0000000..ebecb60
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/OdbcRequest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.odbc;
+
+/**
+ * ODBC command request.
+ */
+public class OdbcRequest {
+ /** Handshake request. */
+ public static final int HANDSHAKE = 1;
+
+ /** Execute sql query. */
+ public static final int EXECUTE_SQL_QUERY = 2;
+
+ /** Fetch query results. */
+ public static final int FETCH_SQL_QUERY = 3;
+
+ /** Close query. */
+ public static final int CLOSE_SQL_QUERY = 4;
+
+ /** Get columns meta query. */
+ public static final int GET_COLUMNS_META = 5;
+
+ /** Get columns meta query. */
+ public static final int GET_TABLES_META = 6;
+
+ /** Command. */
+ private final int cmd;
+
+ /**
+ * @param cmd Command type.
+ */
+ public OdbcRequest(int cmd) {
+ this.cmd = cmd;
+ }
+
+ /**
+ * @return Command.
+ */
+ public int command() {
+ return cmd;
+ }
+}