ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From agoncha...@apache.org
Subject [06/34] ignite git commit: IGNITE-5176: JDBC thin driver: implemented query execution. This closes #1994. This closes #2040.
Date Mon, 05 Jun 2017 09:05:42 GMT
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java
deleted file mode 100644
index 1230bb4..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerRequestHandlerImpl.java
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * 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.sql.ParameterMetaData;
-import java.sql.PreparedStatement;
-import java.sql.Types;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.cache.query.QueryCursor;
-import org.apache.ignite.cache.query.SqlFieldsQuery;
-import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.binary.GridBinaryMarshaller;
-import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
-import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils;
-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.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiTuple;
-
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.META_COLS;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.META_PARAMS;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.META_TBLS;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.QRY_CLOSE;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.QRY_EXEC;
-import static org.apache.ignite.internal.processors.odbc.SqlListenerRequest.QRY_FETCH;
-
-/**
- * SQL query handler.
- */
-public class SqlListenerRequestHandlerImpl implements SqlListenerRequestHandler {
-    /** Query ID sequence. */
-    private static final AtomicLong QRY_ID_GEN = new AtomicLong();
-
-    /** Kernel context. */
-    private final GridKernalContext ctx;
-
-    /** Logger. */
-    private final IgniteLogger log;
-
-    /** Busy lock. */
-    private final GridSpinBusyLock busyLock;
-
-    /** Maximum allowed cursors. */
-    private final int maxCursors;
-
-    /** Current queries cursors. */
-    private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCursors = new ConcurrentHashMap<>();
-
-    /** Distributed joins flag. */
-    private final boolean distributedJoins;
-
-    /** Enforce join order flag. */
-    private final boolean enforceJoinOrder;
-
-    /**
-     * Constructor.
-     *
-     * @param ctx Context.
-     * @param busyLock Shutdown latch.
-     * @param maxCursors Maximum allowed cursors.
-     * @param distributedJoins Distributed joins flag.
-     * @param enforceJoinOrder Enforce join order flag.
-     */
-    public SqlListenerRequestHandlerImpl(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors,
-        boolean distributedJoins, boolean enforceJoinOrder) {
-        this.ctx = ctx;
-        this.busyLock = busyLock;
-        this.maxCursors = maxCursors;
-        this.distributedJoins = distributedJoins;
-        this.enforceJoinOrder = enforceJoinOrder;
-
-        log = ctx.log(getClass());
-    }
-
-    /** {@inheritDoc} */
-    @Override public SqlListenerResponse handle(SqlListenerRequest req) {
-        assert req != null;
-
-        if (!busyLock.enterBusy())
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Failed to handle ODBC request because node is stopping: " + req);
-
-        try {
-            switch (req.command()) {
-                case QRY_EXEC:
-                    return executeQuery((SqlListenerQueryExecuteRequest)req);
-
-                case QRY_FETCH:
-                    return fetchQuery((SqlListenerQueryFetchRequest)req);
-
-                case QRY_CLOSE:
-                    return closeQuery((SqlListenerQueryCloseRequest)req);
-
-                case META_COLS:
-                    return getColumnsMeta((OdbcQueryGetColumnsMetaRequest)req);
-
-                case META_TBLS:
-                    return getTablesMeta((OdbcQueryGetTablesMetaRequest)req);
-
-                case META_PARAMS:
-                    return getParamsMeta((OdbcQueryGetParamsMetaRequest)req);
-            }
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, "Unsupported ODBC request: " + req);
-        }
-        finally {
-            busyLock.leaveBusy();
-        }
-    }
-
-    /**
-     * {@link SqlListenerQueryExecuteRequest} command handler.
-     *
-     * @param req Execute query request.
-     * @return Response.
-     */
-    private SqlListenerResponse executeQuery(SqlListenerQueryExecuteRequest req) {
-        int cursorCnt = qryCursors.size();
-
-        if (maxCursors > 0 && cursorCnt >= maxCursors)
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, "Too many opened cursors (either close other " +
-                "opened cursors or increase the limit through OdbcConfiguration.setMaxOpenCursors()) " +
-                "[maximum=" + maxCursors + ", current=" + cursorCnt + ']');
-
-        long qryId = QRY_ID_GEN.getAndIncrement();
-
-        try {
-            String sql = OdbcEscapeUtils.parse(req.sqlQuery());
-
-            if (log.isDebugEnabled())
-                log.debug("ODBC query parsed [reqId=" + req.requestId() + ", original=" + req.sqlQuery() +
-                    ", parsed=" + sql + ']');
-
-            SqlFieldsQuery qry = new SqlFieldsQuery(sql);
-
-            qry.setArgs(req.arguments());
-
-            qry.setDistributedJoins(distributedJoins);
-            qry.setEnforceJoinOrder(enforceJoinOrder);
-
-            IgniteCache<Object, Object> cache0 = ctx.grid().cache(req.cacheName());
-
-            if (cache0 == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Cache doesn't exist (did you configure it?): " + req.cacheName());
-
-            IgniteCache<Object, Object> cache = cache0.withKeepBinary();
-
-            if (cache == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Can not get cache with keep binary: " + req.cacheName());
-
-            QueryCursor qryCur = cache.query(qry);
-
-            qryCursors.put(qryId, new IgniteBiTuple<QueryCursor, Iterator>(qryCur, null));
-
-            List<?> fieldsMeta = ((QueryCursorImpl) qryCur).fieldsMeta();
-
-            SqlListenerQueryExecuteResult res = new SqlListenerQueryExecuteResult(qryId, convertMetadata(fieldsMeta));
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            qryCursors.remove(qryId);
-
-            U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link SqlListenerQueryCloseRequest} command handler.
-     *
-     * @param req Execute query request.
-     * @return Response.
-     */
-    private SqlListenerResponse closeQuery(SqlListenerQueryCloseRequest req) {
-        try {
-            IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(req.queryId());
-
-            if (tuple == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Failed to find query with ID: " + req.queryId());
-
-            QueryCursor cur = tuple.get1();
-
-            assert(cur != null);
-
-            cur.close();
-
-            qryCursors.remove(req.queryId());
-
-            SqlListenerQueryCloseResult res = new SqlListenerQueryCloseResult(req.queryId());
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            qryCursors.remove(req.queryId());
-
-            U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + req.queryId() + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link SqlListenerQueryFetchRequest} command handler.
-     *
-     * @param req Execute query request.
-     * @return Response.
-     */
-    private SqlListenerResponse fetchQuery(SqlListenerQueryFetchRequest req) {
-        try {
-            IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(req.queryId());
-
-            if (tuple == null)
-                return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED,
-                    "Failed to find query with ID: " + req.queryId());
-
-            Iterator iter = tuple.get2();
-
-            if (iter == null) {
-                QueryCursor cur = tuple.get1();
-
-                iter = cur.iterator();
-
-                tuple.put(cur, iter);
-            }
-
-            List<Object> items = new ArrayList<>();
-
-            for (int i = 0; i < req.pageSize() && iter.hasNext(); ++i)
-                items.add(iter.next());
-
-            SqlListenerQueryFetchResult res = new SqlListenerQueryFetchResult(req.queryId(), items, !iter.hasNext());
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link OdbcQueryGetColumnsMetaRequest} command handler.
-     *
-     * @param req Get columns metadata request.
-     * @return Response.
-     */
-    private SqlListenerResponse getColumnsMeta(OdbcQueryGetColumnsMetaRequest req) {
-        try {
-            List<SqlListenerColumnMeta> 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;
-
-                    SqlListenerColumnMeta columnMeta = new SqlListenerColumnMeta(req.cacheName(), table.name(),
-                        field.getKey(), field.getValue());
-
-                    if (!meta.contains(columnMeta))
-                        meta.add(columnMeta);
-                }
-            }
-
-            OdbcQueryGetColumnsMetaResult res = new OdbcQueryGetColumnsMetaResult(meta);
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to get columns metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link OdbcQueryGetTablesMetaRequest} command handler.
-     *
-     * @param req Get tables metadata request.
-     * @return Response.
-     */
-    private SqlListenerResponse 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(null, cacheName, table.name(), "TABLE");
-
-                    if (!meta.contains(tableMeta))
-                        meta.add(tableMeta);
-                }
-            }
-
-            OdbcQueryGetTablesMetaResult res = new OdbcQueryGetTablesMetaResult(meta);
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to get tables metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * {@link OdbcQueryGetParamsMetaRequest} command handler.
-     *
-     * @param req Get params metadata request.
-     * @return Response.
-     */
-    private SqlListenerResponse getParamsMeta(OdbcQueryGetParamsMetaRequest req) {
-        try {
-            PreparedStatement stmt = ctx.query().prepareNativeStatement(req.cacheName(), req.query());
-
-            ParameterMetaData pmd = stmt.getParameterMetaData();
-
-            byte[] typeIds = new byte[pmd.getParameterCount()];
-
-            for (int i = 1; i <= pmd.getParameterCount(); ++i) {
-                int sqlType = pmd.getParameterType(i);
-
-                typeIds[i - 1] = sqlTypeToBinary(sqlType);
-            }
-
-            OdbcQueryGetParamsMetaResult res = new OdbcQueryGetParamsMetaResult(typeIds);
-
-            return new SqlListenerResponse(res);
-        }
-        catch (Exception e) {
-            U.error(log, "Failed to get params metadata [reqId=" + req.requestId() + ", req=" + req + ']', e);
-
-            return new SqlListenerResponse(SqlListenerResponse.STATUS_FAILED, e.toString());
-        }
-    }
-
-    /**
-     * Convert {@link java.sql.Types} to binary type constant (See {@link GridBinaryMarshaller} constants).
-     *
-     * @param sqlType SQL type.
-     * @return Binary type.
-     */
-    private static byte sqlTypeToBinary(int sqlType) {
-        switch (sqlType) {
-            case Types.BIGINT:
-                return GridBinaryMarshaller.LONG;
-
-            case Types.BOOLEAN:
-                return GridBinaryMarshaller.BOOLEAN;
-
-            case Types.DATE:
-                return GridBinaryMarshaller.DATE;
-
-            case Types.DOUBLE:
-                return GridBinaryMarshaller.DOUBLE;
-
-            case Types.FLOAT:
-            case Types.REAL:
-                return GridBinaryMarshaller.FLOAT;
-
-            case Types.NUMERIC:
-            case Types.DECIMAL:
-                return GridBinaryMarshaller.DECIMAL;
-
-            case Types.INTEGER:
-                return GridBinaryMarshaller.INT;
-
-            case Types.SMALLINT:
-                return GridBinaryMarshaller.SHORT;
-
-            case Types.TIME:
-                return GridBinaryMarshaller.TIME;
-
-            case Types.TIMESTAMP:
-                return GridBinaryMarshaller.TIMESTAMP;
-
-            case Types.TINYINT:
-                return GridBinaryMarshaller.BYTE;
-
-            case Types.CHAR:
-            case Types.VARCHAR:
-            case Types.LONGNVARCHAR:
-                return GridBinaryMarshaller.STRING;
-
-            case Types.NULL:
-                return GridBinaryMarshaller.NULL;
-
-            case Types.BINARY:
-            case Types.VARBINARY:
-            case Types.LONGVARBINARY:
-            default:
-                return GridBinaryMarshaller.BYTE_ARR;
-        }
-    }
-
-    /**
-     * Convert metadata in collection from {@link GridQueryFieldMetadata} to
-     * {@link SqlListenerColumnMeta}.
-     *
-     * @param meta Internal query field metadata.
-     * @return Odbc query field metadata.
-     */
-    private static Collection<SqlListenerColumnMeta> convertMetadata(Collection<?> meta) {
-        List<SqlListenerColumnMeta> res = new ArrayList<>();
-
-        if (meta != null) {
-            for (Object info : meta) {
-                assert info instanceof GridQueryFieldMetadata;
-
-                res.add(new SqlListenerColumnMeta((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/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
index 84c1e26..e35d8f2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerResponse.java
@@ -17,14 +17,12 @@
 
 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;
 
 /**
  * SQL listener response.
  */
-public class SqlListenerResponse {
+public abstract class SqlListenerResponse {
     /** Command succeeded. */
     public static final int STATUS_SUCCESS = 0;
 
@@ -32,26 +30,10 @@ public class SqlListenerResponse {
     public static final int STATUS_FAILED = 1;
 
     /** Success status. */
-    private final int status;
+    private int status;
 
     /** Error. */
-    private final String err;
-
-    /** Response object. */
-    @GridToStringInclude
-    private final Object obj;
-
-    /**
-     * Constructs successful rest response.
-     *
-     * @param obj Response object.
-     */
-    public SqlListenerResponse(Object obj) {
-        this.status = STATUS_SUCCESS;
-
-        this.obj = obj;
-        this.err = null;
-    }
+    private String err;
 
     /**
      * Constructs failed rest response.
@@ -60,11 +42,7 @@ public class SqlListenerResponse {
      * @param err Error, {@code null} if success is {@code true}.
      */
     public SqlListenerResponse(int status, @Nullable String err) {
-        assert status != STATUS_SUCCESS;
-
         this.status = status;
-
-        this.obj = null;
         this.err = err;
     }
 
@@ -76,10 +54,10 @@ public class SqlListenerResponse {
     }
 
     /**
-     * @return Response object.
+     * @param status Status.
      */
-    public Object response() {
-        return obj;
+    public void status(int status) {
+        this.status = status;
     }
 
     /**
@@ -89,8 +67,10 @@ public class SqlListenerResponse {
         return err;
     }
 
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(SqlListenerResponse.class, this);
+    /**
+     * @param err Error message.
+     */
+    public void error(String err) {
+        this.err = err;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java
new file mode 100644
index 0000000..196eafa
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerUtils.java
@@ -0,0 +1,250 @@
+/*
+ * 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.math.BigDecimal;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.UUID;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryUtils;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.binary.GridBinaryMarshaller;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Binary reader with marshaling non-primitive and non-embedded objects with JDK marshaller.
+ */
+@SuppressWarnings("unchecked")
+public abstract class SqlListenerUtils {
+    /**
+     * @param reader Reader.
+     * @param binObjAllow Allow to read non plaint objects.
+     * @return Read object.
+     * @throws BinaryObjectException On error.
+     */
+    @Nullable public static Object readObject(BinaryReaderExImpl reader, boolean binObjAllow)
+        throws BinaryObjectException {
+        byte type = reader.readByte();
+
+        switch (type) {
+            case GridBinaryMarshaller.NULL:
+                return null;
+
+            case GridBinaryMarshaller.BOOLEAN:
+                return reader.readBoolean();
+
+            case GridBinaryMarshaller.BYTE:
+                return reader.readByte();
+
+            case GridBinaryMarshaller.CHAR:
+                return reader.readChar();
+
+            case GridBinaryMarshaller.SHORT:
+                return reader.readShort();
+
+            case GridBinaryMarshaller.INT:
+                return reader.readInt();
+
+            case GridBinaryMarshaller.LONG:
+                return reader.readLong();
+
+            case GridBinaryMarshaller.FLOAT:
+                return reader.readFloat();
+
+            case GridBinaryMarshaller.DOUBLE:
+                return reader.readDouble();
+
+            case GridBinaryMarshaller.STRING:
+                return BinaryUtils.doReadString(reader.in());
+
+            case GridBinaryMarshaller.DECIMAL:
+                return BinaryUtils.doReadDecimal(reader.in());
+
+            case GridBinaryMarshaller.UUID:
+                return BinaryUtils.doReadUuid(reader.in());
+
+            case GridBinaryMarshaller.TIME:
+                return BinaryUtils.doReadTime(reader.in());
+
+            case GridBinaryMarshaller.TIMESTAMP:
+                return BinaryUtils.doReadTimestamp(reader.in());
+
+            case GridBinaryMarshaller.DATE:
+                return BinaryUtils.doReadDate(reader.in());
+
+            case GridBinaryMarshaller.BOOLEAN_ARR:
+                return BinaryUtils.doReadBooleanArray(reader.in());
+
+            case GridBinaryMarshaller.BYTE_ARR:
+                return BinaryUtils.doReadByteArray(reader.in());
+
+            case GridBinaryMarshaller.CHAR_ARR:
+                return BinaryUtils.doReadCharArray(reader.in());
+
+            case GridBinaryMarshaller.SHORT_ARR:
+                return BinaryUtils.doReadShortArray(reader.in());
+
+            case GridBinaryMarshaller.INT_ARR:
+                return BinaryUtils.doReadIntArray(reader.in());
+
+            case GridBinaryMarshaller.FLOAT_ARR:
+                return BinaryUtils.doReadFloatArray(reader.in());
+
+            case GridBinaryMarshaller.DOUBLE_ARR:
+                return BinaryUtils.doReadDoubleArray(reader.in());
+
+            case GridBinaryMarshaller.STRING_ARR:
+                return BinaryUtils.doReadStringArray(reader.in());
+
+            case GridBinaryMarshaller.DECIMAL_ARR:
+                return BinaryUtils.doReadDecimalArray(reader.in());
+
+            case GridBinaryMarshaller.UUID_ARR:
+                return BinaryUtils.doReadUuidArray(reader.in());
+
+            case GridBinaryMarshaller.TIME_ARR:
+                return BinaryUtils.doReadTimeArray(reader.in());
+
+            case GridBinaryMarshaller.TIMESTAMP_ARR:
+                return BinaryUtils.doReadTimestampArray(reader.in());
+
+            case GridBinaryMarshaller.DATE_ARR:
+                return BinaryUtils.doReadDateArray(reader.in());
+
+            default:
+                reader.in().position(reader.in().position() - 1);
+
+                if (binObjAllow)
+                    return reader.readObjectDetached();
+                else
+                    throw new BinaryObjectException("Custom objects are not supported");
+        }
+    }
+
+    /**
+     * @param writer Writer.
+     * @param obj Object to write.
+     * @param binObjAllow Allow to write non plain objects.
+     * @throws BinaryObjectException On error.
+     */
+    public static void writeObject(BinaryWriterExImpl writer, @Nullable Object obj, boolean binObjAllow)
+        throws BinaryObjectException {
+        if (obj == null) {
+            writer.writeByte(GridBinaryMarshaller.NULL);
+
+            return;
+        }
+
+        Class<?> cls = obj.getClass();
+
+        if (cls == Boolean.class)
+            writer.writeBooleanFieldPrimitive((Boolean)obj);
+        else if (cls == Byte.class)
+            writer.writeByteFieldPrimitive((Byte)obj);
+        else if (cls == Character.class)
+            writer.writeCharFieldPrimitive((Character)obj);
+        else if (cls == Short.class)
+            writer.writeShortFieldPrimitive((Short)obj);
+        else if (cls == Integer.class)
+            writer.writeIntFieldPrimitive((Integer)obj);
+        else if (cls == Long.class)
+            writer.writeLongFieldPrimitive((Long)obj);
+        else if (cls == Float.class)
+            writer.writeFloatFieldPrimitive((Float)obj);
+        else if (cls == Double.class)
+            writer.writeDoubleFieldPrimitive((Double)obj);
+        else if (cls == String.class)
+            writer.doWriteString((String)obj);
+        else if (cls == BigDecimal.class)
+            writer.doWriteDecimal((BigDecimal)obj);
+        else if (cls == UUID.class)
+            writer.writeUuid((UUID)obj);
+        else if (cls == Time.class)
+            writer.writeTime((Time)obj);
+        else if (cls == Timestamp.class)
+            writer.writeTimestamp((Timestamp)obj);
+        else if (cls == java.sql.Date.class || cls == java.util.Date.class)
+            writer.writeDate((java.util.Date)obj);
+        else if (cls == boolean[].class)
+            writer.writeBooleanArray((boolean[])obj);
+        else if (cls == byte[].class)
+            writer.writeByteArray((byte[])obj);
+        else if (cls == char[].class)
+            writer.writeCharArray((char[])obj);
+        else if (cls == short[].class)
+            writer.writeShortArray((short[])obj);
+        else if (cls == int[].class)
+            writer.writeIntArray((int[])obj);
+        else if (cls == float[].class)
+            writer.writeFloatArray((float[])obj);
+        else if (cls == double[].class)
+            writer.writeDoubleArray((double[])obj);
+        else if (cls == String[].class)
+            writer.writeStringArray((String[])obj);
+        else if (cls == BigDecimal[].class)
+            writer.writeDecimalArray((BigDecimal[])obj);
+        else if (cls == UUID[].class)
+            writer.writeUuidArray((UUID[])obj);
+        else if (cls == Time[].class)
+            writer.writeTimeArray((Time[])obj);
+        else if (cls == Timestamp[].class)
+            writer.writeTimestampArray((Timestamp[])obj);
+        else if (cls == java.util.Date[].class || cls == java.sql.Date[].class)
+            writer.writeDateArray((java.util.Date[])obj);
+        else if (binObjAllow)
+            writer.writeObjectDetached(obj);
+        else
+            throw new BinaryObjectException("Custom objects are not supported");
+    }
+
+    /**
+     * @param cls Class.
+     * @return {@code true} is the type is plain (not user's custom class).
+     */
+    public static boolean isPlainType(Class<?> cls) {
+        return cls == Boolean.class
+            || cls == Byte.class
+            || cls == Character.class
+            || cls == Short.class
+            || cls == Integer.class
+            || cls == Long.class
+            || cls == Float.class
+            || cls == Double.class
+            || cls == String.class
+            || cls == BigDecimal.class
+            || cls == UUID.class
+            || cls == Time.class
+            || cls == Timestamp.class
+            || cls == java.sql.Date.class || cls == java.util.Date.class
+            || cls == boolean[].class
+            || cls == byte[].class
+            || cls == char[].class
+            || cls == short[].class
+            || cls == int[].class
+            || cls == float[].class
+            || cls == double[].class
+            || cls == String[].class
+            || cls == BigDecimal[].class
+            || cls == UUID[].class
+            || cls == Time[].class
+            || cls == Timestamp[].class
+            || cls == java.util.Date[].class || cls == java.sql.Date[].class;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
new file mode 100644
index 0000000..07cbabe
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcColumnMeta.java
@@ -0,0 +1,129 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+
+/**
+ * SQL listener column metadata.
+ */
+public class JdbcColumnMeta implements JdbcRawBinarylizable {
+    /** Cache name. */
+    private String schemaName;
+
+    /** Table name. */
+    private String tableName;
+
+    /** Column name. */
+    private String columnName;
+
+    /** Data type. */
+    private int dataType;
+
+    /** Data type. */
+    private String dataTypeName;
+
+    /** Data type. */
+    private String dataTypeClass;
+
+    /**
+     * Default constructor is used for serialization.
+     */
+    public JdbcColumnMeta() {
+    }
+
+    /**
+     * @param info Field metadata.
+     */
+    public JdbcColumnMeta(GridQueryFieldMetadata info) {
+        this.schemaName = info.schemaName();
+        this.tableName = info.typeName();
+        this.columnName = info.fieldName();
+
+        dataType = JdbcThinUtils.type(info.fieldTypeName());
+        dataTypeName = JdbcThinUtils.typeName(info.fieldTypeName());
+        dataTypeClass = info.fieldTypeName();
+    }
+
+    /**
+     * @return Schema name.
+     */
+    public String schemaName() {
+        return schemaName;
+    }
+
+    /**
+     * @return Table name.
+     */
+    public String tableName() {
+        return tableName;
+    }
+
+    /**
+     * @return Column name.
+     */
+    public String columnName() {
+        return columnName;
+    }
+
+    /**
+     * @return Column's data type.
+     */
+    public int dataType() {
+        return dataType;
+    }
+
+    /**
+     * @return Column's data type name.
+     */
+    public String dataTypeName() {
+        return dataTypeName;
+    }
+
+    /**
+     * @return Column's data type class.
+     */
+    public String dataTypeClass() {
+        return dataTypeClass;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) {
+        writer.writeString(schemaName);
+        writer.writeString(tableName);
+        writer.writeString(columnName);
+
+        writer.writeInt(dataType);
+        writer.writeString(dataTypeName);
+        writer.writeString(dataTypeClass);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) {
+        schemaName = reader.readString();
+        tableName = reader.readString();
+        columnName = reader.readString();
+
+        dataType = reader.readInt();
+        dataTypeName = reader.readString();
+        dataTypeClass = reader.readString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
index cf87712..0f8a3ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcMessageParser.java
@@ -23,28 +23,65 @@ import org.apache.ignite.internal.binary.BinaryWriterExImpl;
 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.odbc.SqlListenerAbstractMessageParser;
+import org.apache.ignite.internal.processors.odbc.SqlListenerMessageParser;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+import org.apache.ignite.internal.processors.odbc.SqlListenerResponse;
 
 /**
  * JDBC message parser.
  */
-public class JdbcMessageParser extends SqlListenerAbstractMessageParser {
+public class JdbcMessageParser implements SqlListenerMessageParser {
+    /** Kernal context. */
+    private final GridKernalContext ctx;
+
+    /** Initial output stream capacity. */
+    protected static final int INIT_CAP = 1024;
+
     /**
      * @param ctx Context.
      */
     public JdbcMessageParser(GridKernalContext ctx) {
-        super(ctx, new JdbcObjectReader(), new JdbcObjectWriter());
+        this.ctx = ctx;
     }
 
-    /** {@inheritDoc} */
-    @Override protected BinaryReaderExImpl createReader(byte[] msg) {
+    /**
+     * @param msg Message.
+     * @return Reader.
+     */
+    protected BinaryReaderExImpl createReader(byte[] msg) {
         BinaryInputStream stream = new BinaryHeapInputStream(msg);
 
         return new BinaryReaderExImpl(null, stream, ctx.config().getClassLoader(), true);
     }
 
-    /** {@inheritDoc} */
-    @Override protected BinaryWriterExImpl createWriter(int cap) {
+    /**
+     * @param cap Capacisty
+     * @return Writer.
+     */
+    protected BinaryWriterExImpl createWriter(int cap) {
         return new BinaryWriterExImpl(null, new BinaryHeapOutputStream(cap), null, null);
     }
-}
+
+    /** {@inheritDoc} */
+    @Override public SqlListenerRequest decode(byte[] msg) {
+        assert msg != null;
+
+        BinaryReaderExImpl reader = createReader(msg);
+
+        return JdbcRequest.readRequest(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte[] encode(SqlListenerResponse msg) {
+        assert msg != null;
+
+        assert msg instanceof JdbcResponse;
+
+        JdbcResponse res = (JdbcResponse)msg;
+
+        BinaryWriterExImpl writer = createWriter(INIT_CAP);
+
+        res.writeBinary(writer);
+
+        return writer.array();
+    }}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java
deleted file mode 100644
index 81c8c10..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectReader.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.jdbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryReaderExImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractObjectReader;
-
-/**
- * Binary reader with marshaling non-primitive and non-embedded objects with JDK marshaller.
- */
-@SuppressWarnings("unchecked")
-public class JdbcObjectReader extends SqlListenerAbstractObjectReader {
-    /** {@inheritDoc} */
-    @Override protected Object readCustomObject(BinaryReaderExImpl reader) throws BinaryObjectException {
-        throw new BinaryObjectException("JDBC doesn't support custom objects.");
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java
deleted file mode 100644
index e87ef50..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcObjectWriter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.jdbc;
-
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.internal.binary.BinaryWriterExImpl;
-import org.apache.ignite.internal.processors.odbc.SqlListenerAbstractObjectWriter;
-
-/**
- * Binary writer with marshaling non-primitive and non-embedded objects with JDK marshaller..
- */
-public class JdbcObjectWriter extends SqlListenerAbstractObjectWriter {
-    /** {@inheritDoc} */
-    @Override protected void writeCustomObject(BinaryWriterExImpl writer, Object obj)
-        throws BinaryObjectException {
-        throw new BinaryObjectException("JDBC doesn't support custom objects.");
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java
new file mode 100644
index 0000000..411d1e0
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCloseRequest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query close request.
+ */
+public class JdbcQueryCloseRequest extends JdbcRequest {
+    /** Query ID. */
+    private long queryId;
+
+    /**
+     */
+    public JdbcQueryCloseRequest() {
+        super(QRY_CLOSE);
+    }
+
+    /**
+     * @param queryId Query ID.
+     */
+    public JdbcQueryCloseRequest(long queryId) {
+        super(QRY_CLOSE);
+
+        this.queryId = queryId;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryCloseRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java
new file mode 100644
index 0000000..b8edb8d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryCursor.java
@@ -0,0 +1,132 @@
+/*
+ * 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.jdbc;
+
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+
+/**
+ * SQL listener query fetch result.
+ */
+class JdbcQueryCursor {
+    /** Query ID. */
+    private final long queryId;
+
+    /** Fetch size. */
+    private int pageSize;
+
+    /** Max rows. */
+    private final long maxRows;
+
+    /** Number of fetched rows. */
+    private long fetched;
+
+    /** Query result rows. */
+    private final QueryCursorImpl<List<Object>> cur;
+
+    /** Query results iterator. */
+    private final Iterator<List<Object>> iter;
+
+    /**
+     * @param queryId Query ID.
+     * @param pageSize Fetch size.
+     * @param maxRows Max rows.
+     * @param cur Query cursor.
+     */
+    JdbcQueryCursor(long queryId, int pageSize, int maxRows, QueryCursorImpl<List<Object>> cur) {
+        this.queryId = queryId;
+        this.pageSize = pageSize;
+        this.maxRows = maxRows;
+        this.cur = cur;
+
+        iter = cur.iterator();
+    }
+
+    /**
+     * @return List of the rows.
+     */
+    List<List<Object>> fetchRows() {
+        List<List<Object>> items = new ArrayList<>();
+
+        int fetchSize0 = (maxRows > 0) ? (int)Math.min(pageSize, maxRows - fetched) : pageSize;
+
+        for (; fetched < fetchSize0 && iter.hasNext(); ++fetched)
+            items.add(iter.next());
+
+        return items;
+    }
+
+    /**
+     * @return Query metadata.
+     */
+    List<JdbcColumnMeta> meta() {
+        List<?> meta = cur.fieldsMeta();
+
+        List<JdbcColumnMeta> res = new ArrayList<>();
+
+        if (meta != null) {
+            for (Object info : meta) {
+                assert info instanceof GridQueryFieldMetadata;
+
+                res.add(new JdbcColumnMeta((GridQueryFieldMetadata)info));
+            }
+        }
+
+        return res;
+    }
+
+    /**
+     * @return {@code true} if the cursor has more rows
+     */
+    boolean hasNext() {
+        return iter.hasNext() && !(maxRows > 0 && fetched >= maxRows);
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /**
+     * Close the cursor.
+     */
+    public void close() {
+        cur.close();
+    }
+
+    /**
+     * @param pageSize New fetch size.
+     */
+    public void pageSize(int pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return {@code true} if this cursor corresponds to a {@link ResultSet} as a result of query,
+     * {@code false} if query was modifying operation like INSERT, UPDATE, or DELETE.
+     */
+    public boolean isQuery() {
+        return cur.isQuery();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
new file mode 100644
index 0000000..f132366
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerUtils;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * SQL listener query execute request.
+ */
+public class JdbcQueryExecuteRequest extends JdbcRequest {
+    /** Cache name. */
+    private String schemaName;
+
+    /** Fetch size. */
+    private int pageSize;
+
+    /** Max rows. */
+    private int maxRows;
+
+    /** Sql query. */
+    @GridToStringInclude(sensitive = true)
+    private String sqlQry;
+
+    /** Sql query arguments. */
+    @GridToStringInclude(sensitive = true)
+    private Object[] args;
+
+    /**
+     */
+    public JdbcQueryExecuteRequest() {
+        super(QRY_EXEC);
+    }
+
+    /**
+     * @param schemaName Cache name.
+     * @param pageSize Fetch size.
+     * @param maxRows Max rows.
+     * @param sqlQry SQL query.
+     * @param args Arguments list.
+     */
+    public JdbcQueryExecuteRequest(String schemaName, int pageSize, int maxRows, String sqlQry,
+        Object[] args) {
+        super(QRY_EXEC);
+
+        this.schemaName = F.isEmpty(schemaName) ? null : schemaName;
+        this.pageSize = pageSize;
+        this.maxRows = maxRows;
+        this.sqlQry = sqlQry;
+        this.args = args;
+    }
+
+    /**
+     * @return Fetch size.
+     */
+    public int pageSize() {
+        return pageSize;
+    }
+
+    /**
+     * @return Max rows.
+     */
+    public int maxRows() {
+        return maxRows;
+    }
+
+    /**
+     * @return Sql query.
+     */
+    public String sqlQuery() {
+        return sqlQry;
+    }
+
+    /**
+     * @return Sql query arguments.
+     */
+    public Object[] arguments() {
+        return args;
+    }
+
+    /**
+     * @return Cache name.
+     */
+    @Nullable public String schemaName() {
+        return schemaName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeString(schemaName);
+        writer.writeInt(pageSize);
+        writer.writeInt(maxRows);
+        writer.writeString(sqlQry);
+
+        writer.writeInt(args == null ? 0 : args.length);
+
+        if (args != null) {
+            for (Object arg : args)
+                SqlListenerUtils.writeObject(writer, arg, false);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        schemaName = reader.readString();
+        pageSize = reader.readInt();
+        maxRows = reader.readInt();
+        sqlQry = reader.readString();
+
+        int argsNum = reader.readInt();
+
+        args = new Object[argsNum];
+
+        for (int i = 0; i < argsNum; ++i)
+            args[i] = SqlListenerUtils.readObject(reader, false);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryExecuteRequest.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java
new file mode 100644
index 0000000..a935215
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteResult.java
@@ -0,0 +1,150 @@
+/*
+ * 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.jdbc;
+
+import java.util.List;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * SQL listener query execute result.
+ */
+public class JdbcQueryExecuteResult extends JdbcResult {
+    /** Query ID. */
+    private long queryId;
+
+    /** Query result rows. */
+    private List<List<Object>> items;
+
+    /** Flag indicating the query has no unfetched results. */
+    private boolean last;
+
+    /** Flag indicating the query is SELECT query. {@code false} for DML/DDL queries. */
+    private boolean isQuery;
+
+    /** Update count. */
+    private long updateCnt;
+
+    /**
+     * Condtructor.
+     */
+    public JdbcQueryExecuteResult() {
+        super(QRY_EXEC);
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param items Query result rows.
+     * @param last Flag indicates the query has no unfetched results.
+     */
+    public JdbcQueryExecuteResult(long queryId, List<List<Object>> items, boolean last) {
+        super(QRY_EXEC);
+
+        this.queryId = queryId;
+        this.items = items;
+        this.last = last;
+        this.isQuery = true;
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param updateCnt Update count for DML queries.
+     */
+    public JdbcQueryExecuteResult(long queryId, long updateCnt) {
+        super(QRY_EXEC);
+
+        this.queryId = queryId;
+        this.last = true;
+        this.isQuery = false;
+        this.updateCnt = updateCnt;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long getQueryId() {
+        return queryId;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public List<List<Object>> items() {
+        return items;
+    }
+
+    /**
+     * @return Flag indicating the query has no unfetched results.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /**
+     * @return Flag indicating the query is SELECT query. {@code false} for DML/DDL queries.
+     */
+    public boolean isQuery() {
+        return isQuery;
+    }
+
+    /**
+     * @return Update count for DML queries.
+     */
+    public long updateCount() {
+        return updateCnt;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+        writer.writeBoolean(isQuery);
+
+        if (isQuery) {
+            assert items != null;
+
+            writer.writeBoolean(last);
+
+            JdbcUtils.writeItems(writer, items);
+        }
+        else
+            writer.writeLong(updateCnt);
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+        isQuery = reader.readBoolean();
+
+        if (isQuery) {
+            last = reader.readBoolean();
+
+            items = JdbcUtils.readItems(reader);
+        }
+        else {
+            last = true;
+
+            updateCnt = reader.readLong();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java
new file mode 100644
index 0000000..2e1f551
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchRequest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query fetch request.
+ */
+public class JdbcQueryFetchRequest extends JdbcRequest {
+    /** Query ID. */
+    private long queryId;
+
+    /** Fetch size. */
+    private int pageSize;
+
+    /**
+     * Constructor.
+     */
+    public JdbcQueryFetchRequest() {
+        super(QRY_FETCH);
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param pageSize Fetch size.
+     */
+    public JdbcQueryFetchRequest(long queryId, int pageSize) {
+        super(QRY_FETCH);
+
+        this.queryId = queryId;
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /**
+     * @return Fetch page size.
+     */
+    public int pageSize() {
+        return pageSize;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+        writer.writeInt(pageSize);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+        pageSize = reader.readInt();
+   }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryFetchRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java
new file mode 100644
index 0000000..6735c6b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryFetchResult.java
@@ -0,0 +1,84 @@
+/*
+ * 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.jdbc;
+
+import java.util.List;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * SQL listener query fetch result.
+ */
+public class JdbcQueryFetchResult extends JdbcResult {
+    /** Query result rows. */
+    private List<List<Object>> items;
+
+    /** Flag indicating the query has no unfetched results. */
+    private boolean last;
+
+    /**
+     * Default constructor is used for deserialization.
+     */
+    public JdbcQueryFetchResult() {
+        super(QRY_FETCH);
+    }
+
+    /**
+     * @param items Query result rows.
+     * @param last Flag indicating the query has no unfetched results.
+     */
+    public JdbcQueryFetchResult(List<List<Object>> items, boolean last){
+        super(QRY_FETCH);
+
+        this.items = items;
+        this.last = last;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public List<List<Object>> items() {
+        return items;
+    }
+
+    /**
+     * @return Flag indicating the query has no unfetched results.
+     */
+    public boolean last() {
+        return last;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeBoolean(last);
+
+        JdbcUtils.writeItems(writer, items);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        last = reader.readBoolean();
+
+        items = JdbcUtils.readItems(reader);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java
new file mode 100644
index 0000000..d14c9df
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataRequest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ * SQL listener query metadata request.
+ */
+public class JdbcQueryMetadataRequest extends JdbcRequest {
+    /** Query ID. */
+    private long queryId;
+
+    /**
+     * Constructor.
+     */
+    public JdbcQueryMetadataRequest() {
+        super(QRY_META);
+    }
+
+    /**
+     * @param queryId Query ID.
+     */
+    public JdbcQueryMetadataRequest(long queryId) {
+        super(QRY_META);
+
+        this.queryId = queryId;
+    }
+
+    /**
+     * @return Query ID.
+     */
+    public long queryId() {
+        return queryId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        writer.writeLong(queryId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        queryId = reader.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JdbcQueryMetadataRequest.class, this);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java
new file mode 100644
index 0000000..cc193e3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryMetadataResult.java
@@ -0,0 +1,93 @@
+/*
+ * 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.jdbc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * SQL listener query metadata result.
+ */
+public class JdbcQueryMetadataResult extends JdbcResult {
+    /** Fields metadata. */
+    private List<JdbcColumnMeta> meta;
+
+    /**
+     * Default constructor is used for deserialization.
+     */
+    public JdbcQueryMetadataResult() {
+        super(QRY_META);
+    }
+
+    /**
+     * @param queryId Query ID.
+     * @param meta Query metadata.
+     */
+    public JdbcQueryMetadataResult(long queryId, List<JdbcColumnMeta> meta){
+        super(QRY_META);
+
+        this.meta = meta;
+    }
+
+    /**
+     * @return Query result rows.
+     */
+    public List<JdbcColumnMeta> meta() {
+        return meta;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        super.writeBinary(writer);
+
+        if (F.isEmpty(meta))
+            writer.writeInt(0);
+        else {
+            writer.writeInt(meta.size());
+
+            for (JdbcColumnMeta m : meta)
+                m.writeBinary(writer);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        super.readBinary(reader);
+
+        int size = reader.readInt();
+
+        if (size == 0)
+            meta = Collections.emptyList();
+        else {
+            meta = new ArrayList<>(size);
+
+            for (int i = 0; i < size; ++i) {
+                JdbcColumnMeta m = new JdbcColumnMeta();
+
+                m.readBinary(reader);
+
+                meta.add(m);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java
new file mode 100644
index 0000000..c3f1874
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRawBinarylizable.java
@@ -0,0 +1,44 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+
+/**
+ * Interface that allows to implement custom serialization
+ * logic to raw binary streams.
+ */
+public interface JdbcRawBinarylizable {
+    /**
+     * Writes fields to provided writer.
+     *
+     * @param writer Binary object writer.
+     * @throws BinaryObjectException In case of error.
+     */
+    public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException;
+
+    /**
+     * Reads fields from provided reader.
+     *
+     * @param reader Binary object reader.
+     * @throws BinaryObjectException In case of error.
+     */
+    public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java
new file mode 100644
index 0000000..d6f8fd3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.jdbc;
+
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.internal.binary.BinaryReaderExImpl;
+import org.apache.ignite.internal.binary.BinaryWriterExImpl;
+import org.apache.ignite.internal.processors.odbc.SqlListenerRequest;
+
+/**
+ * SQL listener command request.
+ */
+public class JdbcRequest extends SqlListenerRequest implements JdbcRawBinarylizable {
+    /** Execute sql query. */
+    public static final byte QRY_EXEC = 2;
+
+    /** Fetch query results. */
+    public static final byte QRY_FETCH = 3;
+
+    /** Close query. */
+    public static final byte QRY_CLOSE = 4;
+
+    /** Get columns meta query. */
+    public static final byte QRY_META = 5;
+
+    /** Request type. */
+    private byte type;
+
+    /**
+     * @param type Command type.
+     */
+    public JdbcRequest(byte type) {
+        this.type = type;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException {
+        writer.writeByte(type);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException {
+        // No-op.
+    }
+
+    /**
+     * @return Request type.
+     */
+    public byte type() {
+        return type;
+    }
+
+    /**
+     * @param reader Binary reader.
+     * @return Request object.
+     * @throws BinaryObjectException On error.
+     */
+    public static JdbcRequest readRequest(BinaryReaderExImpl reader) throws BinaryObjectException {
+        int reqType = reader.readByte();
+
+        JdbcRequest req;
+
+        switch(reqType) {
+            case QRY_EXEC:
+                req = new JdbcQueryExecuteRequest();
+
+                break;
+
+            case QRY_FETCH:
+                req = new JdbcQueryFetchRequest();
+
+                break;
+
+            case QRY_META:
+                req = new JdbcQueryMetadataRequest();
+
+                break;
+
+            case QRY_CLOSE:
+                req = new JdbcQueryCloseRequest();
+
+                break;
+
+            default:
+                throw new IgniteException("Unknown SQL listener request ID: [request ID=" + reqType + ']');
+        }
+
+        req.readBinary(reader);
+
+        return req;
+    }
+}


Mime
View raw message