IGNITE-4370: Implemented writing of batch of parameters for ODBC.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c10be578 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c10be578 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c10be578 Branch: refs/heads/master Commit: c10be5780589cc84e7929e234e4411d515166e0b Parents: 1288531 Author: Igor Sapego <[email protected]> Authored: Thu Jun 15 16:54:05 2017 +0300 Committer: Igor Sapego <[email protected]> Committed: Thu Jun 15 16:54:05 2017 +0300 ---------------------------------------------------------------------- .../processors/odbc/odbc/OdbcMessageParser.java | 55 ++- .../odbc/odbc/OdbcQueryExecuteBatchRequest.java | 95 +++++ .../odbc/odbc/OdbcQueryExecuteBatchResult.java | 75 ++++ .../odbc/odbc/OdbcQueryExecuteRequest.java | 6 +- .../odbc/odbc/OdbcQueryExecuteResult.java | 2 +- .../processors/odbc/odbc/OdbcRequest.java | 4 +- .../odbc/odbc/OdbcRequestHandler.java | 108 ++++- .../platforms/cpp/core-test/src/test_utils.cpp | 1 + .../src/application_data_buffer_test.cpp | 176 +++----- .../platforms/cpp/odbc-test/src/column_test.cpp | 21 +- .../cpp/odbc-test/src/queries_test.cpp | 404 +++++++++++++++++- .../platforms/cpp/odbc-test/src/row_test.cpp | 9 +- .../platforms/cpp/odbc-test/src/test_utils.cpp | 1 + modules/platforms/cpp/odbc/Makefile.am | 3 + modules/platforms/cpp/odbc/include/Makefile.am | 2 + .../ignite/odbc/app/application_data_buffer.h | 38 +- .../odbc/include/ignite/odbc/app/parameter.h | 20 +- .../include/ignite/odbc/app/parameter_set.h | 268 ++++++++++++ .../ignite/odbc/diagnostic/diagnosable.h | 4 +- .../cpp/odbc/include/ignite/odbc/message.h | 411 +++++++------------ .../include/ignite/odbc/query/batch_query.h | 160 ++++++++ .../odbc/include/ignite/odbc/query/data_query.h | 12 +- .../cpp/odbc/include/ignite/odbc/query/query.h | 3 + .../include/ignite/odbc/query/type_info_query.h | 2 +- .../cpp/odbc/include/ignite/odbc/statement.h | 50 +-- .../platforms/cpp/odbc/project/vs/odbc.vcxproj | 5 + .../cpp/odbc/project/vs/odbc.vcxproj.filters | 15 + .../odbc/src/app/application_data_buffer.cpp | 90 +++- .../platforms/cpp/odbc/src/app/parameter.cpp | 11 +- .../cpp/odbc/src/app/parameter_set.cpp | 242 +++++++++++ modules/platforms/cpp/odbc/src/column.cpp | 1 - .../cpp/odbc/src/config/connection_info.cpp | 36 ++ modules/platforms/cpp/odbc/src/message.cpp | 373 +++++++++++++++++ .../cpp/odbc/src/query/batch_query.cpp | 198 +++++++++ .../platforms/cpp/odbc/src/query/data_query.cpp | 13 +- modules/platforms/cpp/odbc/src/statement.cpp | 250 ++++++----- 36 files changed, 2542 insertions(+), 622 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java index 91ed139..08cce1e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java @@ -33,6 +33,7 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerMessageParser; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.SqlListenerUtils; +import org.jetbrains.annotations.NotNull; /** * JDBC message parser. @@ -85,18 +86,32 @@ public class OdbcMessageParser implements SqlListenerMessageParser { case OdbcRequest.QRY_EXEC: { String schema = reader.readString(); String sql = reader.readString(); - int argsNum = reader.readInt(); + int paramNum = reader.readInt(); - Object[] params = new Object[argsNum]; - - for (int i = 0; i < argsNum; ++i) - params[i] = SqlListenerUtils.readObject(reader, true); + Object[] params = readParameterRow(reader, paramNum); res = new OdbcQueryExecuteRequest(schema, sql, params); break; } + case OdbcRequest.QRY_EXEC_BATCH: { + String schema = reader.readString(); + String sql = reader.readString(); + int paramRowLen = reader.readInt(); + int rowNum = reader.readInt(); + boolean last = reader.readBoolean(); + + Object[][] params = new Object[rowNum][]; + + for (int i = 0; i < rowNum; ++i) + params[i] = readParameterRow(reader, paramRowLen); + + res = new OdbcQueryExecuteBatchRequest(schema, sql, last, params); + + break; + } + case OdbcRequest.QRY_FETCH: { long queryId = reader.readLong(); int pageSize = reader.readInt(); @@ -151,6 +166,21 @@ public class OdbcMessageParser implements SqlListenerMessageParser { return res; } + /** + * Read row of parameters using reader. + * @param reader reader + * @param paramNum Number of parameters in a row + * @return Parameters array. + */ + @NotNull private static Object[] readParameterRow(BinaryReaderExImpl reader, int paramNum) { + Object[] params = new Object[paramNum]; + + for (int i = 0; i < paramNum; ++i) + params[i] = SqlListenerUtils.readObject(reader, true); + + return params; + } + /** {@inheritDoc} */ @Override public byte[] encode(SqlListenerResponse msg0) { assert msg0 != null; @@ -180,9 +210,9 @@ public class OdbcMessageParser implements SqlListenerMessageParser { OdbcQueryExecuteResult res = (OdbcQueryExecuteResult) res0; if (log.isDebugEnabled()) - log.debug("Resulting query ID: " + res.getQueryId()); + log.debug("Resulting query ID: " + res.queryId()); - writer.writeLong(res.getQueryId()); + writer.writeLong(res.queryId()); Collection<OdbcColumnMeta> metas = res.getColumnsMetadata(); @@ -193,6 +223,17 @@ public class OdbcMessageParser implements SqlListenerMessageParser { for (OdbcColumnMeta meta : metas) meta.write(writer); } + else if (res0 instanceof OdbcQueryExecuteBatchResult) { + OdbcQueryExecuteBatchResult res = (OdbcQueryExecuteBatchResult) res0; + + writer.writeBoolean(res.errorMessage() == null); + writer.writeLong(res.rowsAffected()); + + if (res.errorMessage() != null) { + writer.writeLong(res.errorSetIdx()); + writer.writeString(res.errorMessage()); + } + } else if (res0 instanceof OdbcQueryFetchResult) { OdbcQueryFetchResult res = (OdbcQueryFetchResult) res0; http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java new file mode 100644 index 0000000..50d16e5 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java @@ -0,0 +1,95 @@ +package org.apache.ignite.internal.processors.odbc.odbc; + +/* + * 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. + */ + +import org.apache.ignite.internal.util.tostring.GridToStringExclude; +import org.apache.ignite.internal.util.tostring.GridToStringInclude; +import org.apache.ignite.internal.util.typedef.internal.S; +import org.jetbrains.annotations.Nullable; + +/** + * ODBC query execute request with the batch of parameters. + */ +public class OdbcQueryExecuteBatchRequest extends OdbcRequest { + /** Schema. */ + @GridToStringInclude(sensitive = true) + private final String schema; + + /** Sql query. */ + @GridToStringInclude(sensitive = true) + private final String sqlQry; + + /** Last param page flag. */ + private final boolean last; + + /** Sql query arguments. */ + @GridToStringExclude + private final Object[][] args; + + /** + * @param schema Schema. + * @param sqlQry SQL query. + * @param last Last page flag. + * @param args Arguments list. + */ + public OdbcQueryExecuteBatchRequest(@Nullable String schema, String sqlQry, boolean last, Object[][] args) { + super(QRY_EXEC_BATCH); + + assert sqlQry != null : "SQL query should not be null"; + assert args != null : "Parameters should not be null"; + + this.schema = schema; + this.sqlQry = sqlQry; + this.last = last; + this.args = args; + } + + /** + * @return Sql query. + */ + public String sqlQuery() { + return sqlQry; + } + + /** + * @return Sql query arguments. + */ + public Object[][] arguments() { + return args; + } + + /** + * @return Schema. + */ + @Nullable + public String schema() { + return schema; + } + + /** + * @return Last page flag. + */ + public boolean last() { + return last; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(OdbcQueryExecuteBatchRequest.class, this, "args", args, true); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java new file mode 100644 index 0000000..ee02fd6 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java @@ -0,0 +1,75 @@ +/* + * 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.jetbrains.annotations.Nullable; + +/** + * ODBC query execute with batch of parameters result. + */ +public class OdbcQueryExecuteBatchResult { + /** Rows affected. */ + private final long rowsAffected; + + /** Index of the set which caused an error. */ + private final long errorSetIdx; + + /** Error message. */ + private final String errorMessage; + + /** + * @param rowsAffected Number of rows affected by the query. + */ + public OdbcQueryExecuteBatchResult(long rowsAffected) { + this.rowsAffected = rowsAffected; + this.errorSetIdx = -1; + this.errorMessage = null; + } + + /** + * @param rowsAffected Number of rows affected by the query. + * @param errorSetIdx Sets processed. + * @param errorMessage Error message. + */ + public OdbcQueryExecuteBatchResult(long rowsAffected, long errorSetIdx, String errorMessage) { + this.rowsAffected = rowsAffected; + this.errorSetIdx = errorSetIdx; + this.errorMessage = errorMessage; + } + + /** + * @return Number of rows affected by the query. + */ + public long rowsAffected() { + return rowsAffected; + } + + /** + * @return Index of the set which caused an error or -1 if no error occurred. + */ + public long errorSetIdx() { + return errorSetIdx; + } + + /** + * @return Error message. + */ + @Nullable public String errorMessage() { + return errorMessage; + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java index 8bb61dc..26d3328 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java @@ -42,10 +42,12 @@ public class OdbcQueryExecuteRequest extends OdbcRequest { * @param sqlQry SQL query. * @param args Arguments list. */ - public OdbcQueryExecuteRequest(String schema, String sqlQry, Object[] args) { + public OdbcQueryExecuteRequest(@Nullable String schema, String sqlQry, Object[] args) { super(QRY_EXEC); - this.schema = schema.isEmpty() ? null : schema; + assert sqlQry != null : "SQL query should not be null"; + + this.schema = schema; this.sqlQry = sqlQry; this.args = args; } http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java index de5a8fd..4b8ecbe 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteResult.java @@ -41,7 +41,7 @@ public class OdbcQueryExecuteResult { /** * @return Query ID. */ - public long getQueryId() { + public long queryId() { return queryId; } http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java index 825e770..62c4de3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequest.java @@ -41,8 +41,8 @@ public class OdbcRequest extends SqlListenerRequest { /** Get parameters meta. */ public static final int META_PARAMS = 7; - /** Get parameters meta. */ - public static final int JDBC_REQ = 8; + /** Execute sql query with the batch of parameters. */ + public static final int QRY_EXEC_BATCH = 8; /** Command. */ private final int cmd; http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java index dfcd462..0c65edd 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java @@ -27,6 +27,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; + +import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.cache.query.QueryCursor; import org.apache.ignite.cache.query.SqlFieldsQuery; @@ -45,12 +47,7 @@ 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.odbc.OdbcRequest.META_COLS; -import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_PARAMS; -import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.META_TBLS; -import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_CLOSE; -import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_EXEC; -import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.QRY_FETCH; +import static org.apache.ignite.internal.processors.odbc.odbc.OdbcRequest.*; /** * SQL query handler. @@ -59,6 +56,9 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler { /** Query ID sequence. */ private static final AtomicLong QRY_ID_GEN = new AtomicLong(); + /** Batch query ID sequence. */ + private static final AtomicLong BATCH_QRY_ID_GEN = new AtomicLong(); + /** Kernel context. */ private final GridKernalContext ctx; @@ -115,6 +115,9 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler { case QRY_EXEC: return executeQuery((OdbcQueryExecuteRequest)req); + case QRY_EXEC_BATCH: + return executeBatchQuery((OdbcQueryExecuteBatchRequest)req); + case QRY_FETCH: return fetchQuery((OdbcQueryFetchRequest)req); @@ -194,6 +197,99 @@ public class OdbcRequestHandler implements SqlListenerRequestHandler { } /** + * {@link OdbcQueryExecuteBatchRequest} command handler. + * + * @param req Execute query request. + * @return Response. + */ + private SqlListenerResponse executeBatchQuery(OdbcQueryExecuteBatchRequest req) { + long rowsAffected = 0; + int currentSet = 0; + + 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.setDistributedJoins(distributedJoins); + qry.setEnforceJoinOrder(enforceJoinOrder); + qry.setSchema(req.schema()); + + Object[][] paramSet = req.arguments(); + + if (paramSet.length <= 0) + throw new IgniteException("Batch execute request with non-positive batch length. [len=" + + paramSet.length + ']'); + + // Getting meta and do the checks for the first execution. + qry.setArgs(paramSet[0]); + + QueryCursorImpl<List<?>> qryCur = (QueryCursorImpl<List<?>>)ctx.query().querySqlFieldsNoCache(qry, true); + + if (qryCur.isQuery()) + throw new IgniteException("Batching of parameters only supported for DML statements. [query=" + + req.sqlQuery() + ']'); + + rowsAffected += getRowsAffected(qryCur); + + for (currentSet = 1; currentSet < paramSet.length; ++currentSet) + rowsAffected += executeQuery(qry, paramSet[currentSet]); + + OdbcQueryExecuteBatchResult res = new OdbcQueryExecuteBatchResult(rowsAffected); + + return new OdbcResponse(res); + } + catch (Exception e) { + U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e); + + OdbcQueryExecuteBatchResult res = new OdbcQueryExecuteBatchResult(rowsAffected, currentSet, + e.getMessage()); + + return new OdbcResponse(res); + } + } + + /** + * Execute query. + * @param qry Query + * @param row Row + * @return Affected rows. + */ + private long executeQuery(SqlFieldsQuery qry, Object[] row) { + qry.setArgs(row); + + QueryCursor<List<?>> cur = ctx.query().querySqlFieldsNoCache(qry, true); + + return getRowsAffected(cur); + } + + /** + * Get affected rows for DML statement. + * @param qryCur Cursor. + * @return Number of table rows affected. + */ + private static long getRowsAffected(QueryCursor<List<?>> qryCur) { + Iterator<List<?>> iter = qryCur.iterator(); + + if (iter.hasNext()) { + List<?> res = iter.next(); + + if (res.size() > 0) { + Long affected = (Long) res.get(0); + + if (affected != null) + return affected; + } + } + + return 0; + } + + /** * {@link OdbcQueryCloseRequest} command handler. * * @param req Execute query request. http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/core-test/src/test_utils.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/test_utils.cpp b/modules/platforms/cpp/core-test/src/test_utils.cpp index c6e4454..ded229e 100644 --- a/modules/platforms/cpp/core-test/src/test_utils.cpp +++ b/modules/platforms/cpp/core-test/src/test_utils.cpp @@ -36,6 +36,7 @@ namespace ignite_test cfg.jvmOpts.push_back("-DIGNITE_QUIET=false"); cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false"); cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false"); + cfg.jvmOpts.push_back("-Duser.language=en"); std::string home; bool homeFound = jni::ResolveIgniteHome("", home); http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp b/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp index 4454066..5c9e90a 100644 --- a/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/application_data_buffer_test.cpp @@ -44,9 +44,8 @@ BOOST_AUTO_TEST_CASE(TestPutIntToString) { char buffer[1024]; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen); appBuf.PutInt8(12); BOOST_CHECK(!strcmp(buffer, "12")); @@ -77,9 +76,8 @@ BOOST_AUTO_TEST_CASE(TestPutFloatToString) { char buffer[1024]; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen); appBuf.PutFloat(12.42f); BOOST_CHECK(!strcmp(buffer, "12.42")); @@ -102,9 +100,8 @@ BOOST_AUTO_TEST_CASE(TestPutGuidToString) { char buffer[1024]; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen); ignite::Guid guid(0x1da1ef8f39ff4d62ULL, 0x8b72e8e9f3371801ULL); @@ -118,9 +115,8 @@ BOOST_AUTO_TEST_CASE(TestPutBinaryToString) { char buffer[1024]; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen); uint8_t binary[] = { 0x21, 0x84, 0xF4, 0xDC, 0x01, 0x00, 0xFF, 0xF0 }; @@ -134,9 +130,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToString) { char buffer[1024]; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer), &reslen); std::string testString("Test string"); @@ -150,9 +145,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToWstring) { wchar_t buffer[1024]; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_WCHAR, buffer, sizeof(buffer), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_WCHAR, buffer, sizeof(buffer), &reslen); std::string testString("Test string"); @@ -164,9 +158,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToLong) { long numBuf; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, sizeof(numBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, sizeof(numBuf), &reslen); appBuf.PutString("424242424"); BOOST_CHECK(numBuf == 424242424L); @@ -179,9 +172,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToTiny) { int8_t numBuf; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_TINYINT, &numBuf, sizeof(numBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_TINYINT, &numBuf, sizeof(numBuf), &reslen); appBuf.PutString("12"); BOOST_CHECK(numBuf == 12); @@ -194,9 +186,8 @@ BOOST_AUTO_TEST_CASE(TestPutStringToFloat) { float numBuf; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, sizeof(numBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, sizeof(numBuf), &reslen); appBuf.PutString("12.21"); BOOST_CHECK_CLOSE_FRACTION(numBuf, 12.21, FLOAT_PRECISION); @@ -209,9 +200,8 @@ BOOST_AUTO_TEST_CASE(TestPutIntToFloat) { float numBuf; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, sizeof(numBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &numBuf, sizeof(numBuf), &reslen); appBuf.PutInt8(5); BOOST_CHECK_CLOSE_FRACTION(numBuf, 5.0, FLOAT_PRECISION); @@ -236,9 +226,8 @@ BOOST_AUTO_TEST_CASE(TestPutFloatToShort) { short numBuf; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_SHORT, &numBuf, sizeof(numBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_SHORT, &numBuf, sizeof(numBuf), &reslen); appBuf.PutDouble(5.42); BOOST_CHECK(numBuf == 5); @@ -258,7 +247,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToDouble) double numBuf; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, sizeof(numBuf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, sizeof(numBuf), &reslen); common::Decimal decimal; @@ -287,7 +276,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToLong) long numBuf; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, sizeof(numBuf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, sizeof(numBuf), &reslen); common::Decimal decimal; @@ -314,7 +303,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToString) char strBuf[64]; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); common::Decimal decimal; @@ -341,7 +330,7 @@ BOOST_AUTO_TEST_CASE(TestPutDecimalToNumeric) SQL_NUMERIC_STRUCT buf; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_NUMERIC, &buf, sizeof(buf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_NUMERIC, &buf, sizeof(buf), &reslen); common::Decimal decimal; @@ -392,7 +381,7 @@ BOOST_AUTO_TEST_CASE(TestPutDateToString) char strBuf[64] = { 0 }; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); Date date = common::MakeDateGmt(1999, 2, 22); @@ -406,10 +395,7 @@ BOOST_AUTO_TEST_CASE(TestPutDateToDate) SQL_DATE_STRUCT buf = { 0 }; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen); Date date = common::MakeDateGmt(1984, 5, 27); @@ -426,10 +412,7 @@ BOOST_AUTO_TEST_CASE(TestPutDateToTimestamp) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen); Date date = common::MakeDateGmt(1984, 5, 27); @@ -449,7 +432,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimeToString) char strBuf[64] = { 0 }; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); Time time = common::MakeTimeGmt(7, 15, 0); @@ -463,10 +446,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimeToTime) SQL_TIME_STRUCT buf = { 0 }; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), &reslen); Time time = common::MakeTimeGmt(23, 51, 1); @@ -482,7 +462,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToString) char strBuf[64] = { 0 }; SqlLen reslen = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); Timestamp date = common::MakeTimestampGmt(2018, 11, 1, 17, 45, 59); @@ -496,10 +476,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToDate) SQL_DATE_STRUCT buf = { 0 }; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen); Timestamp ts = common::MakeTimestampGmt(2004, 8, 14, 6, 34, 51, 573948623); @@ -515,10 +492,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToTime) SQL_TIME_STRUCT buf = { 0 }; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), &reslen); Timestamp ts = common::MakeTimestampGmt(2004, 8, 14, 6, 34, 51, 573948623); @@ -534,10 +508,7 @@ BOOST_AUTO_TEST_CASE(TestPutTimestampToTimestamp) SQL_TIMESTAMP_STRUCT buf = { 0 }; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen); Timestamp ts = common::MakeTimestampGmt(2004, 8, 14, 6, 34, 51, 573948623); @@ -557,7 +528,7 @@ BOOST_AUTO_TEST_CASE(TestGetGuidFromString) char buffer[] = "1da1ef8f-39ff-4d62-8b72-e8e9f3371801"; SqlLen reslen = sizeof(buffer) - 1; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer) - 1, &reslen, 0); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, buffer, sizeof(buffer) - 1, &reslen); ignite::Guid guid = appBuf.GetGuid(); @@ -568,9 +539,8 @@ BOOST_AUTO_TEST_CASE(TestGetStringFromLong) { long numBuf = 42; SqlLen reslen = sizeof(numBuf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_SIGNED_LONG, &numBuf, reslen, &reslen); std::string res = appBuf.GetString(32); @@ -587,9 +557,8 @@ BOOST_AUTO_TEST_CASE(TestGetStringFromDouble) { double numBuf = 43.36; SqlLen reslen = sizeof(numBuf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &numBuf, reslen, &reslen); std::string res = appBuf.GetString(32); @@ -606,9 +575,8 @@ BOOST_AUTO_TEST_CASE(TestGetStringFromString) { char buf[] = "Some data 32d2d5hs"; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, &reslen); std::string res = appBuf.GetString(reslen); @@ -619,9 +587,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromUshort) { unsigned short numBuf = 7162; SqlLen reslen = sizeof(numBuf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_SHORT, &numBuf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_SHORT, &numBuf, reslen, &reslen); float resFloat = appBuf.GetFloat(); @@ -636,9 +603,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromString) { char buf[] = "28.562"; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, &reslen); float resFloat = appBuf.GetFloat(); @@ -653,9 +619,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromFloat) { float buf = 207.49f; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, &reslen); float resFloat = appBuf.GetFloat(); @@ -670,9 +635,8 @@ BOOST_AUTO_TEST_CASE(TestGetFloatFromDouble) { double buf = 893.162; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, &reslen); float resFloat = appBuf.GetFloat(); @@ -687,9 +651,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromString) { char buf[] = "39"; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf, reslen, &reslen); int64_t resInt64 = appBuf.GetInt64(); @@ -712,9 +675,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromFloat) { float buf = -107.49f; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_FLOAT, &buf, reslen, &reslen); int64_t resInt64 = appBuf.GetInt64(); @@ -737,9 +699,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromDouble) { double buf = 42.97f; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_DOUBLE, &buf, reslen, &reslen); int64_t resInt64 = appBuf.GetInt64(); @@ -762,9 +723,8 @@ BOOST_AUTO_TEST_CASE(TestGetIntFromBigint) { uint64_t buf = 19; SqlLen reslen = sizeof(buf); - int* offset = 0; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, &buf, reslen, &reslen, &offset); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, &buf, reslen, &reslen); int64_t resInt64 = appBuf.GetInt64(); @@ -796,22 +756,19 @@ BOOST_AUTO_TEST_CASE(TestGetIntWithOffset) { 42, sizeof(uint64_t) } }; - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, &buf[0].val, sizeof(buf[0].val), &buf[0].reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_UNSIGNED_BIGINT, &buf[0].val, sizeof(buf[0].val), &buf[0].reslen); int64_t val = appBuf.GetInt64(); BOOST_CHECK(val == 12); - offset += sizeof(TestStruct); + appBuf.SetByteOffset(sizeof(TestStruct)); val = appBuf.GetInt64(); BOOST_CHECK(val == 42); - offsetPtr = 0; + appBuf.SetByteOffset(0); val = appBuf.GetInt64(); @@ -830,11 +787,8 @@ BOOST_AUTO_TEST_CASE(TestSetStringWithOffset) { "", 0 }, { "", 0 } }; - - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0].val, sizeof(buf[0].val), &buf[0].reslen, &offsetPtr); + + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0].val, sizeof(buf[0].val), &buf[0].reslen); appBuf.PutString("Hello Ignite!"); @@ -844,7 +798,7 @@ BOOST_AUTO_TEST_CASE(TestSetStringWithOffset) BOOST_CHECK(res == "Hello Ignite!"); BOOST_CHECK(res.size() == strlen("Hello Ignite!")); - offset += sizeof(TestStruct); + appBuf.SetByteOffset(sizeof(TestStruct)); appBuf.PutString("Hello with offset!"); @@ -865,11 +819,8 @@ BOOST_AUTO_TEST_CASE(TestGetDateFromString) { char buf[] = "1999-02-22"; SqlLen reslen = sizeof(buf); - - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], sizeof(buf), &reslen, &offsetPtr); + + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], sizeof(buf), &reslen); Date date = appBuf.GetDate(); @@ -892,10 +843,8 @@ BOOST_AUTO_TEST_CASE(TestGetTimeFromString) char buf[] = "17:5:59"; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], sizeof(buf), &reslen); Time time = appBuf.GetTime(); @@ -918,10 +867,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromString) char buf[] = "2018-11-01 17:45:59"; SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_CHAR, &buf[0], sizeof(buf), &reslen); Timestamp date = appBuf.GetTimestamp(); @@ -949,10 +895,7 @@ BOOST_AUTO_TEST_CASE(TestGetDateFromDate) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen); Date date = appBuf.GetDate(); @@ -980,10 +923,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromDate) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TDATE, &buf, sizeof(buf), &reslen); Timestamp ts = appBuf.GetTimestamp(); @@ -1011,10 +951,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromTime) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIME, &buf, sizeof(buf), &reslen); Time time = appBuf.GetTime(); @@ -1046,10 +983,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimestampFromTimestamp) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen); Timestamp ts = appBuf.GetTimestamp(); @@ -1082,10 +1016,7 @@ BOOST_AUTO_TEST_CASE(TestGetDateFromTimestamp) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen); Date date = appBuf.GetDate(); @@ -1117,10 +1048,7 @@ BOOST_AUTO_TEST_CASE(TestGetTimeFromTimestamp) SqlLen reslen = sizeof(buf); - int offset = 0; - int* offsetPtr = &offset; - - ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen, &offsetPtr); + ApplicationDataBuffer appBuf(OdbcNativeType::AI_TTIMESTAMP, &buf, sizeof(buf), &reslen); Time time = appBuf.GetTime(); http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/column_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/column_test.cpp b/modules/platforms/cpp/odbc-test/src/column_test.cpp index adc40c4..d6e8f57 100644 --- a/modules/platforms/cpp/odbc-test/src/column_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/column_test.cpp @@ -66,9 +66,8 @@ BOOST_AUTO_TEST_CASE(TestColumnShort) short shortBuf = 0; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_SIGNED_SHORT, &shortBuf, sizeof(shortBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_SIGNED_SHORT, &shortBuf, sizeof(shortBuf), &reslen); BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); @@ -114,9 +113,8 @@ BOOST_AUTO_TEST_CASE(TestColumnString) char strBuf[1024] = {}; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); @@ -164,9 +162,8 @@ BOOST_AUTO_TEST_CASE(TestColumnStringSeveral) std::string strBuf(data.size() / 3 + 2, 0); SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf[0], strBuf.size(), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf[0], strBuf.size(), &reslen); BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); @@ -246,9 +243,8 @@ BOOST_AUTO_TEST_CASE(TestColumnMultiString) char strBuf[1024] = {}; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); BOOST_REQUIRE(column1.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); @@ -312,9 +308,8 @@ BOOST_AUTO_TEST_CASE(TestColumnByteArray) std::vector<int8_t> buf(data.size()); SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf[0], buf.size(), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf[0], buf.size(), &reslen); BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); @@ -362,9 +357,8 @@ BOOST_AUTO_TEST_CASE(TestColumnByteArrayHalfBuffer) std::vector<int8_t> buf(data.size()/2); SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf[0], buf.size(), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf[0], buf.size(), &reslen); BOOST_REQUIRE(column.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); @@ -435,9 +429,8 @@ BOOST_AUTO_TEST_CASE(TestColumnByteArrayTwoColumns) int8_t buf[1024] = {}; SqlLen reslen = 0; - int* offset = 0; - ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf, sizeof(buf), &reslen, &offset); + ApplicationDataBuffer appBuf(type_traits::OdbcNativeType::AI_BINARY, &buf, sizeof(buf), &reslen); BOOST_REQUIRE(column1.ReadToBuffer(reader, appBuf) == SqlResult::AI_SUCCESS); http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/queries_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp index 282c6cb..41bc1fc 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -33,6 +33,7 @@ #include <boost/test/unit_test.hpp> #include "ignite/ignite.h" +#include "ignite/common/fixed_size_array.h" #include "ignite/ignition.h" #include "ignite/impl/binary/binary_utils.h" #include "ignite/binary/binary_object.h" @@ -310,10 +311,10 @@ struct QueriesTestSuiteFixture } /** - * Insert requested number of TestType vlaues with all defaults except + * Insert requested number of TestType values with all defaults except * for the strFields, which are generated using getTestString(). * - * @param num Number of records to insert. + * @param recordsNum Number of records to insert. * @param merge Set to true to use merge instead. */ void InsertTestStrings(int recordsNum, bool merge = false) @@ -371,6 +372,335 @@ struct QueriesTestSuiteFixture BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); } + /** + * Insert requested number of TestType values in a batch. + * + * @param from Index to start from. + * @param to Index to stop. + * @param expectedToAffect Expected number of affected records. + * @param merge Set to true to use merge instead of insert. + * @return Records inserted. + */ + int InsertTestBatch(int from, int to, int expectedToAffect, bool merge = false) + { + SQLCHAR insertReq[] = "INSERT " + "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, " + "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + SQLCHAR mergeReq[] = "MERGE " + "INTO TestType(_key, i8Field, i16Field, i32Field, strField, floatField, doubleField, boolField, dateField, " + "timeField, timestampField, i8ArrayField) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + SQLRETURN ret; + + int recordsNum = to - from; + + ret = SQLPrepare(stmt, merge ? mergeReq : insertReq, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + FixedSizeArray<int64_t> keys(recordsNum); + FixedSizeArray<int8_t> i8Fields(recordsNum); + FixedSizeArray<int16_t> i16Fields(recordsNum); + FixedSizeArray<int32_t> i32Fields(recordsNum); + FixedSizeArray<char> strFields(recordsNum * 1024); + FixedSizeArray<float> floatFields(recordsNum); + FixedSizeArray<double> doubleFields(recordsNum); + FixedSizeArray<bool> boolFields(recordsNum); + FixedSizeArray<SQL_DATE_STRUCT> dateFields(recordsNum); + FixedSizeArray<SQL_TIME_STRUCT> timeFields(recordsNum); + FixedSizeArray<SQL_TIMESTAMP_STRUCT> timestampFields(recordsNum); + FixedSizeArray<int8_t> i8ArrayFields(recordsNum * 42); + + FixedSizeArray<SQLLEN> strFieldsLen(recordsNum); + FixedSizeArray<SQLLEN> i8ArrayFieldsLen(recordsNum); + + BOOST_CHECKPOINT("Filling param data"); + + for (int i = 0; i < recordsNum; ++i) + { + int seed = from + i; + + keys[i] = seed; + i8Fields[i] = seed * 8; + i16Fields[i] = seed * 16; + i32Fields[i] = seed * 32; + + std::string val = getTestString(seed); + strncpy(strFields.GetData() + 1024 * i, val.c_str(), 1023); + strFieldsLen[i] = val.size(); + + floatFields[i] = seed * 0.5f; + doubleFields[i] = seed * 0.25f; + boolFields[i] = seed % 2 == 0; + + dateFields[i].year = 2017 + seed / 365; + dateFields[i].month = ((seed / 28) % 12) + 1; + dateFields[i].day = (seed % 28) + 1; + + timeFields[i].hour = (seed / 3600) % 24; + timeFields[i].minute = (seed / 60) % 60; + timeFields[i].second = seed % 60; + + timestampFields[i].year = dateFields[i].year; + timestampFields[i].month = dateFields[i].month; + timestampFields[i].day = dateFields[i].day; + timestampFields[i].hour = timeFields[i].hour; + timestampFields[i].minute = timeFields[i].minute; + timestampFields[i].second = timeFields[i].second; + timestampFields[i].fraction = std::abs(seed * 914873) % 1000000000; + + for (int j = 0; j < 42; ++j) + i8ArrayFields[i * 42 + j] = seed * 42 + j; + i8ArrayFieldsLen[i] = 42; + } + + SQLULEN setsProcessed = 0; + + BOOST_CHECKPOINT("Setting processed pointer"); + ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMS_PROCESSED_PTR, &setsProcessed, SQL_IS_POINTER); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding keys"); + ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, 0, 0, keys.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i8Fields"); + ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_STINYINT, SQL_TINYINT, 0, 0, i8Fields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i16Fields"); + ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_SSHORT, SQL_SMALLINT, 0, 0, i16Fields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i32Fields"); + ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, i32Fields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding strFields"); + ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, 1024, 0, strFields.GetData(), 1024, strFieldsLen.GetData()); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding floatFields"); + ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, 0, 0, floatFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding doubleFields"); + ret = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, doubleFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding boolFields"); + ret = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, 0, 0, boolFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding dateFields"); + ret = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_DATE, SQL_DATE, 0, 0, dateFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding timeFields"); + ret = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_TIME, SQL_TIME, 0, 0, timeFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding timestampFields"); + ret = SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_TIMESTAMP, SQL_TIMESTAMP, 0, 0, timestampFields.GetData(), 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Binding i8ArrayFields"); + ret = SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, 42, 0, i8ArrayFields.GetData(), 42, i8ArrayFieldsLen.GetData()); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Setting paramset size"); + ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(recordsNum), 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Executing query"); + ret = SQLExecute(stmt); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLLEN affected = 0; + ret = SQLRowCount(stmt, &affected); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECK_EQUAL(affected, expectedToAffect); + + BOOST_CHECKPOINT("Getting next result set"); + ret = SQLMoreResults(stmt); + + if (ret != SQL_NO_DATA) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Resetting parameters."); + ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + BOOST_CHECKPOINT("Setting paramset size"); + ret = SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, reinterpret_cast<SQLPOINTER>(1), 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + return static_cast<int>(setsProcessed); + } + + void InsertBatchSelect(int recordsNum) + { + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache"); + + // Inserting values. + int inserted = InsertTestBatch(0, recordsNum, recordsNum); + + BOOST_REQUIRE_EQUAL(inserted, recordsNum); + + int64_t key = 0; + char strField[1024] = { 0 }; + SQLLEN strFieldLen = 0; + + // Binding columns. + SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // Binding columns. + ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // Just selecting everything to make sure everything is OK + SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY _key"; + + ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq)); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + int selectedRecordsNum = 0; + + ret = SQL_SUCCESS; + + while (ret == SQL_SUCCESS) + { + ret = SQLFetch(stmt); + + if (ret == SQL_NO_DATA) + break; + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + std::string expectedStr = getTestString(selectedRecordsNum); + int64_t expectedKey = selectedRecordsNum; + + BOOST_CHECK_EQUAL(key, expectedKey); + + BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr); + + ++selectedRecordsNum; + } + + BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum); + } + + void InsertNonFullBatchSelect(int recordsNum, int splitAt) + { + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache"); + + // Inserting values. + int inserted = InsertTestBatch(splitAt, recordsNum, recordsNum - splitAt); + + BOOST_REQUIRE_EQUAL(inserted, recordsNum - splitAt); + + inserted = InsertTestBatch(0, recordsNum, splitAt); + + BOOST_REQUIRE_EQUAL(inserted, splitAt); + + int64_t key = 0; + char strField[1024] = { 0 }; + SQLLEN strFieldLen = 0; + + // Binding columns. + SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_SLONG, &key, 0, 0); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // Binding columns. + ret = SQLBindCol(stmt, 2, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // Just selecting everything to make sure everything is OK + SQLCHAR selectReq[] = "SELECT _key, strField FROM TestType ORDER BY _key"; + + ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq)); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + int selectedRecordsNum = 0; + + ret = SQL_SUCCESS; + + while (ret == SQL_SUCCESS) + { + ret = SQLFetch(stmt); + + if (ret == SQL_NO_DATA) + break; + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + std::string expectedStr = getTestString(selectedRecordsNum); + int64_t expectedKey = selectedRecordsNum; + + BOOST_CHECK_EQUAL(key, expectedKey); + + BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expectedStr); + + ++selectedRecordsNum; + } + + BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum); + } + /** Node started during the test. */ Ignite grid; @@ -1303,6 +1633,76 @@ BOOST_AUTO_TEST_CASE(TestInsertMergeSelect) BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum); } +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2) +{ + InsertBatchSelect(2); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect100) +{ + InsertBatchSelect(100); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1000) +{ + InsertBatchSelect(1000); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1023) +{ + InsertBatchSelect(1024); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1024) +{ + InsertBatchSelect(1024); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect1025) +{ + InsertBatchSelect(1025); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2000) +{ + InsertBatchSelect(2000); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2047) +{ + InsertBatchSelect(2048); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2048) +{ + InsertBatchSelect(2048); +} + +BOOST_AUTO_TEST_CASE(TestInsertBatchSelect2049) +{ + InsertBatchSelect(2049); +} + +BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect900) +{ + InsertNonFullBatchSelect(900, 42); +} + +BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect1500) +{ + InsertNonFullBatchSelect(1500, 100); +} + +BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect4500) +{ + InsertNonFullBatchSelect(4500, 1500); +} + +BOOST_AUTO_TEST_CASE(TestNotFullInsertBatchSelect4096) +{ + InsertNonFullBatchSelect(4096, 1024); +} + template<size_t n, size_t k> void CheckMeta(char columns[n][k], SQLLEN columnsLen[n]) { http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/row_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/row_test.cpp b/modules/platforms/cpp/odbc-test/src/row_test.cpp index c692291..08fadd1 100644 --- a/modules/platforms/cpp/odbc-test/src/row_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/row_test.cpp @@ -82,12 +82,11 @@ void CheckRowData(Row& row, size_t rowIdx) char strBuf[1024]; SQLGUID guidBuf; char bitBuf; - int* offset = 0; - ApplicationDataBuffer appLongBuf(type_traits::OdbcNativeType::AI_SIGNED_LONG, &longBuf, sizeof(longBuf), &reslen, &offset); - ApplicationDataBuffer appStrBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen, &offset); - ApplicationDataBuffer appGuidBuf(type_traits::OdbcNativeType::AI_GUID, &guidBuf, sizeof(guidBuf), &reslen, &offset); - ApplicationDataBuffer appBitBuf(type_traits::OdbcNativeType::AI_BIT, &bitBuf, sizeof(bitBuf), &reslen, &offset); + ApplicationDataBuffer appLongBuf(type_traits::OdbcNativeType::AI_SIGNED_LONG, &longBuf, sizeof(longBuf), &reslen); + ApplicationDataBuffer appStrBuf(type_traits::OdbcNativeType::AI_CHAR, &strBuf, sizeof(strBuf), &reslen); + ApplicationDataBuffer appGuidBuf(type_traits::OdbcNativeType::AI_GUID, &guidBuf, sizeof(guidBuf), &reslen); + ApplicationDataBuffer appBitBuf(type_traits::OdbcNativeType::AI_BIT, &bitBuf, sizeof(bitBuf), &reslen); // Checking size. BOOST_REQUIRE(row.GetSize() == 4); http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc-test/src/test_utils.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/test_utils.cpp b/modules/platforms/cpp/odbc-test/src/test_utils.cpp index 6fceb03..c7aa70a 100644 --- a/modules/platforms/cpp/odbc-test/src/test_utils.cpp +++ b/modules/platforms/cpp/odbc-test/src/test_utils.cpp @@ -50,6 +50,7 @@ namespace ignite_test cfg.jvmOpts.push_back("-DIGNITE_QUIET=false"); cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false"); cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false"); + cfg.jvmOpts.push_back("-Duser.language=en"); std::string home; bool homeFound = jni::ResolveIgniteHome("", home); http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/Makefile.am b/modules/platforms/cpp/odbc/Makefile.am index de6f75a..8d7693c 100644 --- a/modules/platforms/cpp/odbc/Makefile.am +++ b/modules/platforms/cpp/odbc/Makefile.am @@ -52,6 +52,7 @@ libignite_odbc_la_SOURCES = \ os/linux/src/system/socket_client.cpp \ src/app/application_data_buffer.cpp \ src/app/parameter.cpp \ + src/app/parameter_set.cpp \ src/common_types.cpp \ src/config/configuration.cpp \ src/config/connection_info.cpp \ @@ -68,6 +69,7 @@ libignite_odbc_la_SOURCES = \ src/dsn_config.cpp \ src/query/column_metadata_query.cpp \ src/query/data_query.cpp \ + src/query/batch_query.cpp \ src/query/foreign_keys_query.cpp \ src/query/primary_keys_query.cpp \ src/query/table_metadata_query.cpp \ @@ -76,6 +78,7 @@ libignite_odbc_la_SOURCES = \ src/protocol_version.cpp \ src/result_page.cpp \ src/row.cpp \ + src/message.cpp \ src/column.cpp \ src/statement.cpp \ src/type_traits.cpp \ http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/Makefile.am b/modules/platforms/cpp/odbc/include/Makefile.am index 36d8e25..92c85c5 100644 --- a/modules/platforms/cpp/odbc/include/Makefile.am +++ b/modules/platforms/cpp/odbc/include/Makefile.am @@ -22,6 +22,7 @@ noinst_HEADERS = \ ignite/odbc/query/table_metadata_query.h \ ignite/odbc/query/special_columns_query.h \ ignite/odbc/query/type_info_query.h \ + ignite/odbc/query/batch_query.h \ ignite/odbc/query/data_query.h \ ignite/odbc/query/foreign_keys_query.h \ ignite/odbc/query/column_metadata_query.h \ @@ -35,6 +36,7 @@ noinst_HEADERS = \ ignite/odbc/parser.h \ ignite/odbc/app/application_data_buffer.h \ ignite/odbc/app/parameter.h \ + ignite/odbc/app/parameter_set.h \ ignite/odbc/row.h \ ignite/odbc/utility.h \ ignite/odbc/environment.h \ http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h b/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h index 24461c2..abce85c 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/application_data_buffer.h @@ -55,10 +55,9 @@ namespace ignite * @param buffer Data buffer pointer. * @param buflen Data buffer length. * @param reslen Resulting data length. - * @param offset Pointer to buffer and reslen offset pointer. */ ApplicationDataBuffer(type_traits::OdbcNativeType::Type type, void* buffer, - SqlLen buflen, SqlLen* reslen, int** offset = 0); + SqlLen buflen, SqlLen* reslen); /** * Copy constructor. @@ -81,13 +80,23 @@ namespace ignite ApplicationDataBuffer& operator=(const ApplicationDataBuffer& other); /** - * Set pointer to offset pointer. + * Set offset in bytes for all bound pointers. * - * @param offset Pointer to offset pointer. + * @param offset Offset. */ - void SetPtrToOffsetPtr(int** offset) + void SetByteOffset(int offset) { - this->offset = offset; + this->byteOffset = offset; + } + + /** + * Set offset in elements for all bound pointers. + * + * @param + */ + void SetElementOffset(SqlUlen idx) + { + this->elementOffset = idx; } /** @@ -329,6 +338,13 @@ namespace ignite SqlLen GetDataAtExecSize() const; /** + * Get single element size. + * + * @return Size of the single element. + */ + SqlLen GetElementSize() const; + + /** * Get size of the input buffer. * * @return Input buffer size, or zero if the data is going @@ -407,10 +423,11 @@ namespace ignite * Apply buffer offset to pointer. * Adds offset to pointer if offset pointer is not null. * @param ptr Pointer. + * @param elemSize Element size. * @return Pointer with applied offset. */ template<typename T> - T* ApplyOffset(T* ptr) const; + T* ApplyOffset(T* ptr, size_t elemSize) const; /** Underlying data type. */ type_traits::OdbcNativeType::Type type; @@ -424,8 +441,11 @@ namespace ignite /** Result length. */ SqlLen* reslen; - /** Pointer to implementation pointer to application offset */ - int** offset; + /** Current byte offset */ + int byteOffset; + + /** Current element offset. */ + SqlUlen elementOffset; }; /** Column binging map type alias. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h index 1cf85b5..cdaaead 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter.h @@ -22,12 +22,10 @@ #include <map> -#include <ignite/guid.h> #include <ignite/impl/binary/binary_writer_impl.h> #include <ignite/impl/binary/binary_reader_impl.h> #include "ignite/odbc/app/application_data_buffer.h" -#include "ignite/odbc/type_traits.h" namespace ignite { @@ -70,7 +68,7 @@ namespace ignite ~Parameter(); /** - * Copy assigment operator. + * Assignment operator. * * @param other Other instance. * @return This. @@ -78,10 +76,12 @@ namespace ignite Parameter& operator=(const Parameter& other); /** - * Write request using provided writer. + * Write parameter using provided writer. * @param writer Writer. + * @param offset Offset for the buffer. + * @param idx Index for the array-of-parameters case. */ - void Write(impl::binary::BinaryWriterImpl& writer) const; + void Write(impl::binary::BinaryWriterImpl& writer, int offset = 0, SqlUlen idx = 0) const; /** * Get data buffer. @@ -91,6 +91,13 @@ namespace ignite ApplicationDataBuffer& GetBuffer(); /** + * Get data buffer. + * + * @return underlying ApplicationDataBuffer instance. + */ + const ApplicationDataBuffer& GetBuffer() const; + + /** * Reset stored at-execution data. */ void ResetStoredData(); @@ -128,9 +135,6 @@ namespace ignite /** Stored at-execution data. */ std::vector<int8_t> storedData; }; - - /** Parameter binging map type alias. */ - typedef std::map<uint16_t, Parameter> ParameterBindingMap; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h new file mode 100644 index 0000000..2ab5580 --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/app/parameter_set.h @@ -0,0 +1,268 @@ +/* + * 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. + */ + +#ifndef _IGNITE_ODBC_APP_PARAMETER_SET +#define _IGNITE_ODBC_APP_PARAMETER_SET + +#include <stdint.h> + +#include <map> + +#include <ignite/impl/binary/binary_writer_impl.h> +#include <ignite/impl/binary/binary_reader_impl.h> + +#include "ignite/odbc/app/parameter.h" + +namespace ignite +{ + namespace odbc + { + namespace app + { + /** + * Parameter set. + */ + class ParameterSet + { + /** Parameter binging map type alias. */ + typedef std::map<uint16_t, Parameter> ParameterBindingMap; + + /** Parameter meta vector. */ + typedef std::vector<int8_t> ParameterTypeVector; + public: + /** + * Default constructor. + */ + ParameterSet(); + + /** + * Destructor. + */ + ~ParameterSet() + { + // No-op. + } + + /** + * Set parameters set size. + * + * @param size Size of the parameter set. + */ + void SetParamSetSize(SqlUlen size); + + /** + * Bind parameter. + * + * @param paramIdx Parameter index. + * @param param Parameter. + */ + void BindParameter(uint16_t paramIdx, const Parameter& param); + + /** + * Unbind specified parameter. + * + * @param paramIdx Parameter index. + */ + void UnbindParameter(uint16_t paramIdx); + + /** + * Unbind all parameters. + */ + void UnbindAll(); + + /** + * Get number of binded parameters. + * + * @return Number of binded parameters. + */ + uint16_t GetParametersNumber() const; + + /** + * Set parameter binding offset pointer. + * + * @param ptr Parameter binding offset pointer. + */ + void SetParamBindOffsetPtr(int* ptr); + + /** + * Get parameter binding offset pointer. + * + * @return Parameter binding offset pointer. + */ + int* GetParamBindOffsetPtr(); + + /** + * Prepare parameters set for statement execution. + */ + void Prepare(); + + /** + * Check if the data at-execution is needed. + * + * @return True if the data at execution is needed. + */ + bool IsDataAtExecNeeded() const; + + /** + * Update parameter types metadata. + * + * @param meta Types metadata. + */ + void UpdateParamsTypes(const ParameterTypeVector& meta); + + /** + * Get type id of the parameter. + * + * @param idx Parameter index. + * @param dflt Default value to return if the type can not be found. + * @return Type ID of the parameter or dflt, if the type can not be returned. + */ + int8_t GetParamType(int16_t idx, int8_t dflt); + + /** + * Get expected parameters number. + * Using metadata. If metadata was not updated returns zero. + * + * @return Expected parameters number. + */ + uint16_t GetExpectedParamNum(); + + /** + * Check if the metadata was set for the parameter set. + * + * @return True if the metadata was set for the parameter set. + */ + bool IsMetadataSet() const; + + /** + * Check if the parameter selected for putting data at-execution. + * + * @return True if the parameter selected for putting data at-execution. + */ + bool IsParameterSelected() const; + + /** + * Get parameter by index. + * + * @param idx Index. + * @return Parameter or null, if parameter is not bound. + */ + Parameter* GetParameter(uint16_t idx); + + /** + * Get selected parameter. + * + * @return Parameter or null, if parameter is not bound. + */ + Parameter* GetSelectedParameter(); + + /** + * Internally selects next parameter for putting data at-execution. + * + * @return Parameter if found and null otherwise. + */ + Parameter* SelectNextParameter(); + + /** + * Write only first row of the param set using provided writer. + * @param writer Writer. + */ + void Write(impl::binary::BinaryWriterImpl& writer) const; + + /** + * Write rows of the param set in interval [begin, end) using provided writer. + * @param writer Writer. + * @param begin Beginng of the interval. + * @param end End of the interval. + * @param last Last page flag. + */ + void Write(impl::binary::BinaryWriterImpl& writer, SqlUlen begin, SqlUlen end, bool last) const; + + /** + * Calculate row length. + * + * @return Row length. + */ + int32_t CalculateRowLen() const; + + /** + * Get parameter set size. + * + * @return Number of rows in set. + */ + int32_t GetParamSetSize() const; + + /** + * Set number of parameters processed in batch. + * + * @param processed Processed. + */ + void SetParamsProcessed(SqlUlen processed) const; + + /** + * Number of processed params should be written using provided address. + * + * @param ptr Pointer. + */ + void SetParamsProcessedPtr(SqlUlen* ptr); + + /** + * Get pointer to write number of parameters processed in batch. + * + * @return Pointer to write number of parameters processed in batch. + */ + SqlUlen* GetParamsProcessedPtr(); + + private: + /** + * Write single row of the param set using provided writer. + * @param writer Writer. + * @param idx Row index. + */ + void WriteRow(impl::binary::BinaryWriterImpl& writer, SqlUlen idx) const; + + IGNITE_NO_COPY_ASSIGNMENT(ParameterSet); + + /** Parameters. */ + ParameterBindingMap parameters; + + /** Parameter types. */ + ParameterTypeVector paramTypes; + + /** Offset added to pointers to change binding of parameters. */ + int* paramBindOffset; + + /** Processed parameters. */ + SqlUlen* processedParamRows; + + /** Parameter set size. */ + SqlUlen paramSetSize; + + /** Current position in parametor set. */ + SqlUlen paramSetPos; + + /** Index of the parameter, which is currently being set. */ + uint16_t currentParamIdx; + + /** Parameter types are set. */ + bool typesSet; + }; + } + } +} + +#endif //_IGNITE_ODBC_APP_PARAMETER_SET http://git-wip-us.apache.org/repos/asf/ignite/blob/c10be578/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h index 4eb1a38..2ec1b5b 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h @@ -45,14 +45,14 @@ namespace ignite * * @return Diagnostic record. */ - virtual const diagnostic::DiagnosticRecordStorage& GetDiagnosticRecords() const = 0; + virtual const DiagnosticRecordStorage& GetDiagnosticRecords() const = 0; /** * Get diagnostic record. * * @return Diagnostic record. */ - virtual diagnostic::DiagnosticRecordStorage& GetDiagnosticRecords() = 0; + virtual DiagnosticRecordStorage& GetDiagnosticRecords() = 0; /** * Add new status record.
