/* * 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; 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 org.apache.ignite.internal.processors.odbc.OdbcQueryGetColumnsMetaRequest; import org.apache.ignite.internal.processors.odbc.OdbcQueryGetColumnsMetaResult; import org.apache.ignite.internal.processors.odbc.OdbcQueryGetParamsMetaRequest; import org.apache.ignite.internal.processors.odbc.OdbcQueryGetParamsMetaResult; import org.apache.ignite.internal.processors.odbc.OdbcQueryGetTablesMetaRequest; import org.apache.ignite.internal.processors.odbc.OdbcQueryGetTablesMetaResult; import org.apache.ignite.internal.processors.odbc.OdbcTableMeta; import org.apache.ignite.internal.processors.odbc.SqlListenerColumnMeta; import org.apache.ignite.internal.processors.odbc.SqlListenerMessageParser; import org.apache.ignite.internal.processors.odbc.SqlListenerQueryCloseRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerQueryCloseResult; import org.apache.ignite.internal.processors.odbc.SqlListenerQueryExecuteRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerQueryExecuteResult; import org.apache.ignite.internal.processors.odbc.SqlListenerQueryFetchRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerQueryFetchResult; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import java.util.Collection; /** * ODBC message parser. */ public class OdbcMessageParser implements SqlListenerMessageParser { /** Initial output stream capacity. */ private static final int INIT_CAP = 1024; /** Marshaller. */ private final GridBinaryMarshaller marsh; /** Logger. */ private final IgniteLogger log; /** * @param ctx Context. */ public OdbcMessageParser(final GridKernalContext ctx) { CacheObjectBinaryProcessorImpl cacheObjProc = (CacheObjectBinaryProcessorImpl)ctx.cacheObjects(); this.marsh = cacheObjProc.marshaller(); this.log = ctx.log(getClass()); } /** {@inheritDoc} */ @Override public SqlListenerRequest decode(byte[] msg) { assert msg != null; BinaryInputStream stream = new BinaryHeapInputStream(msg); BinaryReaderExImpl reader = new BinaryReaderExImpl(null, stream, null, true); byte cmd = reader.readByte(); SqlListenerRequest res; switch (cmd) { case SqlListenerRequest.QRY_EXEC: { 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 SqlListenerQueryExecuteRequest(cache, sql, params); break; } case SqlListenerRequest.QRY_FETCH: { long queryId = reader.readLong(); int pageSize = reader.readInt(); res = new SqlListenerQueryFetchRequest(queryId, pageSize); break; } case SqlListenerRequest.QRY_CLOSE: { long queryId = reader.readLong(); res = new SqlListenerQueryCloseRequest(queryId); break; } case SqlListenerRequest.META_COLS: { String cache = reader.readString(); String table = reader.readString(); String column = reader.readString(); res = new OdbcQueryGetColumnsMetaRequest(cache, table, column); break; } case SqlListenerRequest.META_TBLS: { String catalog = reader.readString(); String schema = reader.readString(); String table = reader.readString(); String tableType = reader.readString(); res = new OdbcQueryGetTablesMetaRequest(catalog, schema, table, tableType); break; } case SqlListenerRequest.META_PARAMS: { String cacheName = reader.readString(); String sqlQuery = reader.readString(); res = new OdbcQueryGetParamsMetaRequest(cacheName, sqlQuery); break; } default: throw new IgniteException("Unknown ODBC command: [cmd=" + cmd + ']'); } return res; } /** {@inheritDoc} */ @Override public byte[] encode(SqlListenerResponse 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() != SqlListenerResponse.STATUS_SUCCESS) { writer.writeString(msg.error()); return writer.array(); } Object res0 = msg.response(); if (res0 == null) return writer.array(); else if (res0 instanceof SqlListenerQueryExecuteResult) { SqlListenerQueryExecuteResult res = (SqlListenerQueryExecuteResult) res0; if (log.isDebugEnabled()) log.debug("Resulting query ID: " + res.getQueryId()); writer.writeLong(res.getQueryId()); Collection<SqlListenerColumnMeta> metas = res.getColumnsMetadata(); assert metas != null; writer.writeInt(metas.size()); for (SqlListenerColumnMeta meta : metas) meta.write(writer); } else if (res0 instanceof SqlListenerQueryFetchResult) { SqlListenerQueryFetchResult res = (SqlListenerQueryFetchResult) 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) { if (obj == null) { writer.writeObjectDetached(null); continue; } Class<?> cls = obj.getClass(); if (cls == java.sql.Time.class) writer.writeTime((java.sql.Time)obj); else if (cls == java.sql.Timestamp.class) writer.writeTimestamp((java.sql.Timestamp)obj); else if (cls == java.sql.Date.class) writer.writeDate((java.util.Date)obj); else writer.writeObjectDetached(obj); } } } } else if (res0 instanceof SqlListenerQueryCloseResult) { SqlListenerQueryCloseResult res = (SqlListenerQueryCloseResult) 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<SqlListenerColumnMeta> columnsMeta = res.meta(); assert columnsMeta != null; writer.writeInt(columnsMeta.size()); for (SqlListenerColumnMeta 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 if (res0 instanceof OdbcQueryGetParamsMetaResult) { OdbcQueryGetParamsMetaResult res = (OdbcQueryGetParamsMetaResult) res0; byte[] typeIds = res.typeIds(); writer.writeObjectDetached(typeIds); } else assert false : "Should not reach here."; return writer.array(); } }