You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/11/23 15:07:14 UTC
ignite git commit: IGNITE-4016: ODBC: Example now uses DML. This
closes #1265.
Repository: ignite
Updated Branches:
refs/heads/ignite-1.8 f4524a6a7 -> 83363d8e0
IGNITE-4016: ODBC: Example now uses DML. This closes #1265.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/83363d8e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/83363d8e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/83363d8e
Branch: refs/heads/ignite-1.8
Commit: 83363d8e0cab93b62f674ce0215082364881254b
Parents: f4524a6
Author: isapego <ig...@gmail.com>
Authored: Wed Nov 23 18:07:06 2016 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Wed Nov 23 18:07:06 2016 +0300
----------------------------------------------------------------------
.../odbc-example/config/example-odbc.xml | 30 +-
.../project/vs/odbc-example.vcxproj | 7 +-
.../project/vs/odbc-example.vcxproj.filters | 8 +
.../examples/odbc-example/src/odbc_example.cpp | 514 ++++++++++++++++---
4 files changed, 466 insertions(+), 93 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/83363d8e/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml b/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
index db4c390..864f950 100644
--- a/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
+++ b/modules/platforms/cpp/examples/odbc-example/config/example-odbc.xml
@@ -39,26 +39,30 @@
<property name="cacheMode" value="PARTITIONED"/>
<property name="atomicityMode" value="TRANSACTIONAL"/>
<property name="writeSynchronizationMode" value="FULL_SYNC"/>
-
- <!-- Configure type metadata to enable queries. -->
- <property name="typeMetadata">
+
+ <property name="queryEntities">
<list>
- <bean class="org.apache.ignite.cache.CacheTypeMetadata">
+ <bean class="org.apache.ignite.cache.QueryEntity">
<property name="keyType" value="java.lang.Long"/>
<property name="valueType" value="Person"/>
- <property name="ascendingFields">
+
+ <property name="fields">
<map>
<entry key="orgId" value="java.lang.Long"/>
- </map>
- </property>
- <property name="queryFields">
- <map>
<entry key="firstName" value="java.lang.String"/>
<entry key="lastName" value="java.lang.String"/>
<entry key="resume" value="java.lang.String"/>
<entry key="salary" value="java.lang.Double"/>
</map>
</property>
+
+ <property name="indexes">
+ <list>
+ <bean class="org.apache.ignite.cache.QueryIndex">
+ <constructor-arg value="orgId"/>
+ </bean>
+ </list>
+ </property>
</bean>
</list>
</property>
@@ -70,13 +74,13 @@
<property name="atomicityMode" value="TRANSACTIONAL"/>
<property name="writeSynchronizationMode" value="FULL_SYNC"/>
- <!-- Configure type metadata to enable queries. -->
- <property name="typeMetadata">
+ <property name="queryEntities">
<list>
- <bean class="org.apache.ignite.cache.CacheTypeMetadata">
+ <bean class="org.apache.ignite.cache.QueryEntity">
<property name="keyType" value="java.lang.Long"/>
<property name="valueType" value="Organization"/>
- <property name="ascendingFields">
+
+ <property name="fields">
<map>
<entry key="name" value="java.lang.String"/>
</map>
http://git-wip-us.apache.org/repos/asf/ignite/blob/83363d8e/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj b/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj
index e7bdd08..9f7cf3a 100644
--- a/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj
+++ b/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj
@@ -54,7 +54,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;..\..\..\include;..\..\..\..\common\os\win\include;..\..\..\..\common\include;..\..\..\..\jni\os\win\include;..\..\..\..\jni\include;..\..\..\..\binary\include;..\..\..\..\core\os\win\include;..\..\..\..\core\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
@@ -78,7 +78,7 @@ copy "$(ProjectDir)..\..\..\..\project\vs\$(Platform)\$(Configuration)\ignite.co
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;..\..\..\include;..\..\..\..\common\os\win\include;..\..\..\..\common\include;..\..\..\..\jni\os\win\include;..\..\..\..\jni\include;..\..\..\..\binary\include;..\..\..\..\core\os\win\include;..\..\..\..\core\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
@@ -102,6 +102,9 @@ copy "$(ProjectDir)..\..\..\..\project\vs\$(Platform)\$(Configuration)\ignite.co
<ClInclude Include="..\..\..\include\ignite\examples\organization.h" />
<ClInclude Include="..\..\..\include\ignite\examples\person.h" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\config\example-odbc.xml" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
http://git-wip-us.apache.org/repos/asf/ignite/blob/83363d8e/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj.filters
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj.filters b/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj.filters
index 44fff7c..aa4427f 100644
--- a/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj.filters
+++ b/modules/platforms/cpp/examples/odbc-example/project/vs/odbc-example.vcxproj.filters
@@ -8,6 +8,9 @@
<Filter Include="Header Files">
<UniqueIdentifier>{6400d7ba-6390-4cdb-aa25-9525f8a71444}</UniqueIdentifier>
</Filter>
+ <Filter Include="Config">
+ <UniqueIdentifier>{d054b826-ae5e-4a0c-833f-ae0b975f57d8}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\odbc_example.cpp">
@@ -25,4 +28,9 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
+ <ItemGroup>
+ <None Include="..\..\config\example-odbc.xml">
+ <Filter>Config</Filter>
+ </None>
+ </ItemGroup>
</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/83363d8e/modules/platforms/cpp/examples/odbc-example/src/odbc_example.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/examples/odbc-example/src/odbc_example.cpp b/modules/platforms/cpp/examples/odbc-example/src/odbc_example.cpp
index 39648d2..38e7426 100644
--- a/modules/platforms/cpp/examples/odbc-example/src/odbc_example.cpp
+++ b/modules/platforms/cpp/examples/odbc-example/src/odbc_example.cpp
@@ -35,7 +35,6 @@
#include "ignite/examples/organization.h"
using namespace ignite;
-using namespace cache;
using namespace examples;
@@ -48,6 +47,16 @@ using namespace examples;
*
* After all pre-requirements are fulfilled just build project as described
* in README and run resulting file.
+ *
+ * Note, that all fields which used in queries must be listed in config file
+ * under queryEntities property of the caches. You can find config file in
+ * config directory: cpp/examples/odbc-example/config/example-odbc.xml
+ *
+ * In addition to all the fields listed under QueryEntity bean, each table
+ * have two special predefined fields: _key and _val, which represent links
+ * to whole key and value objects. In some queries _key column is used. Key
+ * in our case works like an ID for the row and it should always present in
+ * INSERT statements.
*/
/** Read buffer size. */
@@ -118,101 +127,424 @@ std::string GetOdbcErrorMessage(SQLSMALLINT handleType, SQLHANDLE handle)
}
/**
+ * Extract error from ODBC handle and throw it as IgniteError.
+ *
+ * @param handleType Type of the handle.
+ * @param handle Handle.
+ * @param msg Error message.
+ */
+void ThrowOdbcError(SQLSMALLINT handleType, SQLHANDLE handle, std::string msg)
+{
+ std::stringstream builder;
+
+ builder << msg << ": " << GetOdbcErrorMessage(handleType, handle);
+
+ std::string errorMsg = builder.str();
+
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, errorMsg.c_str());
+}
+
+/**
* Fetch cache data using ODBC interface.
*/
-void GetDataWithOdbc(const std::string& query)
+void GetDataWithOdbc(SQLHDBC dbc, const std::string& query)
{
- SQLHENV env;
+ SQLHSTMT stmt;
- // Allocate an environment handle
- SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
+ // Allocate a statement handle
+ SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
- // We want ODBC 3 support
- SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0);
+ std::vector<SQLCHAR> buf(query.begin(), query.end());
- SQLHDBC dbc;
+ SQLRETURN ret = SQLExecDirect(stmt, &buf[0], static_cast<SQLSMALLINT>(buf.size()));
- // Allocate a connection handle
- SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
+ if (SQL_SUCCEEDED(ret))
+ PrintOdbcResultSet(stmt);
+ else
+ std::cerr << "Failed to execute query: " << GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt) << std::endl;
- // Combining connect string
- std::string connectStr = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=Person;";
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+}
- SQLCHAR outstr[ODBC_BUFFER_SIZE];
- SQLSMALLINT outstrlen;
+/**
+ * Populate Person cache with sample data.
+ *
+ * @param dbc Database connection.
+ */
+void PopulatePerson(SQLHDBC dbc)
+{
+ SQLHSTMT stmt;
- // Connecting to ODBC server.
- SQLRETURN ret = SQLDriverConnect(dbc, NULL, reinterpret_cast<SQLCHAR*>(&connectStr[0]),
- static_cast<SQLSMALLINT>(connectStr.size()), outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
+ // Allocate a statement handle
+ SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to allocate statement handle");
+
+ try
{
- std::cerr << "Failed to connect: " << GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc) << std::endl;
+ SQLCHAR query[] =
+ "INSERT INTO Person (_key, orgId, firstName, lastName, resume, salary) "
+ "VALUES (?, ?, ?, ?, ?, ?)";
+
+ ret = SQLPrepare(stmt, query, static_cast<SQLSMALLINT>(sizeof(query)));
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to prepare query");
+
+ // Binding columns.
+
+ int64_t key = 0;
+ int64_t orgId = 0;
+ char firstName[1024] = { 0 };
+ SQLLEN firstNameLen = SQL_NTS;
+ char lastName[1024] = { 0 };
+ SQLLEN lastNameLen = SQL_NTS;
+ char resume[1024] = { 0 };
+ SQLLEN resumeLen = SQL_NTS;
+ double salary = 0.0;
+
+ ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &orgId, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
+ sizeof(firstName), sizeof(firstName), firstName, 0, &firstNameLen);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
+ sizeof(lastName), sizeof(lastName), lastName, 0, &lastNameLen);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR,
+ sizeof(resume), sizeof(resume), resume, 0, &resumeLen);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &salary, 0, 0);
- return;
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ // Filling cache.
+
+ key = 1;
+ orgId = 1;
+ strncpy(firstName, "John", sizeof(firstName));
+ strncpy(lastName, "Doe", sizeof(lastName));
+ strncpy(resume, "Master Degree.", sizeof(resume));
+ salary = 2200.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 1;
+ strncpy(firstName, "Jane", sizeof(firstName));
+ strncpy(lastName, "Doe", sizeof(lastName));
+ strncpy(resume, "Bachelor Degree.", sizeof(resume));
+ salary = 1300.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 2;
+ strncpy(firstName, "John", sizeof(firstName));
+ strncpy(lastName, "Smith", sizeof(lastName));
+ strncpy(resume, "Bachelor Degree.", sizeof(resume));
+ salary = 1700.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 2;
+ strncpy(firstName, "Jane", sizeof(firstName));
+ strncpy(lastName, "Smith", sizeof(lastName));
+ strncpy(resume, "Master Degree.", sizeof(resume));
+ salary = 2500.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 2;
+ strncpy(firstName, "John", sizeof(firstName));
+ strncpy(lastName, "Roe", sizeof(lastName));
+ strncpy(resume, "Bachelor Degree.", sizeof(resume));
+ salary = 1500.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 2;
+ strncpy(firstName, "Jane", sizeof(firstName));
+ strncpy(lastName, "Roe", sizeof(lastName));
+ strncpy(resume, "Bachelor Degree.", sizeof(resume));
+ salary = 1000.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 1;
+ strncpy(firstName, "Richard", sizeof(firstName));
+ strncpy(lastName, "Miles", sizeof(lastName));
+ strncpy(resume, "Master Degree.", sizeof(resume));
+ salary = 2400.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+
+ ret = SQLMoreResults(stmt);
+
+ if (ret != SQL_NO_DATA)
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "No more data expected");
+
+ ++key;
+ orgId = 2;
+ strncpy(firstName, "Mary", sizeof(firstName));
+ strncpy(lastName, "Major", sizeof(lastName));
+ strncpy(resume, "Bachelor Degree.", sizeof(resume));
+ salary = 900.0;
+
+ ret = SQLExecute(stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute prepared statement");
+ }
+ catch(...)
+ {
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+
+ // Re-throwing expection.
+ throw;
}
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+}
+
+/**
+ * Populate Organization cache with sample data.
+ *
+ * @param dbc Database connection.
+ */
+void PopulateOrganization(SQLHDBC dbc)
+{
SQLHSTMT stmt;
// Allocate a statement handle
- SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
+ SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
- std::vector<SQLCHAR> buf(query.begin(), query.end());
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to allocate statement handle");
- ret = SQLExecDirect(stmt, &buf[0], static_cast<SQLSMALLINT>(buf.size()));
+ try
+ {
+ SQLCHAR query1[] = "INSERT INTO \"Organization\".Organization (_key, name) VALUES (1L, 'Microsoft')";
- if (SQL_SUCCEEDED(ret))
- PrintOdbcResultSet(stmt);
- else
- std::cerr << "Failed to execute query: " << GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt) << std::endl;
+ ret = SQLExecDirect(stmt, query1, static_cast<SQLSMALLINT>(sizeof(query1)));
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute query");
+
+ SQLFreeStmt(stmt, SQL_CLOSE);
+
+ SQLCHAR query2[] = "INSERT INTO \"Organization\".Organization (_key, name) VALUES (2L, 'Red Cross')";
+
+ ret = SQLExecDirect(stmt, query2, static_cast<SQLSMALLINT>(sizeof(query2)));
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute query");
+ }
+ catch (...)
+ {
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+
+ // Re-throwing expection.
+ throw;
+ }
// Releasing statement handle.
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+}
+
+/**
+ * Adjust salary for specified employee.
+ *
+ * @param dbc Database connection.
+ * @param key Person key.
+ * @param salary New salary.
+ */
+void AdjustSalary(SQLHDBC dbc, int64_t key, double salary)
+{
+ SQLHSTMT stmt;
+
+ // Allocate a statement handle
+ SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to allocate statement handle");
+
+ try
+ {
+ SQLCHAR query[] = "UPDATE Person SET salary=? WHERE _key=?";
+
+ ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, 0, 0, &salary, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLExecDirect(stmt, query, static_cast<SQLSMALLINT>(sizeof(query)));
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute query");
+ }
+ catch (...)
+ {
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
- // Disconneting from the server.
- SQLDisconnect(dbc);
+ // Re-throwing expection.
+ throw;
+ }
- // Releasing allocated handles.
- SQLFreeHandle(SQL_HANDLE_DBC, dbc);
- SQLFreeHandle(SQL_HANDLE_ENV, env);
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
/**
- * Populate Person cache with sample data.
- *
- * @param cache Cache instance.
+ * Remove specified person.
+ *
+ * @param dbc Database connection.
+ * @param key Person key.
*/
-void Populate(Cache<int64_t, Person>& cache)
+void DeletePerson(SQLHDBC dbc, int64_t key)
{
- std::map<int64_t, Person> persons;
-
- int64_t key = 0;
- persons[++key] = Person(1, "John", "Doe", "Master Degree.", 2200.0);
- persons[++key] = Person(1, "Jane", "Doe", "Bachelor Degree.", 1300.0);
- persons[++key] = Person(2, "John", "Smith", "Bachelor Degree.", 1700.0);
- persons[++key] = Person(2, "Jane", "Smith", "Master Degree.", 2500.0);
- persons[++key] = Person(2, "John", "Roe", "Bachelor Degree.", 1500.0);
- persons[++key] = Person(2, "Jane", "Roe", "Bachelor Degree.", 1000.0);
- persons[++key] = Person(1, "Richard", "Miles", "Master Degree.", 2400.0);
- persons[++key] = Person(2, "Mary", "Major", "Bachelor Degree.", 900.0);
-
- cache.PutAll(persons);
+ SQLHSTMT stmt;
+
+ // Allocate a statement handle
+ SQLRETURN ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to allocate statement handle");
+
+ try
+ {
+ SQLCHAR query[] = "DELETE FROM Person WHERE _key=?";
+
+ ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to bind parameter");
+
+ ret = SQLExecDirect(stmt, query, static_cast<SQLSMALLINT>(sizeof(query)));
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_STMT, stmt, "Failed to execute query");
+ }
+ catch (...)
+ {
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+
+ // Re-throwing expection.
+ throw;
+ }
+
+ // Releasing statement handle.
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt);
}
/**
- * Populate Organization cache with sample data.
+ * Query tables.
*
- * @param cache Cache instance.
+ * @param dbc Database connection.
*/
-void Populate(Cache<int64_t, Organization>& cache)
+void QueryData(SQLHDBC dbc)
{
- std::map<int64_t, Organization> orgs;
+ std::cout << std::endl;
+ std::cout << ">>> Getting list of persons:" << std::endl;
- int64_t key = 0;
- orgs[++key] = Organization("Microsoft", Address("1096 Eddy Street, San Francisco, CA", 94109));
- orgs[++key] = Organization("Red Cross", Address("184 Fidler Drive, San Antonio, TX", 78205));
+ GetDataWithOdbc(dbc, "SELECT firstName, lastName, resume, salary FROM Person");
+
+ std::cout << std::endl;
+ std::cout << ">>> Getting average salary by degree:" << std::endl;
+
+ GetDataWithOdbc(dbc, "SELECT resume, AVG(salary) FROM Person GROUP BY resume");
+
+ std::cout << std::endl;
+ std::cout << ">>> Getting people with organizations:" << std::endl;
- cache.PutAll(orgs);
+ GetDataWithOdbc(dbc, "SELECT firstName, lastName, Organization.name FROM Person "
+ "INNER JOIN \"Organization\".Organization ON Person.orgId = Organization._KEY");
}
/**
@@ -225,7 +557,7 @@ int main()
IgniteConfiguration cfg;
cfg.jvmInitMem = 512;
- cfg.jvmMaxMem = 512;
+ cfg.jvmMaxMem = 1024;
cfg.springCfgPath = "platforms/cpp/examples/odbc-example/config/example-odbc.xml";
@@ -234,39 +566,65 @@ int main()
// Start a node.
Ignite grid = Ignition::Start(cfg);
- std::cout << std::endl;
- std::cout << ">>> Cache ODBC example started." << std::endl;
- std::cout << std::endl;
+ SQLHENV env;
- // Get Person cache instance.
- Cache<int64_t, Person> personCache = grid.GetCache<int64_t, Person>("Person");
+ // Allocate an environment handle
+ SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
- // Get Organization cache instance.
- Cache<int64_t, Organization> orgCache = grid.GetCache<int64_t, Organization>("Organization");
+ // We want ODBC 3 support
+ SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0);
- // Clear caches.
- personCache.Clear();
- orgCache.Clear();
+ SQLHDBC dbc;
- // Populate caches.
- Populate(personCache);
- Populate(orgCache);
+ // Allocate a connection handle
+ SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
+
+ // Combining connect string
+ std::string connectStr = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=Person;";
+
+ SQLCHAR outstr[ODBC_BUFFER_SIZE];
+ SQLSMALLINT outstrlen;
+
+ // Connecting to ODBC server.
+ SQLRETURN ret = SQLDriverConnect(dbc, NULL, reinterpret_cast<SQLCHAR*>(&connectStr[0]),
+ static_cast<SQLSMALLINT>(connectStr.size()), outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
+
+ if (!SQL_SUCCEEDED(ret))
+ ThrowOdbcError(SQL_HANDLE_DBC, dbc, "Failed to connect");
std::cout << std::endl;
- std::cout << ">>> Getting list of persons:" << std::endl;
+ std::cout << ">>> Cache ODBC example started." << std::endl;
+ std::cout << std::endl;
+
+ // Populate caches.
+ PopulatePerson(dbc);
+ PopulateOrganization(dbc);
- GetDataWithOdbc("SELECT firstName, lastName, resume, salary FROM Person");
+ QueryData(dbc);
std::cout << std::endl;
- std::cout << ">>> Getting average salary by degree:" << std::endl;
+ std::cout << std::endl;
+ std::cout << ">>> Adjusted salary for Mary Major. Querying again." << std::endl;
+
+ AdjustSalary(dbc, 8, 1200.0);
- GetDataWithOdbc("SELECT resume, AVG(salary) FROM Person GROUP BY resume");
+ QueryData(dbc);
std::cout << std::endl;
- std::cout << ">>> Getting people with organizations:" << std::endl;
+ std::cout << std::endl;
+ std::cout << ">>> Removing several employees. Querying again." << std::endl;
+
+ DeletePerson(dbc, 4);
+ DeletePerson(dbc, 5);
+
+ QueryData(dbc);
+
+ // Disconneting from the server.
+ SQLDisconnect(dbc);
- GetDataWithOdbc("SELECT firstName, lastName, Organization.name FROM Person "
- "INNER JOIN \"Organization\".Organization ON Person.orgId = Organization._KEY");
+ // Releasing allocated handles.
+ SQLFreeHandle(SQL_HANDLE_DBC, dbc);
+ SQLFreeHandle(SQL_HANDLE_ENV, env);
// Stop node.
Ignition::StopAll(false);
@@ -277,7 +635,7 @@ int main()
}
std::cout << std::endl;
- std::cout << ">>> Example finished, press any key to exit ..." << std::endl;
+ std::cout << ">>> Example finished, press 'Enter' to exit ..." << std::endl;
std::cout << std::endl;
std::cin.get();