mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-29 00:06:58 -05:00
Add odbc-cpp-wrapper library to external folder
This commit is contained in:
parent
7f7bbae1d0
commit
d4494e5b43
@ -155,19 +155,6 @@ RUN curl -v -j -k -L -H "Cookie: eula_3_1_agreed=tools.hana.ondemand.com/develop
|
||||
&& rm -rf client \
|
||||
&& rm hanaclient*
|
||||
ENV PATH="/usr/sap/hdbclient:${PATH}"
|
||||
# Install cmake version 3.12 required by odbc-cpp-wrapper
|
||||
RUN curl -LJO https://cmake.org/files/v3.12/cmake-3.12.4-Linux-x86_64.tar.gz \
|
||||
&& tar -xvf cmake-3.12.4-Linux-x86_64.tar.gz && cp cmake-3.12.4-Linux-x86_64/bin/cmake /usr/local/bin \
|
||||
&& mkdir -p /usr/local/share/cmake-3.12 \
|
||||
&& cp -r cmake-3.12.4-Linux-x86_64/share/cmake-3.12/* /usr/local/share/cmake-3.12 \
|
||||
&& rm -rf cmake-3.12.4-Linux-x86_64*
|
||||
# Download and compile odbc-cpp-wrapper
|
||||
RUN git clone --branch v0.2 --depth 1 https://github.com/SAP/odbc-cpp-wrapper.git \
|
||||
&& mkdir odbc-cpp-wrapper/build \
|
||||
&& cd odbc-cpp-wrapper/build \
|
||||
&& cmake .. \
|
||||
&& make -j 2 \
|
||||
&& make install
|
||||
|
||||
# MSSQL: client side
|
||||
RUN curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
|
||||
|
||||
@ -240,10 +240,17 @@ if(WITH_CORE)
|
||||
set(ORACLE_LIBDIR "" CACHE STRING "Path to OCI libraries")
|
||||
endif()
|
||||
|
||||
SET (WITH_HANA FALSE CACHE BOOL "Determines whether SAP HANA Spatial support should be built")
|
||||
IF(WITH_HANA)
|
||||
SET(HAVE_HANA TRUE)
|
||||
ENDIF(WITH_HANA)
|
||||
set (WITH_HANA FALSE CACHE BOOL "Determines whether SAP HANA Spatial support should be built")
|
||||
if(WITH_HANA)
|
||||
find_package(ODBC)
|
||||
if(ODBC_FOUND)
|
||||
set(HAVE_HANA TRUE)
|
||||
add_subdirectory(external/odbccpp)
|
||||
set_target_properties(odbccpp odbccpp_static PROPERTIES AUTOMOC OFF AUTOUIC OFF AUTORCC OFF)
|
||||
else()
|
||||
message(STATUS "Couldn't find ODBC library")
|
||||
endif()
|
||||
endif(WITH_HANA)
|
||||
|
||||
set (WITH_PDAL FALSE CACHE BOOL "Determines whether PDAL support should be built")
|
||||
if(WITH_PDAL)
|
||||
|
||||
@ -1,48 +0,0 @@
|
||||
# Find odbc-cpp-wrapper
|
||||
# ~~~~~~~~~~~~~~~
|
||||
# CMake module to search for C++ Wrapper for ODBC from:
|
||||
# https://github.com/SAP/odbc-cpp-wrapper
|
||||
|
||||
FIND_PACKAGE(ODBC REQUIRED)
|
||||
|
||||
IF (NOT ODBCCPP_INCLUDE_DIR)
|
||||
FIND_PATH(ODBCCPP_INCLUDE_DIR odbc/Environment.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/usr/include
|
||||
c:/msys/local/include
|
||||
"$ENV{LIB_DIR}/include"
|
||||
$ENV{INCLUDE}
|
||||
"$ENV{ODBCCPP_PATH}/include"
|
||||
)
|
||||
ENDIF (NOT ODBCCPP_INCLUDE_DIR)
|
||||
|
||||
IF (NOT ODBCCPP_LIBRARY)
|
||||
FIND_LIBRARY(ODBCCPP_LIBRARY odbccpp_static
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
c:/msys/local/lib
|
||||
"$ENV{LIB_DIR}/lib"
|
||||
$ENV{LIB}
|
||||
"$ENV{ODBCCPP_PATH}/lib"
|
||||
)
|
||||
ENDIF (NOT ODBCCPP_LIBRARY)
|
||||
|
||||
IF (ODBCCPP_INCLUDE_DIR AND ODBCCPP_LIBRARY)
|
||||
SET(ODBCCPP_FOUND TRUE)
|
||||
ENDIF (ODBCCPP_INCLUDE_DIR AND ODBCCPP_LIBRARY)
|
||||
|
||||
IF (ODBCCPP_FOUND)
|
||||
IF (NOT ODBCCPP_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found odbc-cpp: ${ODBCCPP_LIBRARY}")
|
||||
ENDIF (NOT ODBCCPP_FIND_QUIETLY)
|
||||
ELSE (ODBCCPP_FOUND)
|
||||
IF (ODBCCPP_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find odbc-cpp library")
|
||||
ELSE (ODBCCPP_FIND_REQUIRED)
|
||||
IF (NOT ODBCCPP_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Could not find odbc-cpp library")
|
||||
ENDIF (NOT ODBCCPP_FIND_QUIETLY)
|
||||
ENDIF (ODBCCPP_FIND_REQUIRED)
|
||||
ENDIF (ODBCCPP_FOUND)
|
||||
10
external/odbccpp/CMakeLists.txt
vendored
Normal file
10
external/odbccpp/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
|
||||
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
PROJECT(odbccpp)
|
||||
|
||||
FIND_PACKAGE(ODBC REQUIRED)
|
||||
|
||||
ADD_SUBDIRECTORY(src)
|
||||
|
||||
212
external/odbccpp/LICENSE
vendored
Normal file
212
external/odbccpp/LICENSE
vendored
Normal file
@ -0,0 +1,212 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed 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.
|
||||
|
||||
--- Exceptions to the Apache 2.0 License ---
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision
|
||||
(Section 3), the indemnity provision (Section 9) or other Section of the
|
||||
License conflicts with the conditions of the GPLv2, you may retroactively
|
||||
and prospectively choose to deem waived or otherwise exclude such Section(s)
|
||||
of the License, but only in their entirety and only with respect to the
|
||||
Combined Software.
|
||||
1
external/odbccpp/NOTICE
vendored
Normal file
1
external/odbccpp/NOTICE
vendored
Normal file
@ -0,0 +1 @@
|
||||
Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
|
||||
191
external/odbccpp/README.md
vendored
Normal file
191
external/odbccpp/README.md
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
# C++ Wrapper for ODBC
|
||||
|
||||
odbc-cpp-wrapper is an object-oriented C++-wrapper of the ODBC API. It takes
|
||||
care of
|
||||
- managing the lifetime of ODBC resources,
|
||||
- allocating and managing resources needed for ODBC operations and
|
||||
- converting ODBC errors to exceptions and throwing them.
|
||||
|
||||
The odbc-cpp-wrapper API attempts to make usage of ODBC as simple as possible.
|
||||
The API was designed to make wrong usage almost impossible and to ensure proper
|
||||
object lifetime management.
|
||||
|
||||
odbc-cpp-wrapper was originally developed for exchanging spatial data with
|
||||
databases. It focuses on batch operations of variable-sized data, which is not
|
||||
very well supported by other ODBC wrappers.
|
||||
|
||||
## Requirements
|
||||
|
||||
To build odbc-cpp-wrapper you need
|
||||
- A C++-11-standard-compliant compiler
|
||||
- [The Git command line client](https://git-scm.com/)
|
||||
- [CMake 3.12 or newer](https://cmake.org/)
|
||||
|
||||
On Linux platforms you additionally need
|
||||
- [unixODBC](http://www.unixodbc.org/)
|
||||
|
||||
To generate the API's documentation, you need
|
||||
- [Doxygen 1.8.0 or later](http://www.doxygen.nl/)
|
||||
|
||||
|
||||
## Building and Installation
|
||||
|
||||
### Linux
|
||||
|
||||
- Clone the repository:
|
||||
```
|
||||
git clone https://github.com/SAP/odbc-cpp-wrapper.git
|
||||
```
|
||||
|
||||
- Create a build directory and change to it:
|
||||
```
|
||||
mkdir odbc-cpp-wrapper/build && cd odbc-cpp-wrapper/build
|
||||
```
|
||||
|
||||
- Create the makefiles with CMake:
|
||||
```
|
||||
cmake ..
|
||||
```
|
||||
|
||||
- Build the library:
|
||||
```
|
||||
make -j <number of parallel build jobs>
|
||||
```
|
||||
|
||||
The build will create a shared library `libodbccpp.so` and a static library `libodbccpp_static.a`.
|
||||
|
||||
- To build the documentation (optional):
|
||||
```
|
||||
make doc
|
||||
```
|
||||
|
||||
The mainpage of the documentation can be found at `doc/html/index.html`.
|
||||
|
||||
- Install the library:
|
||||
```
|
||||
sudo make install
|
||||
```
|
||||
|
||||
This will install the library and header files. CMake will install them to `usr/local/lib` and `usr/local/include` by default. If you prefer different locations, you can set CMake's install prefix to a different path. See
|
||||
https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html for details.
|
||||
|
||||
|
||||
### Windows
|
||||
|
||||
- Clone the repository:
|
||||
```
|
||||
git clone https://github.com/SAP/odbc-cpp-wrapper.git
|
||||
```
|
||||
|
||||
- Create a build directory and change to it:
|
||||
```
|
||||
mkdir odbc-cpp-wrapper\build && cd odbc-cpp-wrapper\build
|
||||
```
|
||||
|
||||
#### Visual Studio 2015 and later
|
||||
|
||||
- Generate a Visual Studio solution
|
||||
```
|
||||
cmake ..
|
||||
```
|
||||
|
||||
You can then open the `odbccpp.sln` file and build the desired targets in Visual Studio.
|
||||
|
||||
#### MSBuild (nmake)
|
||||
|
||||
- Start the Visual Studio Native Tools Command Prompt for the desired target and change the directory to the build directory. Create the makefiles for nmake:
|
||||
```
|
||||
cmake -G "NMake Makefiles" ..
|
||||
```
|
||||
|
||||
> Optionally you can use CMAKE_BUILD_TYPE to define if you'd like to build a Debug or Release build. See
|
||||
https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html for details.
|
||||
|
||||
- Build the library:
|
||||
```
|
||||
nmake
|
||||
```
|
||||
|
||||
The build will create a dynamic link library `odbccpp.dll` and a static library `odbccpp_static.lib`.
|
||||
|
||||
- Build the documentation (optional):
|
||||
```
|
||||
nmake doc
|
||||
```
|
||||
|
||||
The mainpage of the documentation can be found at `doc\html\index.html`.
|
||||
|
||||
- Install the library (optional):
|
||||
```
|
||||
nmake install
|
||||
```
|
||||
|
||||
This will install the library and header files. CMake will install them to `C:\Program Files\odbccpp` by default. If you prefer a different location, you can set CMake's install prefix to a different path. See
|
||||
https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html for details.
|
||||
|
||||
|
||||
## Using the library
|
||||
|
||||
You can just link against the shared/dynamic or the static library. If you are linking against the static library, you have to additionally define `ODBC_STATIC` when compiling.
|
||||
|
||||
Usage of the library should be pretty straight-forward if you are familiar with ODBC and/or other database connectors.
|
||||
|
||||
### Example
|
||||
|
||||
The following code gives an example how working with odbc-cpp-wrapper looks like. It connects to a database, batch inserts two rows and executes a query.
|
||||
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/Environment.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/PreparedStatement.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
odbc::EnvironmentRef env = odbc::Environment::create();
|
||||
|
||||
odbc::ConnectionRef conn = env->createConnection();
|
||||
conn->connect("DSN", "user", "pass");
|
||||
conn->setAutoCommit(false);
|
||||
|
||||
odbc::PreparedStatementRef psInsert =
|
||||
conn->prepareStatement("INSERT INTO TAB (ID, DATA) VALUES (?, ?)");
|
||||
psInsert->setInt(1, 101);
|
||||
psInsert->setCString(2, "One hundred one");
|
||||
psInsert->addBatch();
|
||||
psInsert->setInt(1, 102);
|
||||
psInsert->setCString(2, "One hundred two");
|
||||
psInsert->addBatch();
|
||||
psInsert->executeBatch();
|
||||
conn->commit();
|
||||
|
||||
odbc::PreparedStatementRef psSelect =
|
||||
conn->prepareStatement("SELECT ID, DATA FROM TAB WHERE ID > ?");
|
||||
psSelect->setInt(1, 100);
|
||||
odbc::ResultSetRef rs = psSelect->executeQuery();
|
||||
while (rs->next())
|
||||
{
|
||||
std::cout << rs->getInt(1) << ", " << rs->getString(2) << std::endl;
|
||||
}
|
||||
}
|
||||
catch (const odbc::Exception& e)
|
||||
{
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## How to obtain support
|
||||
|
||||
If you experience issues with using the library, please file a report in the GitHub bug tracking system.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
|
||||
|
||||
This file is licensed under the Apache Software License 2.0 except as noted otherwise in the [LICENSE](LICENSE) file.
|
||||
2
external/odbccpp/src/CMakeLists.txt
vendored
Normal file
2
external/odbccpp/src/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
ADD_SUBDIRECTORY(odbc)
|
||||
79
external/odbccpp/src/odbc/CMakeLists.txt
vendored
Normal file
79
external/odbccpp/src/odbc/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
# Public Header Files
|
||||
SET(public_headers
|
||||
Config.h
|
||||
Connection.h
|
||||
DatabaseMetaData.h
|
||||
DatabaseMetaDataBase.h
|
||||
DatabaseMetaDataUnicode.h
|
||||
Environment.h
|
||||
Exception.h
|
||||
Forwards.h
|
||||
ParameterMetaData.h
|
||||
PreparedStatement.h
|
||||
RefCounted.h
|
||||
ResultSet.h
|
||||
ResultSetMetaData.h
|
||||
ResultSetMetaDataBase.h
|
||||
ResultSetMetaDataUnicode.h
|
||||
Statement.h
|
||||
StatementBase.h
|
||||
Types.h
|
||||
Util.h
|
||||
)
|
||||
|
||||
# Sources
|
||||
SET(odbccpp_sources
|
||||
Connection.cpp
|
||||
DatabaseMetaData.cpp
|
||||
DatabaseMetaDataBase.cpp
|
||||
DatabaseMetaDataUnicode.cpp
|
||||
Environment.cpp
|
||||
Exception.cpp
|
||||
ParameterMetaData.cpp
|
||||
PreparedStatement.cpp
|
||||
RefCounted.cpp
|
||||
ResultSet.cpp
|
||||
ResultSetMetaData.cpp
|
||||
ResultSetMetaDataBase.cpp
|
||||
ResultSetMetaDataUnicode.cpp
|
||||
Statement.cpp
|
||||
StatementBase.cpp
|
||||
Types.cpp
|
||||
Util.cpp
|
||||
internal/Batch.cpp
|
||||
internal/ParameterData.cpp
|
||||
internal/UtilInternal.cpp
|
||||
)
|
||||
|
||||
# Static library
|
||||
ADD_LIBRARY(odbccpp_static
|
||||
STATIC
|
||||
${odbccpp_sources}
|
||||
)
|
||||
TARGET_COMPILE_DEFINITIONS(odbccpp_static
|
||||
PUBLIC
|
||||
ODBC_STATIC
|
||||
)
|
||||
SET_PROPERTY(TARGET odbccpp_static PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# Shared library
|
||||
ADD_LIBRARY(odbccpp
|
||||
SHARED
|
||||
${odbccpp_sources}
|
||||
)
|
||||
TARGET_COMPILE_DEFINITIONS(odbccpp
|
||||
PRIVATE
|
||||
ODBC_EXPORTS
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(odbccpp
|
||||
PUBLIC
|
||||
${ODBC_LIBRARIES}
|
||||
)
|
||||
|
||||
SET_PROPERTY(TARGET odbccpp PROPERTY public_headers ${public_headers})
|
||||
|
||||
# Installation
|
||||
INSTALL(TARGETS odbccpp_static DESTINATION lib)
|
||||
INSTALL(TARGETS odbccpp DESTINATION lib)
|
||||
INSTALL(FILES ${public_headers} DESTINATION include/odbc)
|
||||
24
external/odbccpp/src/odbc/Config.h
vendored
Normal file
24
external/odbccpp/src/odbc/Config.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef ODBC_CONFIG_H_INCLUDED
|
||||
#define ODBC_CONFIG_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef ODBC_EXPORT
|
||||
# ifdef ODBC_STATIC
|
||||
# define ODBC_EXPORT
|
||||
# else
|
||||
# if defined(__clang__) || defined(__GNUC__)
|
||||
# define ODBC_EXPORT __attribute__ ((visibility("default")))
|
||||
# elif defined(_MSC_VER)
|
||||
# ifdef ODBC_EXPORTS
|
||||
# define ODBC_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define ODBC_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
# pragma warning(disable: 4251 4275)
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
265
external/odbccpp/src/odbc/Connection.cpp
vendored
Normal file
265
external/odbccpp/src/odbc/Connection.cpp
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
#include <limits>
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/DatabaseMetaData.h>
|
||||
#include <odbc/DatabaseMetaDataUnicode.h>
|
||||
#include <odbc/Environment.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/PreparedStatement.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
Connection::Connection(Environment* parent)
|
||||
: parent_(parent, true)
|
||||
, hdbc_(SQL_NULL_HANDLE)
|
||||
, connected_(false)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Connection::~Connection()
|
||||
{
|
||||
if (connected_)
|
||||
SQLDisconnect(hdbc_);
|
||||
if (hdbc_)
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, hdbc_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setHandle(void* hdbc)
|
||||
{
|
||||
hdbc_ = hdbc;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::connect(const char* dsn, const char* user,
|
||||
const char* password)
|
||||
{
|
||||
EXEC_DBC(SQLConnectA, hdbc_,
|
||||
(SQLCHAR*)dsn, SQL_NTS,
|
||||
(SQLCHAR*)user, SQL_NTS,
|
||||
(SQLCHAR*)password, SQL_NTS);
|
||||
connected_ = true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::connect(const char* connString)
|
||||
{
|
||||
SQLCHAR outString[1024];
|
||||
SQLSMALLINT outLength;
|
||||
EXEC_DBC(SQLDriverConnectA, hdbc_, NULL,
|
||||
(SQLCHAR*)connString, SQL_NTS,
|
||||
outString, sizeof(outString),
|
||||
&outLength, SQL_DRIVER_NOPROMPT);
|
||||
connected_ = true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::disconnect()
|
||||
{
|
||||
SQLRETURN rc = SQLDisconnect(hdbc_);
|
||||
connected_ = false;
|
||||
Exception::checkForError(rc, SQL_HANDLE_DBC, hdbc_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool Connection::connected() const
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool Connection::isValid()
|
||||
{
|
||||
SQLULEN ret = 0;
|
||||
EXEC_DBC(SQLGetConnectAttr, hdbc_, SQL_ATTR_CONNECTION_DEAD, &ret, 0, NULL);
|
||||
return ret == SQL_CD_FALSE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned long Connection::getConnectionTimeout()
|
||||
{
|
||||
SQLULEN ret = 0;
|
||||
EXEC_DBC(SQLGetConnectAttr, hdbc_, SQL_ATTR_CONNECTION_TIMEOUT, &ret, 0,
|
||||
NULL);
|
||||
return (unsigned long)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setConnectionTimeout(unsigned long seconds)
|
||||
{
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, SQL_ATTR_CONNECTION_TIMEOUT,
|
||||
(SQLPOINTER)(ptrdiff_t)seconds, SQL_IS_UINTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned long Connection::getLoginTimeout()
|
||||
{
|
||||
SQLULEN ret = 0;
|
||||
EXEC_DBC(SQLGetConnectAttr, hdbc_, SQL_ATTR_LOGIN_TIMEOUT, &ret, 0, NULL);
|
||||
return (unsigned long)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setLoginTimeout(unsigned long seconds)
|
||||
{
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, SQL_ATTR_LOGIN_TIMEOUT,
|
||||
(SQLPOINTER)(ptrdiff_t)seconds, SQL_IS_UINTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setAttribute(int attr, int value)
|
||||
{
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, attr, (SQLPOINTER)(ptrdiff_t)value,
|
||||
SQL_IS_INTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setAttribute(int attr, unsigned int value)
|
||||
{
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, attr, (SQLPOINTER)(ptrdiff_t)value,
|
||||
SQL_IS_UINTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setAttribute(int attr, const char* value)
|
||||
{
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, attr, (SQLPOINTER)value, SQL_NTS);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setAttribute(int attr, const char* value, std::size_t size)
|
||||
{
|
||||
if (size > (size_t)numeric_limits<SQLINTEGER>::max())
|
||||
throw Exception("The attribute value is too long");
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, attr, (SQLPOINTER)value,
|
||||
(SQLINTEGER)size);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setAttribute(int attr, const void* value, std::size_t size)
|
||||
{
|
||||
if (size > (size_t)numeric_limits<SQLINTEGER>::max())
|
||||
throw Exception("The attribute value is too long");
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, attr, (SQLPOINTER)value,
|
||||
(SQLINTEGER)size);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool Connection::getAutoCommit() const
|
||||
{
|
||||
SQLULEN ret = 0;
|
||||
EXEC_DBC(SQLGetConnectAttr, hdbc_, SQL_ATTR_AUTOCOMMIT, &ret, 0, NULL);
|
||||
return ret == SQL_AUTOCOMMIT_ON;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setAutoCommit(bool autoCommit)
|
||||
{
|
||||
EXEC_DBC(SQLSetConnectAttr, hdbc_, SQL_ATTR_AUTOCOMMIT,
|
||||
autoCommit ?
|
||||
(SQLPOINTER)SQL_AUTOCOMMIT_ON: (SQLPOINTER)SQL_AUTOCOMMIT_OFF,
|
||||
SQL_IS_INTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::commit()
|
||||
{
|
||||
SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, hdbc_, SQL_COMMIT);
|
||||
Exception::checkForError(rc, SQL_HANDLE_DBC, hdbc_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::rollback()
|
||||
{
|
||||
SQLRETURN rc = SQLEndTran(SQL_HANDLE_DBC, hdbc_, SQL_ROLLBACK);
|
||||
Exception::checkForError(rc, SQL_HANDLE_DBC, hdbc_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool Connection::isReadOnly()
|
||||
{
|
||||
SQLULEN ret = 0;
|
||||
EXEC_DBC(SQLGetConnectAttr, hdbc_, SQL_ATTR_ACCESS_MODE, &ret, 0, NULL);
|
||||
return ret == SQL_MODE_READ_ONLY;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setReadOnly(bool readOnly)
|
||||
{
|
||||
unsigned int mode = readOnly ? SQL_MODE_READ_ONLY : SQL_MODE_READ_WRITE;
|
||||
setAttribute(SQL_ATTR_ACCESS_MODE, mode);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
TransactionIsolationLevel Connection::getTransactionIsolation()
|
||||
{
|
||||
SQLULEN txn = 0;
|
||||
EXEC_DBC(SQLGetConnectAttr, hdbc_, SQL_ATTR_TXN_ISOLATION, &txn, 0, NULL);
|
||||
|
||||
switch (txn)
|
||||
{
|
||||
case SQL_TXN_READ_COMMITTED:
|
||||
return TransactionIsolationLevel::READ_COMMITTED;
|
||||
case SQL_TXN_READ_UNCOMMITTED:
|
||||
return TransactionIsolationLevel::READ_UNCOMMITTED;
|
||||
case SQL_TXN_REPEATABLE_READ:
|
||||
return TransactionIsolationLevel::REPEATABLE_READ;
|
||||
case SQL_TXN_SERIALIZABLE:
|
||||
return TransactionIsolationLevel::SERIALIZABLE;
|
||||
case 0:
|
||||
return TransactionIsolationLevel::NONE;
|
||||
default:
|
||||
throw Exception("Unknown transaction isolation level.");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Connection::setTransactionIsolation(TransactionIsolationLevel level)
|
||||
{
|
||||
unsigned int txn = 0;
|
||||
switch (level)
|
||||
{
|
||||
case TransactionIsolationLevel::READ_COMMITTED:
|
||||
txn = SQL_TXN_READ_COMMITTED;
|
||||
break;
|
||||
case TransactionIsolationLevel::READ_UNCOMMITTED:
|
||||
txn = SQL_TXN_READ_UNCOMMITTED;
|
||||
break;
|
||||
case TransactionIsolationLevel::REPEATABLE_READ:
|
||||
txn = SQL_TXN_REPEATABLE_READ;
|
||||
break;
|
||||
case TransactionIsolationLevel::SERIALIZABLE:
|
||||
txn = SQL_TXN_SERIALIZABLE;
|
||||
break;
|
||||
case TransactionIsolationLevel::NONE:
|
||||
throw Exception("NONE transaction isolation level cannot be set.");
|
||||
}
|
||||
|
||||
setAttribute(SQL_ATTR_TXN_ISOLATION, txn);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
StatementRef Connection::createStatement()
|
||||
{
|
||||
SQLHANDLE hstmt;
|
||||
StatementRef ret(new Statement(this));
|
||||
SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc_, &hstmt);
|
||||
Exception::checkForError(rc, SQL_HANDLE_DBC, hdbc_);
|
||||
ret->setHandle(hstmt);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
PreparedStatementRef Connection::prepareStatement(const char* sql)
|
||||
{
|
||||
SQLHANDLE hstmt;
|
||||
PreparedStatementRef ret(new PreparedStatement(this));
|
||||
SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc_, &hstmt);
|
||||
Exception::checkForError(rc, SQL_HANDLE_DBC, hdbc_);
|
||||
ret->setHandleAndQuery(hstmt, sql);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
PreparedStatementRef Connection::prepareStatement(const char16_t* sql)
|
||||
{
|
||||
SQLHANDLE hstmt;
|
||||
PreparedStatementRef ret(new PreparedStatement(this));
|
||||
SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc_, &hstmt);
|
||||
Exception::checkForError(rc, SQL_HANDLE_DBC, hdbc_);
|
||||
ret->setHandleAndQuery(hstmt, sql);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
DatabaseMetaDataRef Connection::getDatabaseMetaData()
|
||||
{
|
||||
DatabaseMetaDataRef ret(new DatabaseMetaData(this));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
DatabaseMetaDataUnicodeRef Connection::getDatabaseMetaDataUnicode()
|
||||
{
|
||||
DatabaseMetaDataUnicodeRef ret(new DatabaseMetaDataUnicode(this));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
328
external/odbccpp/src/odbc/Connection.h
vendored
Normal file
328
external/odbccpp/src/odbc/Connection.h
vendored
Normal file
@ -0,0 +1,328 @@
|
||||
#ifndef ODBC_CONNECTION_H_INCLUDED
|
||||
#define ODBC_CONNECTION_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <cstddef>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* ODBC Connection Wrapper.
|
||||
*
|
||||
* A new Connection object can be created using Environment::createConnection().
|
||||
*
|
||||
* If a Connection object is connected to a database, it will disconnect
|
||||
* automatically when destroyed. However, it is not possible to check if an
|
||||
* error occurred during the disconnect. Therefore, it is recommended to use the
|
||||
* disconnect() member function to disconnect.
|
||||
*/
|
||||
class ODBC_EXPORT Connection : public RefCounted
|
||||
{
|
||||
friend class Environment;
|
||||
friend class DatabaseMetaDataBase;
|
||||
friend class DatabaseMetaDataUnicode;
|
||||
|
||||
private:
|
||||
Connection(Environment* parent);
|
||||
~Connection();
|
||||
|
||||
private:
|
||||
void setHandle(void* hdbc);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Attempts to establish a database connection using a data source name.
|
||||
*
|
||||
* The method will throw an exception if a connection could not be
|
||||
* established.
|
||||
*
|
||||
* @param dsn The data source name.
|
||||
* @param user The user name to use.
|
||||
* @param password The password to use.
|
||||
*/
|
||||
void connect(const char* dsn, const char* user, const char* password);
|
||||
|
||||
/**
|
||||
* Attempts to establish a database connection using an ODBC driver-specific
|
||||
* connection string.
|
||||
*
|
||||
* Refer to the documentation of your ODBC driver for details on the
|
||||
* connection string.
|
||||
*
|
||||
* The method will throw an exception if a connection could not be
|
||||
* established.
|
||||
*
|
||||
* @param connString The driver-specific connection string.
|
||||
*/
|
||||
void connect(const char* connString);
|
||||
|
||||
/**
|
||||
* Disconnects from the database.
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* Checks whether this Connection object is currently connected to the
|
||||
* database.
|
||||
*
|
||||
* This method checks only whether a successful connection has been made in
|
||||
* the past and has not been actively disconnected by the client. It will
|
||||
* not check if the connection is still alive. Use function isValid() to
|
||||
* check if a connection is still alive.
|
||||
*
|
||||
* @return Returns true if the Connection object is connected to the
|
||||
* database, false otherwise.
|
||||
*/
|
||||
bool connected() const;
|
||||
|
||||
/**
|
||||
* Checks whether the connection is still alive or not.
|
||||
*
|
||||
* @return Returns true if the connection is alive, false otherwise.
|
||||
*/
|
||||
bool isValid();
|
||||
|
||||
/**
|
||||
* Gets the number of seconds that a driver can wait for any connection
|
||||
* request to complete.
|
||||
*
|
||||
* If the returned value equals 0, the driver will wait infinitely. The
|
||||
* default value is driver-specific.
|
||||
*
|
||||
* @return Returns the connection timeout.
|
||||
*/
|
||||
unsigned long getConnectionTimeout();
|
||||
|
||||
/**
|
||||
* Sets the numer of seconds that a driver will wait for a connection
|
||||
* request to complete.
|
||||
*
|
||||
* If the value is set to 0, the driver can wait infinitely.
|
||||
*
|
||||
* @param seconds The connection timeout.
|
||||
*/
|
||||
void setConnectionTimeout(unsigned long seconds);
|
||||
|
||||
/**
|
||||
* Gets the number of seconds that a driver can wait for a login attempt to
|
||||
* complete.
|
||||
*
|
||||
* If the returned value equals 0, the driver will wait infinitely. The
|
||||
* default value is driver-specific.
|
||||
*
|
||||
* @return Returns the login timeout.
|
||||
*/
|
||||
unsigned long getLoginTimeout();
|
||||
|
||||
/**
|
||||
* Sets the numer of seconds that a driver will wait for a login attempt to
|
||||
* complete.
|
||||
*
|
||||
* If the value is set to 0, the driver can wait infinitely.
|
||||
*
|
||||
* @param seconds The login timeout.
|
||||
*/
|
||||
void setLoginTimeout(unsigned long seconds);
|
||||
|
||||
/**
|
||||
* Sets a connection attribute of type integer.
|
||||
*
|
||||
* This method is intended for setting driver-specific connection
|
||||
* attributes. Generic connection attributes like the auto-commit attribute
|
||||
* should be set via the corresponding member function. Refer to your ODBC
|
||||
* driver documentation for a list of available attributes.
|
||||
*
|
||||
* Some connection attributes can only be set before a connection has been
|
||||
* made, others can only be set after a connection has been made. Refer
|
||||
* to the documentation of the attribute to find out if it must been set
|
||||
* before or after making a connection.
|
||||
*
|
||||
* @param attr The attribute to set.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
void setAttribute(int attr, int value);
|
||||
|
||||
/**
|
||||
* Sets a connection attribute of type unsigned integer.
|
||||
*
|
||||
* This method is intended for setting driver-specific connection
|
||||
* attributes. Generic connection attributes like the auto-commit attribute
|
||||
* should be set via the corresponding member function. Refer to your ODBC
|
||||
* driver documentation for a list of available attributes.
|
||||
*
|
||||
* Some connection attributes can only be set before a connection has been
|
||||
* made, others can only be set after a connection has been made. Refer
|
||||
* to the documentation of the attribute to find out if it must been set
|
||||
* before or after making a connection.
|
||||
*
|
||||
* @param attr The attribute to set.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
void setAttribute(int attr, unsigned int value);
|
||||
|
||||
/**
|
||||
* Sets a connection attribute of type string.
|
||||
*
|
||||
* This method is intended for setting driver-specific connection
|
||||
* attributes. Generic connection attributes like the auto-commit attribute
|
||||
* should be set via the corresponding member function. Refer to your ODBC
|
||||
* driver documentation for a list of available attributes.
|
||||
*
|
||||
* Some connection attributes can only be set before a connection has been
|
||||
* made, others can only be set after a connection has been made. Refer
|
||||
* to the documentation of the attribute to find out if it must been set
|
||||
* before or after making a connection.
|
||||
*
|
||||
* @param attr The attribute to set.
|
||||
* @param value The value to set.
|
||||
*/
|
||||
void setAttribute(int attr, const char* value);
|
||||
|
||||
/**
|
||||
* Sets a connection attribute of type string.
|
||||
*
|
||||
* This method is intended for setting driver-specific connection
|
||||
* attributes. Generic connection attributes like the auto-commit attribute
|
||||
* should be set via the corresponding member function. Refer to your ODBC
|
||||
* driver documentation for a list of available attributes.
|
||||
*
|
||||
* Some connection attributes can only be set before a connection has been
|
||||
* made, others can only be set after a connection has been made. Refer
|
||||
* to the documentation of the attribute to find out if it must been set
|
||||
* before or after making a connection.
|
||||
*
|
||||
* @param attr The attribute to set.
|
||||
* @param value The value to set.
|
||||
* @param length The length of the string.
|
||||
*/
|
||||
void setAttribute(int attr, const char* value, std::size_t length);
|
||||
|
||||
/**
|
||||
* Sets a connection attribute of type binary.
|
||||
*
|
||||
* This method is intended for setting driver-specific connection
|
||||
* attributes. Generic connection attributes like the auto-commit attribute
|
||||
* should be set via the corresponding member function. Refer to your ODBC
|
||||
* driver documentation for a list of available attributes.
|
||||
*
|
||||
* Some connection attributes can only be set before a connection has been
|
||||
* made, others can only be set after a connection has been made. Refer
|
||||
* to the documentation of the attribute to find out if it must been set
|
||||
* before or after making a connection.
|
||||
*
|
||||
* @param attr The attribute to set.
|
||||
* @param value The value to set.
|
||||
* @param size The size of the binary data in bytes.
|
||||
*/
|
||||
void setAttribute(int attr, const void* value, std::size_t size);
|
||||
|
||||
/**
|
||||
* Checks whether auto-commit mode is enabled.
|
||||
*
|
||||
* @return Returns true if auto-commit is enabled, false otherwise.
|
||||
*/
|
||||
bool getAutoCommit() const;
|
||||
|
||||
/**
|
||||
* Enables or disables auto-commit mode for this connection.
|
||||
*
|
||||
* @param autoCommit Set to true to enable auto-commit, set to false to
|
||||
* disable auto-commit.
|
||||
*/
|
||||
void setAutoCommit(bool autoCommit);
|
||||
|
||||
/**
|
||||
* Commits all changes made since the previous commit or rollback.
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* Undoes all changes made since the previous commit or rollback.
|
||||
*/
|
||||
void rollback();
|
||||
|
||||
/**
|
||||
* Checks whether the Connection object allows statements performing any
|
||||
* updates on data.
|
||||
*
|
||||
* @return Returns true if the Connection is in read only mode.
|
||||
*/
|
||||
bool isReadOnly();
|
||||
|
||||
/**
|
||||
* Sets the Connection object either in read-only or read-write mode.
|
||||
*
|
||||
* By default, the read-only mode is set to false.
|
||||
*
|
||||
* @param readOnly The value indicating read-only mode.
|
||||
*/
|
||||
void setReadOnly(bool readOnly);
|
||||
|
||||
/**
|
||||
* Retrieves the transaction isolation level of this Connection object.
|
||||
*
|
||||
* @return Returns the transaction isolation level.
|
||||
*/
|
||||
TransactionIsolationLevel getTransactionIsolation();
|
||||
|
||||
/**
|
||||
* Attempts to set the isolation level on which the transactions should be
|
||||
* executed.
|
||||
*
|
||||
* This method can be called only if there are no open transactions on the
|
||||
* current Connection object.
|
||||
*
|
||||
* @param level The transaction isolation level.
|
||||
*/
|
||||
void setTransactionIsolation(TransactionIsolationLevel level);
|
||||
|
||||
/**
|
||||
* Creates a new Statement object.
|
||||
*
|
||||
* @return Returns a reference to the newly created Statement object.
|
||||
*/
|
||||
StatementRef createStatement();
|
||||
|
||||
/**
|
||||
* Creates a new PreparedStatement object.
|
||||
*
|
||||
* @param sql The SQL statement to prepare. Use '?' for placeholders.
|
||||
* @return Returns a reference to the newly created PreparedStatement
|
||||
* object.
|
||||
*/
|
||||
PreparedStatementRef prepareStatement(const char* sql);
|
||||
|
||||
/**
|
||||
* Creates a new PreparedStatement object.
|
||||
*
|
||||
* @param sql The SQL statement to prepare. Use '?' for placeholders.
|
||||
* @return Returns a reference to the newly created PreparedStatement
|
||||
* object.
|
||||
*/
|
||||
PreparedStatementRef prepareStatement(const char16_t* sql);
|
||||
|
||||
/**
|
||||
* Retrieves metadata information of the database.
|
||||
*
|
||||
* @return Returns a reference to the DatabaseMetaData object.
|
||||
*/
|
||||
DatabaseMetaDataRef getDatabaseMetaData();
|
||||
|
||||
/**
|
||||
* Retrieves metadata information of the database.
|
||||
*
|
||||
* @return Returns a reference to the DatabaseMetaDataUnicode object.
|
||||
*/
|
||||
DatabaseMetaDataUnicodeRef getDatabaseMetaDataUnicode();
|
||||
|
||||
private:
|
||||
EnvironmentRef parent_;
|
||||
void* hdbc_;
|
||||
bool connected_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
183
external/odbccpp/src/odbc/DatabaseMetaData.cpp
vendored
Normal file
183
external/odbccpp/src/odbc/DatabaseMetaData.cpp
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
#include <cstring>
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/DatabaseMetaData.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
DatabaseMetaData::DatabaseMetaData(Connection* parent)
|
||||
: DatabaseMetaDataBase(parent)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaData::getColumns(const char* catalogName,
|
||||
const char* schemaName, const char* tableName, const char* columnName)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen(tableName) : 0;
|
||||
size_t columnLen = columnName ? strlen(columnName) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8*sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
if (columnLen > maxLen)
|
||||
throw Exception("The column name is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLColumnsA, stmt->hstmt_,
|
||||
(SQLCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLCHAR*)tableName, (SQLSMALLINT)tableLen,
|
||||
(SQLCHAR*)columnName, (SQLSMALLINT)columnLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaData::getColumnPrivileges(const char* catalogName,
|
||||
const char* schemaName, const char* tableName, const char* columnName)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen(tableName) : 0;
|
||||
size_t columnLen = columnName ? strlen(columnName) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8 * sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
if (columnLen > maxLen)
|
||||
throw Exception("The column name is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLColumnPrivilegesA, stmt->hstmt_,
|
||||
(SQLCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLCHAR*)tableName, (SQLSMALLINT)tableLen,
|
||||
(SQLCHAR*)columnName, (SQLSMALLINT)columnLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaData::getPrimaryKeys(const char* catalogName,
|
||||
const char* schemaName, const char* tableName)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen(tableName) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8*sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLPrimaryKeysA, stmt->hstmt_,
|
||||
(SQLCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLCHAR*)tableName, (SQLSMALLINT)tableLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaData::getTables(const char* catalogName,
|
||||
const char* schemaName, const char* tableName, const char* tableType)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen(tableName) : 0;
|
||||
size_t tableTypeLen = tableType ? strlen(tableType) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8 * sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
if (tableTypeLen > maxLen)
|
||||
throw Exception("The table type is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLTablesA, stmt->hstmt_,
|
||||
(SQLCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLCHAR*)tableName, (SQLSMALLINT)tableLen,
|
||||
(SQLCHAR*)tableType, (SQLSMALLINT)tableTypeLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaData::getTypeInfo()
|
||||
{
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLGetTypeInfoA, stmt->hstmt_, SQL_ALL_TYPES);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaData::getTypeInfo(int type)
|
||||
{
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLGetTypeInfoA, stmt->hstmt_, type);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getDataSourceName()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_DATA_SOURCE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getDatabaseName()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_DATABASE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getDBMSName()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_DBMS_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getDBMSVersion()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_DBMS_VER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getDriverName()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_DRIVER_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getDriverVersion()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_DRIVER_VER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getServerName()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_SERVER_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaData::getUserName()
|
||||
{
|
||||
return getStringTypeInfoA(SQL_USER_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
268
external/odbccpp/src/odbc/DatabaseMetaData.h
vendored
Normal file
268
external/odbccpp/src/odbc/DatabaseMetaData.h
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
#ifndef ODBC_DATABASEMETADATA_H_INCLUDED
|
||||
#define ODBC_DATABASEMETADATA_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <string>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/DatabaseMetaDataBase.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Provides information about the database.
|
||||
*
|
||||
* A DatabaseMetaData object can be created using
|
||||
* Connection::getDatabaseMetaData().
|
||||
*
|
||||
* Most functions provide only a rudementary description of the data that is
|
||||
* returned. Refer to the ODBC documentation and your ODBC driver documentation
|
||||
* for further details.
|
||||
*/
|
||||
class ODBC_EXPORT DatabaseMetaData : public DatabaseMetaDataBase
|
||||
{
|
||||
friend class Connection;
|
||||
|
||||
private:
|
||||
DatabaseMetaData(Connection* parent);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves a list of columns in specified tables.
|
||||
*
|
||||
* The list of columns is returned as a ResultSet object, in which each
|
||||
* returned row has the following columns:
|
||||
* 1. Catalog name
|
||||
* 2. Schema name
|
||||
* 3. Table name
|
||||
* 4. Column name
|
||||
* 5. Data type
|
||||
* 6. Type name
|
||||
* 7. Column size
|
||||
* 8. Buffer length
|
||||
* 9. Decimal digits
|
||||
* 10. Numeric radix
|
||||
* 11. Nullability
|
||||
* 12. Remarks
|
||||
* 13. Default value (ODBC 3.0)
|
||||
* 14. SQL data type (ODBC 3.0)
|
||||
* 15. Subtype code for date, time and interval data types (ODBC 3.0)
|
||||
* 16. Maximum length of bytes in a character or binary column type
|
||||
* (ODBC 3.0)
|
||||
* 17. The ordinal position of the column in the table (1-based)
|
||||
* (ODBC 3.0)
|
||||
* 18. Nullability as "NO" or "YES" string (ODBC 3.0)
|
||||
*
|
||||
* This function uses the ODBC function SQLColumns. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string search pattern for schema names.
|
||||
* @param tableName A string search pattern for table names.
|
||||
* @param columnName A string search pattern for column names.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* table description.
|
||||
*/
|
||||
ResultSetRef getColumns(
|
||||
const char* catalogName,
|
||||
const char* schemaName,
|
||||
const char* tableName,
|
||||
const char* columnName);
|
||||
|
||||
/**
|
||||
* Retrieves a list of columns and associated privileges for the specified
|
||||
* table.
|
||||
*
|
||||
* The list of columns is returned as a ResultSet object, in which each
|
||||
* returned row has the following columns:
|
||||
* 1. Catalog name
|
||||
* 2. Schema name
|
||||
* 3. Table name
|
||||
* 4. Column name
|
||||
* 5. Grantor
|
||||
* 6. Grantee
|
||||
* 7. Privilege
|
||||
* 8. Grantable
|
||||
*
|
||||
* This function uses the ODBC function SQLColumnPrivileges. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string indicating the schema name.
|
||||
* @param tableName A string indicating the table name.
|
||||
* @param columnName A string search pattern for column names.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* information about privileges.
|
||||
*/
|
||||
ResultSetRef getColumnPrivileges(
|
||||
const char* catalogName,
|
||||
const char* schemaName,
|
||||
const char* tableName,
|
||||
const char* columnName);
|
||||
|
||||
/**
|
||||
* Retrieves a list of primary keys in the specified table.
|
||||
*
|
||||
* The list of primary keys is returned as a ResultSet object, in which
|
||||
* each returned row has the following columns:
|
||||
* 1. Table catalog name
|
||||
* 2. Table schema name
|
||||
* 3. Table name
|
||||
* 4. Primary key column name
|
||||
* 5. Primary column sequence number in key (1-based)
|
||||
* 6. Primary key name
|
||||
*
|
||||
* This functions uses the ODBC function SQLPrimaryKeys. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string indicating the schema name.
|
||||
* @param tableName A string indicating the table name.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* table description.
|
||||
*/
|
||||
ResultSetRef getPrimaryKeys(
|
||||
const char* catalogName,
|
||||
const char* schemaName,
|
||||
const char* tableName);
|
||||
|
||||
/**
|
||||
* Retrieves a description of the tables that are available in the connected
|
||||
* database.
|
||||
*
|
||||
* The list of tables is returned as a ResultSet object, in which each
|
||||
* returned row has the following columns:
|
||||
* 1. Catalog name
|
||||
* 2. Schema name
|
||||
* 3. Table name
|
||||
* 4. Table type
|
||||
* 5. Remarks
|
||||
*
|
||||
* This function uses the ODBC function SQLTables. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string search pattern for schema names.
|
||||
* @param tableName A string search pattern for table names.
|
||||
* @param tableType A list of table types to be searched. The list must
|
||||
* be empty or must contain a list of a comma-separated
|
||||
* values. These values are "TABLE", "VIEW",
|
||||
* "SYSTEM TABLE", "GLOBAL TEMPORARY",
|
||||
* "LOCAL TEMPORARY", "ALIAS", "SYNONYM", or a data
|
||||
* source-specific type name.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* table description.
|
||||
*/
|
||||
ResultSetRef getTables(
|
||||
const char* catalogName,
|
||||
const char* schemaName,
|
||||
const char* tableName,
|
||||
const char* tableType);
|
||||
|
||||
/**
|
||||
* Retrieves information about all data types.
|
||||
*
|
||||
* The information is returned as a ResultSet object, in which each returned
|
||||
* row has the following columns:
|
||||
* 1. Type name
|
||||
* 2. Data type
|
||||
* 3. Maximum column size for the data type.
|
||||
* 4. Characters used to prefix a literal of that data type.
|
||||
* 5. Characters used to suffix a literal of that data type.
|
||||
* 6. A list of keywords, separated by commas, corresponding to each
|
||||
* parameter that the application may specify in parentheses when
|
||||
* using the name that is returned in field 1.
|
||||
* 7. Nullability of the type.
|
||||
* 8. Case-sensitiveness.
|
||||
* 9. Searchability.
|
||||
* 10. Unsignedness.
|
||||
* 11. Flag indicating if the type has a predefined fixed precision and
|
||||
* scale.
|
||||
* 12. Auto-incrementing flag.
|
||||
* 13. Localized type name.
|
||||
* 14. Minimum scale.
|
||||
* 15. Maximum scale.
|
||||
* 16. SQL data type code.
|
||||
* 17. Date/time subcode.
|
||||
* 18. The radix used by a numeric type.
|
||||
* 19. Interval leading precision.
|
||||
*
|
||||
* This function uses the ODBC function SQLGetTypeInfo. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @return Returns a ResultSet object containing the requested data
|
||||
* type information.
|
||||
*/
|
||||
ResultSetRef getTypeInfo();
|
||||
|
||||
/**
|
||||
* Retrieves information about a specific data type.
|
||||
*
|
||||
* See the documentation of getTypeInfo() for further details.
|
||||
*
|
||||
* @param type The data type to retrieve the type information of.
|
||||
* @return Returns a ResultSet object containing the requested data
|
||||
* type information.
|
||||
*/
|
||||
ResultSetRef getTypeInfo(int type);
|
||||
|
||||
/**
|
||||
* Retrieves the name of the data source.
|
||||
*
|
||||
* @return Returns the name of the data source.
|
||||
*/
|
||||
std::string getDataSourceName();
|
||||
|
||||
/**
|
||||
* Retrieves the current database in use.
|
||||
*
|
||||
* @return Returns the current database in use.
|
||||
*/
|
||||
std::string getDatabaseName();
|
||||
|
||||
/**
|
||||
* Retrieves the name of the DBMS system.
|
||||
*
|
||||
* @return Returns the name of the DBMS system.
|
||||
*/
|
||||
std::string getDBMSName();
|
||||
|
||||
/**
|
||||
* Retrieves the version of the DBMS system.
|
||||
*
|
||||
* @return Returns the version of the DBMS system.
|
||||
*/
|
||||
std::string getDBMSVersion();
|
||||
|
||||
/**
|
||||
* Retrieves the name of the ODBC driver.
|
||||
*
|
||||
* @return Returns the name of the ODBC driver.
|
||||
*/
|
||||
std::string getDriverName();
|
||||
|
||||
/**
|
||||
* Retrieves the version of the ODBC driver.
|
||||
*
|
||||
* @return Returns the version of the ODBC driver.
|
||||
*/
|
||||
std::string getDriverVersion();
|
||||
|
||||
/**
|
||||
* Retrieves the server name.
|
||||
*
|
||||
* @return Returns the server name.
|
||||
*/
|
||||
std::string getServerName();
|
||||
|
||||
/**
|
||||
* Retrieves the name used in the database.
|
||||
*
|
||||
* @return Returns the name used in the database.
|
||||
*/
|
||||
std::string getUserName();
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
126
external/odbccpp/src/odbc/DatabaseMetaDataBase.cpp
vendored
Normal file
126
external/odbccpp/src/odbc/DatabaseMetaDataBase.cpp
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/DatabaseMetaDataBase.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
DatabaseMetaDataBase::DatabaseMetaDataBase(Connection* parent)
|
||||
: parent_(parent, true)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short DatabaseMetaDataBase::getMaxConnections()
|
||||
{
|
||||
return getUSmallIntTypeInfo(SQL_MAX_DRIVER_CONNECTIONS);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned long DatabaseMetaDataBase::getMaxStatementLength()
|
||||
{
|
||||
return getUIntTypeInfo(SQL_MAX_STATEMENT_LEN);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DatabaseMetaDataBase::isReadOnly()
|
||||
{
|
||||
return (getStringTypeInfoA(SQL_DATA_SOURCE_READ_ONLY) == "Y");
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DatabaseMetaDataBase::supportsAlterTableWithAddColumn()
|
||||
{
|
||||
SQLUINTEGER val = getUIntTypeInfo(SQL_ALTER_TABLE);
|
||||
return IS_FLAG_SET(val, SQL_AT_ADD_COLUMN_COLLATION) ||
|
||||
IS_FLAG_SET(val, SQL_AT_ADD_COLUMN_DEFAULT) ||
|
||||
IS_FLAG_SET(val, SQL_AT_ADD_COLUMN_SINGLE);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DatabaseMetaDataBase::supportsAlterTableWithDropColumn()
|
||||
{
|
||||
SQLUINTEGER val = getUIntTypeInfo(SQL_ALTER_TABLE);
|
||||
return IS_FLAG_SET(val, SQL_AT_DROP_COLUMN_CASCADE) ||
|
||||
IS_FLAG_SET(val, SQL_AT_DROP_COLUMN_DEFAULT) ||
|
||||
IS_FLAG_SET(val, SQL_AT_DROP_COLUMN_RESTRICT);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
TransactionIsolationLevel DatabaseMetaDataBase::getDefaultTransactionIsolation()
|
||||
{
|
||||
SQLUINTEGER txn = getUIntTypeInfo(SQL_DEFAULT_TXN_ISOLATION);
|
||||
switch (txn)
|
||||
{
|
||||
case SQL_TXN_READ_COMMITTED:
|
||||
return TransactionIsolationLevel::READ_COMMITTED;
|
||||
case SQL_TXN_READ_UNCOMMITTED:
|
||||
return TransactionIsolationLevel::READ_UNCOMMITTED;
|
||||
case SQL_TXN_REPEATABLE_READ:
|
||||
return TransactionIsolationLevel::REPEATABLE_READ;
|
||||
case SQL_TXN_SERIALIZABLE:
|
||||
return TransactionIsolationLevel::SERIALIZABLE;
|
||||
case 0:
|
||||
return TransactionIsolationLevel::NONE;
|
||||
default:
|
||||
throw Exception("Unknown transaction isolation level.");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool DatabaseMetaDataBase::supportsTransactionIsolation(
|
||||
TransactionIsolationLevel level)
|
||||
{
|
||||
SQLUINTEGER txn = getUIntTypeInfo(SQL_TXN_ISOLATION_OPTION);
|
||||
switch (level)
|
||||
{
|
||||
case TransactionIsolationLevel::READ_COMMITTED:
|
||||
return IS_FLAG_SET(txn, SQL_TXN_READ_COMMITTED);
|
||||
case TransactionIsolationLevel::READ_UNCOMMITTED:
|
||||
return IS_FLAG_SET(txn, SQL_TXN_READ_UNCOMMITTED);
|
||||
case TransactionIsolationLevel::REPEATABLE_READ:
|
||||
return IS_FLAG_SET(txn, SQL_TXN_REPEATABLE_READ);
|
||||
case TransactionIsolationLevel::SERIALIZABLE:
|
||||
return IS_FLAG_SET(txn, SQL_TXN_SERIALIZABLE);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
StatementRef DatabaseMetaDataBase::createStatement()
|
||||
{
|
||||
return parent_->createStatement();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string DatabaseMetaDataBase::getStringTypeInfoA(unsigned short typeInfo)
|
||||
{
|
||||
vector<char> buffer;
|
||||
buffer.resize(256);
|
||||
while (true)
|
||||
{
|
||||
SQLPOINTER ptr = &buffer[0];
|
||||
SQLSMALLINT bufLen = (SQLSMALLINT)buffer.size();
|
||||
SQLSMALLINT dataLen;
|
||||
EXEC_DBC(SQLGetInfoA, parent_->hdbc_, typeInfo, ptr, bufLen, &dataLen);
|
||||
if (dataLen < bufLen)
|
||||
break;
|
||||
buffer.resize(dataLen + 1);
|
||||
}
|
||||
return string(&buffer[0]);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned long DatabaseMetaDataBase::getUIntTypeInfo(unsigned short typeInfo)
|
||||
{
|
||||
SQLUINTEGER ret;
|
||||
SQLSMALLINT len;
|
||||
EXEC_DBC(SQLGetInfo, parent_->hdbc_, typeInfo, &ret, sizeof(ret), &len);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short DatabaseMetaDataBase::getUSmallIntTypeInfo(
|
||||
unsigned short typeInfo)
|
||||
{
|
||||
SQLUSMALLINT ret;
|
||||
SQLSMALLINT len;
|
||||
EXEC_DBC(SQLGetInfo, parent_->hdbc_, typeInfo, &ret, sizeof(ret), &len);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
93
external/odbccpp/src/odbc/DatabaseMetaDataBase.h
vendored
Normal file
93
external/odbccpp/src/odbc/DatabaseMetaDataBase.h
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef ODBC_DATABASEMETADATABASE_H_INCLUDED
|
||||
#define ODBC_DATABASEMETADATABASE_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <string>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Base class for DatabaseMetaData and DatabaseMetaDataUnicode.
|
||||
*/
|
||||
class ODBC_EXPORT DatabaseMetaDataBase : public RefCounted
|
||||
{
|
||||
protected:
|
||||
DatabaseMetaDataBase(Connection* parent);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves the maximum number of active connections the driver can
|
||||
* support.
|
||||
*
|
||||
* @return Returns the maximum number of active connections the driver can
|
||||
* support. If there is no limit or if the limit is not known,
|
||||
* the function returns 0.
|
||||
*/
|
||||
unsigned short getMaxConnections();
|
||||
|
||||
/**
|
||||
* Retrieves the maximum length of a statement string.
|
||||
*
|
||||
* @return Returns the maximum length of a statement string. If there is no
|
||||
* limit or if the limit is not known, the function returns 0.
|
||||
*/
|
||||
unsigned long getMaxStatementLength();
|
||||
|
||||
/**
|
||||
* Checks whether the database is in read-only mode.
|
||||
*
|
||||
* @return Returns true if the database is in read-only mode, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool isReadOnly();
|
||||
|
||||
/**
|
||||
* Checks whether the database supports adding columns to existing tables.
|
||||
*
|
||||
* @returns Returns true if the database supports adding columns to
|
||||
* existing tables, false otherwise.
|
||||
*/
|
||||
bool supportsAlterTableWithAddColumn();
|
||||
|
||||
/**
|
||||
* Checks whether the database supports dropping columns from existing
|
||||
* tables.
|
||||
*
|
||||
* @returns Returns true if the database supports dropping columns to
|
||||
* existing tables, false otherwise.
|
||||
*/
|
||||
bool supportsAlterTableWithDropColumn();
|
||||
|
||||
/**
|
||||
* Retrieves the default transaction isolation level of the database.
|
||||
*
|
||||
* @return Returns the default transaction isolation level.
|
||||
*/
|
||||
TransactionIsolationLevel getDefaultTransactionIsolation();
|
||||
|
||||
/**
|
||||
* Checks whether the database supports the given transaction isolation
|
||||
* level or not.
|
||||
*
|
||||
* @return Returns true if the given transaction isolation level is
|
||||
* supported, otherwise false.
|
||||
*/
|
||||
bool supportsTransactionIsolation(TransactionIsolationLevel level);
|
||||
|
||||
protected:
|
||||
StatementRef createStatement();
|
||||
std::string getStringTypeInfoA(unsigned short typeInfo);
|
||||
|
||||
private:
|
||||
unsigned long getUIntTypeInfo(unsigned short typeInfo);
|
||||
unsigned short getUSmallIntTypeInfo(unsigned short typeInfo);
|
||||
|
||||
protected:
|
||||
ConnectionRef parent_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
213
external/odbccpp/src/odbc/DatabaseMetaDataUnicode.cpp
vendored
Normal file
213
external/odbccpp/src/odbc/DatabaseMetaDataUnicode.cpp
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
#include <string>
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/DatabaseMetaDataUnicode.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace {
|
||||
//------------------------------------------------------------------------------
|
||||
size_t strlen16(const char16_t* str)
|
||||
{
|
||||
return char_traits<char16_t>::length(str);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
DatabaseMetaDataUnicode::DatabaseMetaDataUnicode(Connection* parent)
|
||||
: DatabaseMetaDataBase(parent)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaDataUnicode::getColumns(const char16_t* catalogName,
|
||||
const char16_t* schemaName, const char16_t* tableName,
|
||||
const char16_t* columnName)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen16(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen16(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen16(tableName) : 0;
|
||||
size_t columnLen = columnName ? strlen16(columnName) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8*sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
if (columnLen > maxLen)
|
||||
throw Exception("The column name is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLColumnsW, stmt->hstmt_,
|
||||
(SQLWCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLWCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLWCHAR*)tableName, (SQLSMALLINT)tableLen,
|
||||
(SQLWCHAR*)columnName, (SQLSMALLINT)columnLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaDataUnicode::getColumnPrivileges(
|
||||
const char16_t* catalogName, const char16_t* schemaName,
|
||||
const char16_t* tableName, const char16_t* columnName)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen16(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen16(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen16(tableName) : 0;
|
||||
size_t columnLen = columnName ? strlen16(columnName) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8 * sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
if (columnLen > maxLen)
|
||||
throw Exception("The column name is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLColumnPrivilegesW, stmt->hstmt_,
|
||||
(SQLWCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLWCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLWCHAR*)tableName, (SQLSMALLINT)tableLen,
|
||||
(SQLWCHAR*)columnName, (SQLSMALLINT)columnLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaDataUnicode::getPrimaryKeys(
|
||||
const char16_t* catalogName, const char16_t* schemaName,
|
||||
const char16_t* tableName)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen16(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen16(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen16(tableName) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8*sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLPrimaryKeysW, stmt->hstmt_,
|
||||
(SQLWCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLWCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLWCHAR*)tableName, (SQLSMALLINT)tableLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaDataUnicode::getTables(const char16_t* catalogName,
|
||||
const char16_t* schemaName, const char16_t* tableName,
|
||||
const char16_t* tableType)
|
||||
{
|
||||
size_t catalogLen = catalogName ? strlen16(catalogName) : 0;
|
||||
size_t schemaLen = schemaName ? strlen16(schemaName) : 0;
|
||||
size_t tableLen = tableName ? strlen16(tableName) : 0;
|
||||
size_t tableTypeLen = tableType ? strlen16(tableType) : 0;
|
||||
|
||||
size_t maxLen = (1 << 8 * sizeof(SQLSMALLINT)) - 1;
|
||||
if (catalogLen > maxLen)
|
||||
throw Exception("The catalog name is too long");
|
||||
if (schemaLen > maxLen)
|
||||
throw Exception("The schema name is too long");
|
||||
if (tableLen > maxLen)
|
||||
throw Exception("The table name is too long");
|
||||
if (tableTypeLen > maxLen)
|
||||
throw Exception("The table type is too long");
|
||||
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLTablesW, stmt->hstmt_,
|
||||
(SQLWCHAR*)catalogName, (SQLSMALLINT)catalogLen,
|
||||
(SQLWCHAR*)schemaName, (SQLSMALLINT)schemaLen,
|
||||
(SQLWCHAR*)tableName, (SQLSMALLINT)tableLen,
|
||||
(SQLWCHAR*)tableType, (SQLSMALLINT)tableTypeLen);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaDataUnicode::getTypeInfo()
|
||||
{
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLGetTypeInfoW, stmt->hstmt_, SQL_ALL_TYPES);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef DatabaseMetaDataUnicode::getTypeInfo(int type)
|
||||
{
|
||||
StatementRef stmt = createStatement();
|
||||
ResultSetRef ret(new ResultSet(stmt.get()));
|
||||
EXEC_STMT(SQLGetTypeInfoW, stmt->hstmt_, type);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getDataSourceName()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_DATA_SOURCE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getDatabaseName()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_DATABASE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getDBMSName()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_DBMS_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getDBMSVersion()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_DBMS_VER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getDriverName()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_DRIVER_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getDriverVersion()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_DRIVER_VER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getServerName()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_SERVER_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getUserName()
|
||||
{
|
||||
return getStringTypeInfoW(SQL_USER_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string DatabaseMetaDataUnicode::getStringTypeInfoW(unsigned short typeInfo)
|
||||
{
|
||||
vector<char16_t> buffer;
|
||||
buffer.resize(256);
|
||||
while (true)
|
||||
{
|
||||
SQLPOINTER ptr = &buffer[0];
|
||||
SQLSMALLINT bufLen = (SQLSMALLINT)(buffer.size() * sizeof(char16_t));
|
||||
SQLSMALLINT dataLen;
|
||||
EXEC_DBC(SQLGetInfoW, parent_->hdbc_, typeInfo, ptr, bufLen, &dataLen);
|
||||
if (dataLen < bufLen)
|
||||
break;
|
||||
buffer.resize(dataLen / sizeof(char16_t) + 1);
|
||||
}
|
||||
return u16string(&buffer[0]);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
271
external/odbccpp/src/odbc/DatabaseMetaDataUnicode.h
vendored
Normal file
271
external/odbccpp/src/odbc/DatabaseMetaDataUnicode.h
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
#ifndef ODBC_DATABASEMETADATAUNICODE_H_INCLUDED
|
||||
#define ODBC_DATABASEMETADATAUNICODE_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <string>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/DatabaseMetaDataBase.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Provides information about the database.
|
||||
*
|
||||
* A DatabaseMetaDataUnicode object can be created using
|
||||
* Connection::getDatabaseMetaDataUnicode().
|
||||
*
|
||||
* Most functions provide only a rudementary description of the data that is
|
||||
* returned. Refer to the ODBC documentation and your ODBC driver documentation
|
||||
* for further details.
|
||||
*/
|
||||
class ODBC_EXPORT DatabaseMetaDataUnicode : public DatabaseMetaDataBase
|
||||
{
|
||||
friend class Connection;
|
||||
|
||||
private:
|
||||
DatabaseMetaDataUnicode(Connection* parent);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves a list of columns in specified tables.
|
||||
*
|
||||
* The list of columns is returned as a ResultSet object, in which each
|
||||
* returned row has the following columns:
|
||||
* 1. Catalog name
|
||||
* 2. Schema name
|
||||
* 3. Table name
|
||||
* 4. Column name
|
||||
* 5. Data type
|
||||
* 6. Type name
|
||||
* 7. Column size
|
||||
* 8. Buffer length
|
||||
* 9. Decimal digits
|
||||
* 10. Numeric radix
|
||||
* 11. Nullability
|
||||
* 12. Remarks
|
||||
* 13. Default value (ODBC 3.0)
|
||||
* 14. SQL data type (ODBC 3.0)
|
||||
* 15. Subtype code for date, time and interval data types (ODBC 3.0)
|
||||
* 16. Maximum length of bytes in a character or binary column type
|
||||
* (ODBC 3.0)
|
||||
* 17. The ordinal position of the column in the table (1-based)
|
||||
* (ODBC 3.0)
|
||||
* 18. Nullability as "NO" or "YES" string (ODBC 3.0)
|
||||
*
|
||||
* This function uses the ODBC function SQLColumns. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string search pattern for schema names.
|
||||
* @param tableName A string search pattern for table names.
|
||||
* @param columnName A string search pattern for column names.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* table description.
|
||||
*/
|
||||
ResultSetRef getColumns(
|
||||
const char16_t* catalogName,
|
||||
const char16_t* schemaName,
|
||||
const char16_t* tableName,
|
||||
const char16_t* columnName);
|
||||
|
||||
/**
|
||||
* Retrieves a list of columns and associated privileges for the specified
|
||||
* table.
|
||||
*
|
||||
* The list of columns is returned as a ResultSet object, in which each
|
||||
* returned row has the following columns:
|
||||
* 1. Catalog name
|
||||
* 2. Schema name
|
||||
* 3. Table name
|
||||
* 4. Column name
|
||||
* 5. Grantor
|
||||
* 6. Grantee
|
||||
* 7. Privilege
|
||||
* 8. Grantable
|
||||
*
|
||||
* This function uses the ODBC function SQLColumnPrivileges. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string indicating the schema name.
|
||||
* @param tableName A string indicating the table name.
|
||||
* @param columnName A string search pattern for column names.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* information about privileges.
|
||||
*/
|
||||
ResultSetRef getColumnPrivileges(
|
||||
const char16_t* catalogName,
|
||||
const char16_t* schemaName,
|
||||
const char16_t* tableName,
|
||||
const char16_t* columnName);
|
||||
|
||||
/**
|
||||
* Retrieves a list of primary keys in the specified table.
|
||||
*
|
||||
* The list of primary keys is returned as a ResultSet object, in which
|
||||
* each returned row has the following columns:
|
||||
* 1. Table catalog name
|
||||
* 2. Table schema name
|
||||
* 3. Table name
|
||||
* 4. Primary key column name
|
||||
* 5. Primary column sequence number in key (1-based)
|
||||
* 6. Primary key name
|
||||
*
|
||||
* This functions uses the ODBC function SQLPrimaryKeys. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string indicating the schema name.
|
||||
* @param tableName A string indicating the table name.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* table description.
|
||||
*/
|
||||
ResultSetRef getPrimaryKeys(
|
||||
const char16_t* catalogName,
|
||||
const char16_t* schemaName,
|
||||
const char16_t* tableName);
|
||||
|
||||
/**
|
||||
* Retrieves a description of the tables that are available in the connected
|
||||
* database.
|
||||
*
|
||||
* The list of tables is returned as a ResultSet object, in which each
|
||||
* returned row has the following columns:
|
||||
* 1. Catalog name
|
||||
* 2. Schema name
|
||||
* 3. Table name
|
||||
* 4. Table type
|
||||
* 5. Remarks
|
||||
*
|
||||
* This function uses the ODBC function SQLTables. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @param catalogName A string indicating the catalog name.
|
||||
* @param schemaName A string search pattern for schema names.
|
||||
* @param tableName A string search pattern for table names.
|
||||
* @param tableType A list of table types to be searched. The list must
|
||||
* be empty or must contain a list of a comma-separated
|
||||
* values. These values are "TABLE", "VIEW",
|
||||
* "SYSTEM TABLE", "GLOBAL TEMPORARY",
|
||||
* "LOCAL TEMPORARY", "ALIAS", "SYNONYM", or a data
|
||||
* source-specific type name.
|
||||
* @return Returns a ResultSet object containing the requested
|
||||
* table description.
|
||||
*/
|
||||
ResultSetRef getTables(
|
||||
const char16_t* catalogName,
|
||||
const char16_t* schemaName,
|
||||
const char16_t* tableName,
|
||||
const char16_t* tableType);
|
||||
|
||||
/**
|
||||
* Retrieves information about all data types.
|
||||
*
|
||||
* The information is returned as a ResultSet object, in which each returned
|
||||
* row has the following columns:
|
||||
* 1. Type name
|
||||
* 2. Data type
|
||||
* 3. Maximum column size for the data type.
|
||||
* 4. Characters used to prefix a literal of that data type.
|
||||
* 5. Characters used to suffix a literal of that data type.
|
||||
* 6. A list of keywords, separated by commas, corresponding to each
|
||||
* parameter that the application may specify in parentheses when
|
||||
* using the name that is returned in field 1.
|
||||
* 7. Nullability of the type.
|
||||
* 8. Case-sensitiveness.
|
||||
* 9. Searchability.
|
||||
* 10. Unsignedness.
|
||||
* 11. Flag indicating if the type has a predefined fixed precision and
|
||||
* scale.
|
||||
* 12. Auto-incrementing flag.
|
||||
* 13. Localized type name.
|
||||
* 14. Minimum scale.
|
||||
* 15. Maximum scale.
|
||||
* 16. SQL data type code.
|
||||
* 17. Date/time subcode.
|
||||
* 18. The radix used by a numeric type.
|
||||
* 19. Interval leading precision.
|
||||
*
|
||||
* This function uses the ODBC function SQLGetTypeInfo. Refer to its
|
||||
* documentation for further details on the data in the ResultSet object.
|
||||
*
|
||||
* @return Returns a ResultSet object containing the requested data
|
||||
* type information.
|
||||
*/
|
||||
ResultSetRef getTypeInfo();
|
||||
|
||||
/**
|
||||
* Retrieves information about a specific data type.
|
||||
*
|
||||
* See the documentation of getTypeInfo() for further details.
|
||||
*
|
||||
* @param type The data type to retrieve the type information of.
|
||||
* @return Returns a ResultSet object containing the requested data
|
||||
* type information.
|
||||
*/
|
||||
ResultSetRef getTypeInfo(int type);
|
||||
|
||||
/**
|
||||
* Retrieves the name of the data source.
|
||||
*
|
||||
* @return Returns the name of the data source.
|
||||
*/
|
||||
std::u16string getDataSourceName();
|
||||
|
||||
/**
|
||||
* Retrieves the current database in use.
|
||||
*
|
||||
* @return Returns the current database in use.
|
||||
*/
|
||||
std::u16string getDatabaseName();
|
||||
|
||||
/**
|
||||
* Retrieves the name of the DBMS system.
|
||||
*
|
||||
* @return Returns the name of the DBMS system.
|
||||
*/
|
||||
std::u16string getDBMSName();
|
||||
|
||||
/**
|
||||
* Retrieves the version of the DBMS system.
|
||||
*
|
||||
* @return Returns the version of the DBMS system.
|
||||
*/
|
||||
std::u16string getDBMSVersion();
|
||||
|
||||
/**
|
||||
* Retrieves the name of the ODBC driver.
|
||||
*
|
||||
* @return Returns the name of the ODBC driver.
|
||||
*/
|
||||
std::u16string getDriverName();
|
||||
|
||||
/**
|
||||
* Retrieves the version of the ODBC driver.
|
||||
*
|
||||
* @return Returns the version of the ODBC driver.
|
||||
*/
|
||||
std::u16string getDriverVersion();
|
||||
|
||||
/**
|
||||
* Retrieves the server name.
|
||||
*
|
||||
* @return Returns the server name.
|
||||
*/
|
||||
std::u16string getServerName();
|
||||
|
||||
/**
|
||||
* Retrieves the name used in the database.
|
||||
*
|
||||
* @return Returns the name used in the database.
|
||||
*/
|
||||
std::u16string getUserName();
|
||||
|
||||
private:
|
||||
std::u16string getStringTypeInfoW(unsigned short typeInfo);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
194
external/odbccpp/src/odbc/Environment.cpp
vendored
Normal file
194
external/odbccpp/src/odbc/Environment.cpp
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
#include <cstring>
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/Environment.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
EnvironmentRef Environment::create()
|
||||
{
|
||||
return EnvironmentRef(new Environment);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Environment::Environment()
|
||||
{
|
||||
SQLRETURN rc;
|
||||
rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv_);
|
||||
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
|
||||
throw Exception("Could not allocate environment");
|
||||
|
||||
EXEC_ENV(SQLSetEnvAttr, henv_, SQL_ATTR_ODBC_VERSION,
|
||||
(SQLPOINTER)SQL_OV_ODBC3, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Environment::~Environment()
|
||||
{
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, henv_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ConnectionRef Environment::createConnection()
|
||||
{
|
||||
SQLHANDLE hdbc;
|
||||
ConnectionRef ret(new Connection(this));
|
||||
SQLRETURN rc = SQLAllocHandle(SQL_HANDLE_DBC, henv_, &hdbc);
|
||||
Exception::checkForError(rc, SQL_HANDLE_ENV, henv_);
|
||||
ret->setHandle(hdbc);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
vector<DataSourceInformation> Environment::getDataSources()
|
||||
{
|
||||
return getDataSources(DSNType::ALL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
vector<DataSourceInformation> Environment::getDataSources(DSNType dsnType)
|
||||
{
|
||||
vector<DataSourceInformation> ret;
|
||||
|
||||
SQLCHAR nameBuf[SQL_MAX_DSN_LENGTH + 1];
|
||||
vector<SQLCHAR> descBuf;
|
||||
descBuf.resize(256);
|
||||
SQLSMALLINT nameLen;
|
||||
SQLSMALLINT descLen;
|
||||
SQLUSMALLINT direction;
|
||||
|
||||
switch (dsnType)
|
||||
{
|
||||
case DSNType::ALL:
|
||||
direction = SQL_FETCH_FIRST;
|
||||
break;
|
||||
case DSNType::SYSTEM:
|
||||
direction = SQL_FETCH_FIRST_SYSTEM;
|
||||
break;
|
||||
case DSNType::USER:
|
||||
direction = SQL_FETCH_FIRST_USER;
|
||||
break;
|
||||
default:
|
||||
ODBC_FAIL("Unknown DSN type.");
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
SQLRETURN rc = SQLDataSourcesA(henv_, direction,
|
||||
nameBuf, sizeof(nameBuf), &nameLen,
|
||||
descBuf.data(), (SQLSMALLINT)descBuf.size(), &descLen);
|
||||
if (rc == SQL_NO_DATA)
|
||||
return ret;
|
||||
Exception::checkForError(rc, SQL_HANDLE_ENV, henv_);
|
||||
if (descLen < (SQLSMALLINT)descBuf.size())
|
||||
break;
|
||||
descBuf.resize(descLen + 1);
|
||||
}
|
||||
|
||||
ret.push_back({ string((const char*)nameBuf, nameLen),
|
||||
string((const char*)descBuf.data(), descLen) });
|
||||
direction = SQL_FETCH_NEXT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
vector<DriverInformation> Environment::getDrivers()
|
||||
{
|
||||
vector<DriverInformation> ret;
|
||||
|
||||
vector<SQLCHAR> descBuf;
|
||||
descBuf.resize(256);
|
||||
vector<SQLCHAR> attrBuf;
|
||||
attrBuf.resize(256);
|
||||
SQLSMALLINT descLen;
|
||||
SQLSMALLINT attrLen;
|
||||
SQLUSMALLINT direction = SQL_FETCH_FIRST;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
SQLRETURN rc = SQLDriversA(henv_, direction,
|
||||
descBuf.data(), (SQLSMALLINT)descBuf.size(), &descLen,
|
||||
attrBuf.data(), (SQLSMALLINT)attrBuf.size(), &attrLen);
|
||||
if (rc == SQL_NO_DATA)
|
||||
return ret;
|
||||
Exception::checkForError(rc, SQL_HANDLE_ENV, henv_);
|
||||
if (descLen < (SQLSMALLINT)descBuf.size() &&
|
||||
attrLen < (SQLSMALLINT)attrBuf.size())
|
||||
break;
|
||||
if (descLen >= (SQLSMALLINT)descBuf.size())
|
||||
descBuf.resize(descLen + 1);
|
||||
if (attrLen >= (SQLSMALLINT)attrBuf.size())
|
||||
attrBuf.resize(attrLen + 1);
|
||||
}
|
||||
|
||||
DriverInformation driverInfo;
|
||||
driverInfo.description = string((const char*)descBuf.data(), descLen);
|
||||
if (attrLen > 0)
|
||||
{
|
||||
// Parse keyword-value pairs given in the following format
|
||||
// FileUsage=1\0FileExtns=*.dbf\0\0
|
||||
const char* start = (const char*)attrBuf.data();
|
||||
size_t attrBufLen = (size_t)attrLen;
|
||||
size_t totalLen = 0;
|
||||
while (totalLen < attrBufLen)
|
||||
{
|
||||
const char* end = strchr(start, '\0');
|
||||
if (end == nullptr)
|
||||
throw Exception("Unable to parse driver attribute value.");
|
||||
size_t len = end - start;
|
||||
const char* sep = strchr(start, '=');
|
||||
if (sep == nullptr)
|
||||
throw Exception("Unable to parse driver attribute value.");
|
||||
size_t pos = sep - start;
|
||||
driverInfo.attributes.push_back(
|
||||
{ string(start, pos),
|
||||
string(start + pos + 1, len - pos - 1) });
|
||||
totalLen += len + 1;
|
||||
start = end + 1;
|
||||
}
|
||||
}
|
||||
ret.push_back(move(driverInfo));
|
||||
|
||||
direction = SQL_FETCH_NEXT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool Environment::isDriverInstalled(const char* name)
|
||||
{
|
||||
vector<SQLCHAR> descBuf;
|
||||
descBuf.resize(256);
|
||||
SQLSMALLINT descLen;
|
||||
SQLSMALLINT attrLen;
|
||||
SQLUSMALLINT direction = SQL_FETCH_FIRST;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
SQLRETURN rc = SQLDriversA(henv_, direction,
|
||||
descBuf.data(), (SQLSMALLINT)descBuf.size(), &descLen,
|
||||
nullptr, 0, &attrLen);
|
||||
if (rc == SQL_NO_DATA)
|
||||
return false;
|
||||
Exception::checkForError(rc, SQL_HANDLE_ENV, henv_);
|
||||
if (descLen < (SQLSMALLINT)descBuf.size())
|
||||
break;
|
||||
descBuf.resize(descLen + 1);
|
||||
}
|
||||
|
||||
if (strcmp(name, (const char*)descBuf.data()) == 0)
|
||||
return true;
|
||||
|
||||
direction = SQL_FETCH_NEXT;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
132
external/odbccpp/src/odbc/Environment.h
vendored
Normal file
132
external/odbccpp/src/odbc/Environment.h
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef ODBC_ENVIRONMENT_H_INCLUDED
|
||||
#define ODBC_ENVIRONMENT_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
struct DataSourceInformation;
|
||||
struct DriverInformation;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* ODBC Environment Wrapper.
|
||||
*
|
||||
* Represents an environment context that manages connection creations.
|
||||
*/
|
||||
class ODBC_EXPORT Environment : public RefCounted
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a new Environment object.
|
||||
*
|
||||
* @return Returns a reference to the newly created Environment object.
|
||||
*/
|
||||
static EnvironmentRef create();
|
||||
|
||||
private:
|
||||
Environment();
|
||||
~Environment();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a new Connection object.
|
||||
*
|
||||
* @return Returns a reference to the newly created Connection object.
|
||||
*/
|
||||
ConnectionRef createConnection();
|
||||
|
||||
/**
|
||||
* Retrieves information about available data sources.
|
||||
*
|
||||
* @return Returns a full list of DataSourceInformation objects.
|
||||
*/
|
||||
std::vector<DataSourceInformation> getDataSources();
|
||||
|
||||
/**
|
||||
* Retrieves information about available data sources of the specified type.
|
||||
*
|
||||
* @param dsnType Specifies the type of the returned ODBC DSNs.
|
||||
* @return Returns a list of DataSourceInformation objects.
|
||||
*/
|
||||
std::vector<DataSourceInformation> getDataSources(DSNType dsnType);
|
||||
|
||||
/**
|
||||
* Retrieves information about available drivers.
|
||||
*
|
||||
* @return Returns a list of DriverInformation objects.
|
||||
*/
|
||||
std::vector<DriverInformation> getDrivers();
|
||||
|
||||
/**
|
||||
* Gets a value indicating whether the given driver is installed or not.
|
||||
*
|
||||
* @param name The driver name.
|
||||
* @return Returns true if the driver is installed, otherwise false.
|
||||
*/
|
||||
bool isDriverInstalled(const char* name);
|
||||
|
||||
private:
|
||||
void* henv_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Stores the name and description of a data source.
|
||||
*/
|
||||
struct DataSourceInformation
|
||||
{
|
||||
/**
|
||||
* The data source name.
|
||||
*
|
||||
* For example, dBASE Files or SQL Server.
|
||||
*/
|
||||
std::string name;
|
||||
/**
|
||||
* The description of the driver associated with the data source.
|
||||
*
|
||||
* For example, Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx).
|
||||
*/
|
||||
std::string description;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Stores the description and additional information about the driver.
|
||||
*/
|
||||
struct DriverInformation
|
||||
{
|
||||
/**
|
||||
* Stores the name and the value of a driver attribute.
|
||||
*
|
||||
* For example, DriverODBCVer=03.51.
|
||||
*/
|
||||
struct Attribute
|
||||
{
|
||||
/**
|
||||
* The attribute's name.
|
||||
*/
|
||||
std::string name;
|
||||
/**
|
||||
* The attribute's value.
|
||||
*/
|
||||
std::string value;
|
||||
};
|
||||
|
||||
/**
|
||||
* The driver description.
|
||||
*
|
||||
* For example, PostgreSQL Unicode(x64) or SQL Server.
|
||||
*/
|
||||
std::string description;
|
||||
|
||||
/**
|
||||
* The list of driver attributes.
|
||||
*/
|
||||
std::vector<Attribute> attributes;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
83
external/odbccpp/src/odbc/Exception.cpp
vendored
Normal file
83
external/odbccpp/src/odbc/Exception.cpp
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
#include <sstream>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace {
|
||||
//------------------------------------------------------------------------------
|
||||
bool appendRecord(short handleType, void* handle, SQLSMALLINT recNumber,
|
||||
ostringstream& out)
|
||||
{
|
||||
SQLCHAR sqlState[6];
|
||||
SQLINTEGER nativeError;
|
||||
SQLCHAR messageText[2048];
|
||||
SQLSMALLINT textLength;
|
||||
SQLRETURN rc = SQLGetDiagRecA(handleType, handle, recNumber, sqlState,
|
||||
&nativeError, messageText, sizeof(messageText)/sizeof(SQLCHAR),
|
||||
&textLength);
|
||||
switch (rc)
|
||||
{
|
||||
case SQL_SUCCESS:
|
||||
case SQL_SUCCESS_WITH_INFO:
|
||||
if (recNumber > 1)
|
||||
out << endl;
|
||||
out << "ERROR: " << nativeError << ": " << sqlState << " : "
|
||||
<< messageText << endl;
|
||||
return true;
|
||||
case SQL_ERROR:
|
||||
if (recNumber > 1)
|
||||
out << endl;
|
||||
out << "An error occurred while calling SQLGetDiagRec" << endl;
|
||||
return false;
|
||||
case SQL_INVALID_HANDLE:
|
||||
if (recNumber > 1)
|
||||
out << endl;
|
||||
out << "The handle passed to SQLGetDiagRec is not valid" << endl;
|
||||
return false;
|
||||
case SQL_NO_DATA:
|
||||
return false;
|
||||
default:
|
||||
if (recNumber > 1)
|
||||
out << endl;
|
||||
out << "An unknown return code was returned by SQLGetDiagRec" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
void Exception::checkForError(short rc, short handleType, void* handle)
|
||||
{
|
||||
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
|
||||
throw create(handleType, handle);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Exception Exception::create(short handleType, void* handle)
|
||||
{
|
||||
ostringstream out;
|
||||
SQLSMALLINT recNumber = 1;
|
||||
while (appendRecord(handleType, handle, recNumber, out))
|
||||
{
|
||||
++recNumber;
|
||||
}
|
||||
return Exception(out.str());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Exception::Exception(const char* s) : msg_(s)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Exception::Exception(const std::string& s) : msg_(s)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
const char* Exception::what() const noexcept
|
||||
{
|
||||
return msg_.c_str();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
59
external/odbccpp/src/odbc/Exception.h
vendored
Normal file
59
external/odbccpp/src/odbc/Exception.h
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef ODBC_EXCEPTION_H_INCLUDED
|
||||
#define ODBC_EXCEPTION_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* ODBC-related exception.
|
||||
*/
|
||||
class ODBC_EXPORT Exception : public std::exception
|
||||
{
|
||||
private:
|
||||
friend class Batch;
|
||||
friend class Connection;
|
||||
friend class DatabaseMetaData;
|
||||
friend class DatabaseMetaDataBase;
|
||||
friend class DatabaseMetaDataUnicode;
|
||||
friend class date;
|
||||
friend class decimal;
|
||||
friend class Environment;
|
||||
friend class ParameterMetaData;
|
||||
friend class PreparedStatement;
|
||||
friend class ResultSet;
|
||||
friend class ResultSetMetaData;
|
||||
friend class ResultSetMetaDataBase;
|
||||
friend class ResultSetMetaDataUnicode;
|
||||
friend class Statement;
|
||||
friend class StatementBase;
|
||||
friend class time;
|
||||
friend class timestamp;
|
||||
friend class ValueBuffer;
|
||||
friend class Util;
|
||||
|
||||
static void checkForError(short rc, short handleType, void* handle);
|
||||
static Exception create(short handleType, void* handle);
|
||||
|
||||
Exception(const char* s);
|
||||
Exception(const std::string& s);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Describes the reason of the exception.
|
||||
*
|
||||
* @return Returns a description of the error that occurred.
|
||||
*/
|
||||
virtual const char* what() const noexcept;
|
||||
|
||||
private:
|
||||
std::string msg_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
39
external/odbccpp/src/odbc/Forwards.h
vendored
Normal file
39
external/odbccpp/src/odbc/Forwards.h
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef ODBC_FORWARDS_H_INCLUDED
|
||||
#define ODBC_FORWARDS_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/RefCounted.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
class Connection;
|
||||
class DatabaseMetaData;
|
||||
class DatabaseMetaDataBase;
|
||||
class DatabaseMetaDataUnicode;
|
||||
class Environment;
|
||||
class Exception;
|
||||
class ParameterMetaData;
|
||||
class PreparedStatement;
|
||||
class ResultSet;
|
||||
class ResultSetMetaData;
|
||||
class ResultSetMetaDataBase;
|
||||
class ResultSetMetaDataUnicode;
|
||||
class StatementBase;
|
||||
class Statement;
|
||||
class ValueBuffer;
|
||||
//------------------------------------------------------------------------------
|
||||
typedef Reference<Connection> ConnectionRef;
|
||||
typedef Reference<DatabaseMetaData> DatabaseMetaDataRef;
|
||||
typedef Reference<DatabaseMetaDataUnicode> DatabaseMetaDataUnicodeRef;
|
||||
typedef Reference<Environment> EnvironmentRef;
|
||||
typedef Reference<ParameterMetaData> ParameterMetaDataRef;
|
||||
typedef Reference<PreparedStatement> PreparedStatementRef;
|
||||
typedef Reference<ResultSet> ResultSetRef;
|
||||
typedef Reference<ResultSetMetaData> ResultSetMetaDataRef;
|
||||
typedef Reference<ResultSetMetaDataUnicode> ResultSetMetaDataUnicodeRef;
|
||||
typedef Reference<StatementBase> StatementBaseRef;
|
||||
typedef Reference<Statement> StatementRef;
|
||||
typedef Reference<ValueBuffer> ValueBufferRef;
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
76
external/odbccpp/src/odbc/ParameterMetaData.cpp
vendored
Normal file
76
external/odbccpp/src/odbc/ParameterMetaData.cpp
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ParameterMetaData.h>
|
||||
#include <odbc/PreparedStatement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
ParameterMetaData::ParameterMetaData(PreparedStatement* ps)
|
||||
: ps_(ps, true)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short ParameterMetaData::getParameterCount()
|
||||
{
|
||||
SQLSMALLINT ret;
|
||||
EXEC_STMT(SQLNumParams, ps_->hstmt_, &ret);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
short ParameterMetaData::getParameterType(unsigned short paramIndex)
|
||||
{
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN parameterSize;
|
||||
SQLSMALLINT decimalDigits;
|
||||
SQLSMALLINT nullable;
|
||||
EXEC_STMT(SQLDescribeParam, ps_->hstmt_, paramIndex, &dataType,
|
||||
¶meterSize, &decimalDigits, &nullable);
|
||||
return dataType;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ParameterMetaData::getParameterSize(unsigned short paramIndex)
|
||||
{
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN parameterSize;
|
||||
SQLSMALLINT decimalDigits;
|
||||
SQLSMALLINT nullable;
|
||||
EXEC_STMT(SQLDescribeParam, ps_->hstmt_, paramIndex, &dataType,
|
||||
¶meterSize, &decimalDigits, &nullable);
|
||||
return (size_t)parameterSize;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short ParameterMetaData::getPrecision(unsigned short paramIndex)
|
||||
{
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN parameterSize;
|
||||
SQLSMALLINT decimalDigits;
|
||||
SQLSMALLINT nullable;
|
||||
EXEC_STMT(SQLDescribeParam, ps_->hstmt_, paramIndex, &dataType,
|
||||
¶meterSize, &decimalDigits, &nullable);
|
||||
return (unsigned short)parameterSize;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short ParameterMetaData::getScale(unsigned short paramIndex)
|
||||
{
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN parameterSize;
|
||||
SQLSMALLINT decimalDigits;
|
||||
SQLSMALLINT nullable;
|
||||
EXEC_STMT(SQLDescribeParam, ps_->hstmt_, paramIndex, &dataType,
|
||||
¶meterSize, &decimalDigits, &nullable);
|
||||
return (decimalDigits >= 0) ? decimalDigits : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ParameterMetaData::isNullable(unsigned short paramIndex)
|
||||
{
|
||||
SQLSMALLINT dataType;
|
||||
SQLULEN parameterSize;
|
||||
SQLSMALLINT decimalDigits;
|
||||
SQLSMALLINT nullable;
|
||||
EXEC_STMT(SQLDescribeParam, ps_->hstmt_, paramIndex, &dataType,
|
||||
¶meterSize, &decimalDigits, &nullable);
|
||||
return nullable == SQL_NULLABLE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
82
external/odbccpp/src/odbc/ParameterMetaData.h
vendored
Normal file
82
external/odbccpp/src/odbc/ParameterMetaData.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef ODBC_PARAMETERMETADATA_H_INCLUDED
|
||||
#define ODBC_PARAMETERMETADATA_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Metadata on parameters in a prepared statement.
|
||||
*/
|
||||
class ODBC_EXPORT ParameterMetaData : public RefCounted
|
||||
{
|
||||
friend class PreparedStatement;
|
||||
|
||||
private:
|
||||
ParameterMetaData(PreparedStatement* ps);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves the number of parameters in the associated PreparedStatement
|
||||
* object.
|
||||
*
|
||||
* @return The number of parameters.
|
||||
*/
|
||||
unsigned short getParameterCount();
|
||||
|
||||
/**
|
||||
* Retrieves the SQL type of the specified parameter.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @return The SQL type.
|
||||
*/
|
||||
short getParameterType(unsigned short paramIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the size of the column or expression measured in characters.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @return The size in characters.
|
||||
*/
|
||||
std::size_t getParameterSize(unsigned short paramIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the precision of the type assigned to the parameter.
|
||||
*
|
||||
* For numeric data, the returned value denotes the maximum number of digits
|
||||
* in a number. For character data, this is the length of a character
|
||||
* sequence. For date, time and timestamp types, this is the length of their
|
||||
* string representation.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @return The precision value.
|
||||
*/
|
||||
unsigned short getPrecision(unsigned short paramIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the scale of numeric data, which is the maximum number of
|
||||
* decimal digits.
|
||||
*
|
||||
* The function returns 0 for non-numeric data.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @return The scale value.
|
||||
*/
|
||||
unsigned short getScale(unsigned short paramIndex);
|
||||
|
||||
/**
|
||||
* Determines whether the corresponding column accepts null values or not.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @return True if the parameter accepts nulls, false otherwise.
|
||||
*/
|
||||
bool isNullable(unsigned short paramIndex);
|
||||
|
||||
private:
|
||||
PreparedStatementRef ps_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
405
external/odbccpp/src/odbc/PreparedStatement.cpp
vendored
Normal file
405
external/odbccpp/src/odbc/PreparedStatement.cpp
vendored
Normal file
@ -0,0 +1,405 @@
|
||||
#include <string>
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ParameterMetaData.h>
|
||||
#include <odbc/PreparedStatement.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
#include <odbc/ResultSetMetaData.h>
|
||||
#include <odbc/ResultSetMetaDataUnicode.h>
|
||||
#include <odbc/internal/Batch.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
#include <odbc/internal/ParameterData.h>
|
||||
#include <odbc/internal/TypeInfo.h>
|
||||
#include <odbc/internal/UtilInternal.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
PreparedStatement::PreparedStatement(Connection* parent) : StatementBase(parent)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
PreparedStatement::~PreparedStatement()
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setHandleAndQuery(void* hstmt, const char* query)
|
||||
{
|
||||
hstmt_ = hstmt;
|
||||
|
||||
EXEC_STMT(SQLPrepareA, hstmt, (SQLCHAR*)query, SQL_NTS);
|
||||
|
||||
SQLSMALLINT count;
|
||||
EXEC_STMT(SQLNumParams, hstmt_, &count);
|
||||
parameterData_.resize(count);
|
||||
|
||||
batch_.reset(new Batch(parameterData_));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setHandleAndQuery(void* hstmt, const char16_t* query)
|
||||
{
|
||||
hstmt_ = hstmt;
|
||||
|
||||
EXEC_STMT(SQLPrepareW, hstmt, (SQLWCHAR*)query, SQL_NTS);
|
||||
|
||||
SQLSMALLINT count;
|
||||
EXEC_STMT(SQLNumParams, hstmt_, &count);
|
||||
parameterData_.resize(count);
|
||||
|
||||
batch_.reset(new Batch(parameterData_));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ParameterMetaDataRef PreparedStatement::getParameterMetaData()
|
||||
{
|
||||
ParameterMetaDataRef ret(new ParameterMetaData(this));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setBoolean(unsigned short paramIndex,
|
||||
const Boolean& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setByte(unsigned short paramIndex, const Byte& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setUByte(unsigned short paramIndex, const UByte& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setShort(unsigned short paramIndex, const Short& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setUShort(unsigned short paramIndex,
|
||||
const UShort& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setInt(unsigned short paramIndex, const Int& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setUInt(unsigned short paramIndex, const UInt& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setLong(unsigned short paramIndex, const Long& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setULong(unsigned short paramIndex, const ULong& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setDecimal(unsigned short paramIndex,
|
||||
const Decimal& value)
|
||||
{
|
||||
if (value.isNull())
|
||||
{
|
||||
parameterData_[paramIndex - 1].setNull(TypeToOdbc<decimal>::VALUETYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SQL_NUMERIC_STRUCT ns;
|
||||
UtilInternal::decimalToNumeric(*value, ns);
|
||||
ParameterData& pd = parameterData_[paramIndex - 1];
|
||||
pd.setValue(TypeToOdbc<decimal>::VALUETYPE, &ns, sizeof(ns));
|
||||
pd.setColumnSize(ns.precision);
|
||||
pd.setDecimalDigits(ns.scale);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setFloat(unsigned short paramIndex, const Float& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setDouble(unsigned short paramIndex,
|
||||
const Double& value)
|
||||
{
|
||||
setFixedSizeData(paramIndex, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setString(unsigned short paramIndex,
|
||||
const String& value)
|
||||
{
|
||||
if (value.isNull())
|
||||
setCString(paramIndex, nullptr, 0);
|
||||
else
|
||||
setCString(paramIndex, value->c_str(), value->length());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setCString(unsigned short paramIndex, const char* s)
|
||||
{
|
||||
if (s == nullptr)
|
||||
setCString(paramIndex, nullptr, 0);
|
||||
else
|
||||
setCString(paramIndex, s, char_traits<char>::length(s));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setCString(unsigned short paramIndex, const char* s,
|
||||
std::size_t len)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
ParameterData& pd = parameterData_[paramIndex - 1];
|
||||
if (s == nullptr)
|
||||
{
|
||||
pd.setNull(SQL_C_CHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
pd.setValue(SQL_C_CHAR, s, len);
|
||||
pd.setColumnSize(len);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setNString(unsigned short paramIndex,
|
||||
const NString& value)
|
||||
{
|
||||
if (value.isNull())
|
||||
setNCString(paramIndex, nullptr, 0);
|
||||
else
|
||||
setNCString(paramIndex, value->c_str(), value->length());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setNCString(unsigned short paramIndex,
|
||||
const char16_t* s)
|
||||
{
|
||||
if (s == nullptr)
|
||||
setNCString(paramIndex, nullptr, 0);
|
||||
else
|
||||
setNCString(paramIndex, s, char_traits<char16_t>::length(s));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setNCString(unsigned short paramIndex,
|
||||
const char16_t* s, std::size_t len)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
ParameterData& pd = parameterData_[paramIndex - 1];
|
||||
if (s == nullptr)
|
||||
{
|
||||
pd.setNull(SQL_C_WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
pd.setValue(SQL_C_WCHAR, s, len*sizeof(char16_t));
|
||||
pd.setColumnSize(len);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setBinary(unsigned short paramIndex,
|
||||
const Binary& value)
|
||||
{
|
||||
if (value.isNull())
|
||||
setBytes(paramIndex, nullptr, 0);
|
||||
else
|
||||
setBytes(paramIndex, value->data(), value->size());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setBytes(unsigned short paramIndex, const void* data,
|
||||
size_t size)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
ParameterData& pd = parameterData_[paramIndex - 1];
|
||||
if (data == nullptr)
|
||||
{
|
||||
pd.setNull(SQL_C_BINARY);
|
||||
}
|
||||
else
|
||||
{
|
||||
pd.setValue(SQL_C_BINARY, data, size);
|
||||
pd.setColumnSize(size);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setDate(unsigned short paramIndex, const Date& value)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
if (value.isNull())
|
||||
{
|
||||
parameterData_[paramIndex - 1].setNull(TypeToOdbc<date>::VALUETYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SQL_DATE_STRUCT ds = {
|
||||
(SQLSMALLINT)value->year(),
|
||||
(SQLUSMALLINT)value->month(),
|
||||
(SQLUSMALLINT)value->day()
|
||||
};
|
||||
parameterData_[paramIndex - 1].setValue(
|
||||
TypeToOdbc<date>::VALUETYPE, &ds, sizeof(ds));
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setTime(unsigned short paramIndex, const Time& value)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
if (value.isNull())
|
||||
{
|
||||
parameterData_[paramIndex - 1].setNull(TypeToOdbc<time>::VALUETYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SQL_TIME_STRUCT ts = {
|
||||
(SQLUSMALLINT)value->hour(),
|
||||
(SQLUSMALLINT)value->minute(),
|
||||
(SQLUSMALLINT)value->second()
|
||||
};
|
||||
parameterData_[paramIndex - 1].setValue(
|
||||
TypeToOdbc<time>::VALUETYPE, &ts, sizeof(ts));
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::setTimestamp(unsigned short paramIndex,
|
||||
const Timestamp& value)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
if (value.isNull())
|
||||
{
|
||||
parameterData_[paramIndex - 1].setNull(
|
||||
TypeToOdbc<timestamp>::VALUETYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SQL_TIMESTAMP_STRUCT tss = {
|
||||
(SQLSMALLINT)value->year(),
|
||||
(SQLUSMALLINT)value->month(),
|
||||
(SQLUSMALLINT)value->day(),
|
||||
(SQLUSMALLINT)value->hour(),
|
||||
(SQLUSMALLINT)value->minute(),
|
||||
(SQLUSMALLINT)value->second(),
|
||||
(SQLUINTEGER)value->milliseconds() * 1000000
|
||||
};
|
||||
parameterData_[paramIndex - 1].setValue(
|
||||
TypeToOdbc<timestamp>::VALUETYPE, &tss, sizeof(tss));
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::clearParameters()
|
||||
{
|
||||
for (ParameterData& pd : parameterData_)
|
||||
pd.clear();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaDataRef PreparedStatement::getMetaData()
|
||||
{
|
||||
ResultSetMetaDataRef ret(new ResultSetMetaData(this));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaDataUnicodeRef PreparedStatement::getMetaDataUnicode()
|
||||
{
|
||||
ResultSetMetaDataUnicodeRef ret(new ResultSetMetaDataUnicode(this));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef PreparedStatement::executeQuery()
|
||||
{
|
||||
ResultSetRef ret(new ResultSet(this));
|
||||
EXEC_STMT(SQLFreeStmt, hstmt_, SQL_CLOSE);
|
||||
bindParameters();
|
||||
EXEC_STMT(SQLExecute, hstmt_);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t PreparedStatement::executeUpdate()
|
||||
{
|
||||
EXEC_STMT(SQLFreeStmt, hstmt_, SQL_CLOSE);
|
||||
bindParameters();
|
||||
SQLRETURN rc = SQLExecute(hstmt_);
|
||||
if (rc == SQL_NO_DATA)
|
||||
return 0;
|
||||
Exception::checkForError(rc, SQL_HANDLE_STMT, hstmt_);
|
||||
SQLLEN numRows;
|
||||
EXEC_STMT(SQLRowCount, hstmt_, &numRows);
|
||||
return numRows;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::addBatch()
|
||||
{
|
||||
verifyAllParametersValid();
|
||||
batch_->addRow();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::executeBatch()
|
||||
{
|
||||
batch_->execute(hstmt_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::clearBatch()
|
||||
{
|
||||
batch_->clear();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t PreparedStatement::getBatchDataSize() const
|
||||
{
|
||||
return batch_->getDataSize();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::bindParameters()
|
||||
{
|
||||
verifyAllParametersValid();
|
||||
for (size_t i = 1; i <= parameterData_.size(); ++i)
|
||||
{
|
||||
const ParameterData& pd = parameterData_[i - 1];
|
||||
if (pd.isNull())
|
||||
{
|
||||
EXEC_STMT(SQLBindParameter, hstmt_, (SQLUSMALLINT)i,
|
||||
SQL_PARAM_INPUT, pd.getValueType(),
|
||||
TypeInfo::getParamTypeForValueType(pd.getValueType()),
|
||||
0, 0, 0, 0, (SQLLEN*)pd.getLenIndPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
EXEC_STMT(SQLBindParameter, hstmt_, (SQLUSMALLINT)i,
|
||||
SQL_PARAM_INPUT, pd.getValueType(),
|
||||
TypeInfo::getParamTypeForValueType(pd.getValueType()),
|
||||
pd.getColumnSize(), pd.getDecimalDigits(),
|
||||
(SQLPOINTER)pd.getData(), pd.getSize(),
|
||||
(SQLLEN*)pd.getLenIndPtr());
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
void PreparedStatement::setFixedSizeData(
|
||||
unsigned short paramIndex, const Nullable<T>& value)
|
||||
{
|
||||
verifyValidParamIndex(paramIndex);
|
||||
if (value.isNull())
|
||||
parameterData_[paramIndex - 1].setNull(TypeToOdbc<T>::VALUETYPE);
|
||||
else
|
||||
parameterData_[paramIndex - 1].setValue(
|
||||
TypeToOdbc<T>::VALUETYPE, &(*value), sizeof(T));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::verifyValidParamIndex(unsigned short paramIndex) const
|
||||
{
|
||||
ODBC_CHECK(
|
||||
(paramIndex >= 1) && ((size_t)paramIndex <= parameterData_.size()),
|
||||
"Invalid parameter index (" << paramIndex << ")");
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void PreparedStatement::verifyAllParametersValid() const
|
||||
{
|
||||
for (size_t i = 0; i < parameterData_.size(); ++i)
|
||||
{
|
||||
ODBC_CHECK(parameterData_[i].isInitialized(),
|
||||
"Parameter " << (i+1) << " has not been set");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
298
external/odbccpp/src/odbc/PreparedStatement.h
vendored
Normal file
298
external/odbccpp/src/odbc/PreparedStatement.h
vendored
Normal file
@ -0,0 +1,298 @@
|
||||
#ifndef ODBC_PREPAREDSTATEMENT_H_INCLUDED
|
||||
#define ODBC_PREPAREDSTATEMENT_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/StatementBase.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
class Batch;
|
||||
class ParameterData;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Represents a precompiled SQL statement.
|
||||
*/
|
||||
class ODBC_EXPORT PreparedStatement : public StatementBase
|
||||
{
|
||||
friend class Connection;
|
||||
friend class ParameterMetaData;
|
||||
|
||||
private:
|
||||
PreparedStatement(Connection* parent);
|
||||
|
||||
public:
|
||||
~PreparedStatement();
|
||||
|
||||
private:
|
||||
void setHandleAndQuery(void* hstmt, const char* query);
|
||||
|
||||
void setHandleAndQuery(void* hstmt, const char16_t* query);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Retrieves the number, types and properties of the parameters.
|
||||
*
|
||||
* @return Returns a ParameterMetaData object that contains information
|
||||
* about the number, types and properties for each parameter.
|
||||
*/
|
||||
ParameterMetaDataRef getParameterMetaData();
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given boolean value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setBoolean(unsigned short paramIndex, const Boolean& value);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given signed byte value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setByte(unsigned short paramIndex, const Byte& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given unsigned byte value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setUByte(unsigned short paramIndex, const UByte& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given signed short integer value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setShort(unsigned short paramIndex, const Short& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given unsigned short integer value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setUShort(unsigned short paramIndex, const UShort& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given signed integer value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setInt(unsigned short paramIndex, const Int& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given unsigned integer value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setUInt(unsigned short paramIndex, const UInt& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given signed long integer value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setLong(unsigned short paramIndex, const Long& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given unsigned long integer value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setULong(unsigned short paramIndex, const ULong& value);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given decimal value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setDecimal(unsigned short paramIndex, const Decimal& value);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given float value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setFloat(unsigned short paramIndex, const Float& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given double value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setDouble(unsigned short paramIndex, const Double& value);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given string value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setString(unsigned short paramIndex, const String& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given null-terminated character
|
||||
* sequence (C-String).
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param s The null-terminated character sequence.
|
||||
*/
|
||||
void setCString(unsigned short paramIndex, const char* s);
|
||||
/**
|
||||
* Sets the specified parameter to the given character sequence of the
|
||||
* desired length.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param s The sequence of characters.
|
||||
* @param len The length of the sequence.
|
||||
*/
|
||||
void setCString(unsigned short paramIndex, const char* s, std::size_t len);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given string with 16-bit characters.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setNString(unsigned short paramIndex, const NString& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given null-terminated 16-bit
|
||||
* character sequence (C-String).
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param s The null-terminated character sequence.
|
||||
*/
|
||||
void setNCString(unsigned short paramIndex, const char16_t* s);
|
||||
/**
|
||||
* Sets the specified parameter to the given 16-bit character sequence of
|
||||
* the desired length.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param s The sequence of characters.
|
||||
* @param len The length of the sequence.
|
||||
*/
|
||||
void setNCString(unsigned short paramIndex, const char16_t* s,
|
||||
std::size_t len);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given Binary object.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setBinary(unsigned short paramIndex, const Binary& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given byte sequence of the desired
|
||||
* length.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param data The sequence of bytes.
|
||||
* @param size The length of the sequence.
|
||||
*/
|
||||
void setBytes(unsigned short paramIndex, const void* data,
|
||||
std::size_t size);
|
||||
|
||||
/**
|
||||
* Sets the specified parameter to the given Date value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setDate(unsigned short paramIndex, const Date& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given Time value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setTime(unsigned short paramIndex, const Time& value);
|
||||
/**
|
||||
* Sets the specified parameter to the given Timestamp value.
|
||||
*
|
||||
* @param paramIndex The parameter index starting from 1.
|
||||
* @param value The parameter value.
|
||||
*/
|
||||
void setTimestamp(unsigned short paramIndex, const Timestamp& value);
|
||||
|
||||
/**
|
||||
* Clears the parameter values.
|
||||
*/
|
||||
void clearParameters();
|
||||
|
||||
/**
|
||||
* Retrieves a ResultSetMetaData object that contains information about a
|
||||
* ResultSet object returned by executeQuery method.
|
||||
*
|
||||
* @return Returns a ResultSetMetaData object.
|
||||
*/
|
||||
ResultSetMetaDataRef getMetaData();
|
||||
|
||||
/**
|
||||
* Retrieves a ResultSetMetaDataUnicode object that contains information
|
||||
* about a ResultSet object returned by executeQuery method.
|
||||
*
|
||||
* @return Returns a ResultSetMetaDataUnicode object.
|
||||
*/
|
||||
ResultSetMetaDataUnicodeRef getMetaDataUnicode();
|
||||
|
||||
/**
|
||||
* Executes the SQL query of this PreparedStatement object and returns a
|
||||
* ResultSet object.
|
||||
*
|
||||
* @return Returns a ResultSet object that contains the data produced
|
||||
* by the given SQL statement.
|
||||
*/
|
||||
ResultSetRef executeQuery();
|
||||
|
||||
/**
|
||||
* Executes the SQL query of this PreparedStatement object and returns
|
||||
* the number of rows affected by an UPDATE, INSERT, or DELETE statement.
|
||||
*
|
||||
* @return Returns the number of rows affected by an UPDATE, INSERT, or
|
||||
* DELETE statement.
|
||||
*/
|
||||
std::size_t executeUpdate();
|
||||
|
||||
/**
|
||||
* Add the current set of parameters to the batch of commands.
|
||||
*/
|
||||
void addBatch();
|
||||
/**
|
||||
* Executes the batch of commands.
|
||||
*/
|
||||
void executeBatch();
|
||||
/**
|
||||
* Clears the batch of commands.
|
||||
*/
|
||||
void clearBatch();
|
||||
|
||||
/**
|
||||
* Retrieves the number of bytes required by the batch of commands.
|
||||
*
|
||||
* @return Returns the number of bytes required by the batch of commands.
|
||||
*/
|
||||
std::size_t getBatchDataSize() const;
|
||||
|
||||
private:
|
||||
void bindParameters();
|
||||
|
||||
template<typename T>
|
||||
void setFixedSizeData(unsigned short paramIndex, const Nullable<T>& value);
|
||||
|
||||
void verifyValidParamIndex(unsigned short paramIndex) const;
|
||||
void verifyAllParametersValid() const;
|
||||
|
||||
private:
|
||||
std::vector<ParameterData> parameterData_;
|
||||
std::unique_ptr<Batch> batch_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
28
external/odbccpp/src/odbc/RefCounted.cpp
vendored
Normal file
28
external/odbccpp/src/odbc/RefCounted.cpp
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
#include <odbc/RefCounted.h>
|
||||
#include <cstddef>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
RefCounted::RefCounted() : refcount_(1)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
RefCounted::~RefCounted()
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void RefCounted::incRef() const
|
||||
{
|
||||
refcount_.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void RefCounted::decRef() const
|
||||
{
|
||||
if (refcount_.fetch_sub(1, std::memory_order_release) == 1)
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
219
external/odbccpp/src/odbc/RefCounted.h
vendored
Normal file
219
external/odbccpp/src/odbc/RefCounted.h
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
#ifndef ODBC_REFCOUNTED_H_INCLUDED
|
||||
#define ODBC_REFCOUNTED_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <atomic>
|
||||
#include <odbc/Config.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
class Reference;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Base class for reference-counted objects.
|
||||
*
|
||||
* Reference count management is done by the Reference class.
|
||||
*/
|
||||
class ODBC_EXPORT RefCounted
|
||||
{
|
||||
template<typename T>
|
||||
friend class Reference;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor initializing the reference-count to 1.
|
||||
*/
|
||||
RefCounted();
|
||||
RefCounted(const RefCounted& other) = delete;
|
||||
RefCounted& operator=(const RefCounted& other) = delete;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~RefCounted();
|
||||
|
||||
private:
|
||||
void incRef() const;
|
||||
void decRef() const;
|
||||
|
||||
private:
|
||||
mutable std::atomic_ptrdiff_t refcount_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Manager for reference-counted objects.
|
||||
*
|
||||
* Takes care of properly incrementing and decrementing reference counts of the
|
||||
* managed object.
|
||||
*
|
||||
* @tparam T Type offering methods incRef() and decRef().
|
||||
*/
|
||||
template<typename T>
|
||||
class Reference
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a NULL reference.
|
||||
*/
|
||||
Reference() : ptr_(0) {}
|
||||
|
||||
/**
|
||||
* Constructs a reference to a given reference-counted object.
|
||||
*
|
||||
* @param ptr A pointer to a reference-counted object.
|
||||
* @param incref Increases the reference-count of the passed object if set
|
||||
* to true.
|
||||
*/
|
||||
Reference(T* ptr, bool incref = false) : ptr_(ptr)
|
||||
{
|
||||
if (ptr && incref)
|
||||
ptr->incRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructs a reference.
|
||||
*
|
||||
* The reference-count of the managed object is increased by 1.
|
||||
*
|
||||
* @param other Another reference.
|
||||
*/
|
||||
Reference(const Reference<T>& other) { set_(other.ptr_); }
|
||||
|
||||
/**
|
||||
* Destructor decreasing the reference-count of the managed object.
|
||||
*/
|
||||
~Reference() { free_(); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Assigns another reference to this reference.
|
||||
*
|
||||
* The reference-count of the currently managed object is decremented and
|
||||
* the reference-count of the newly managed object is incremented.
|
||||
*
|
||||
* @param other Another reference.
|
||||
*/
|
||||
Reference& operator=(const Reference<T>& other)
|
||||
{
|
||||
reset_(other.ptr_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this reference manages an object.
|
||||
*
|
||||
* @return Returns true if this reference manages an object, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool isNull() const { return ptr_ == 0; }
|
||||
|
||||
/**
|
||||
* Returns a reference to the managed object.
|
||||
*
|
||||
* @return Returns a reference to the managed object.
|
||||
*/
|
||||
T& operator*() { return *ptr_; }
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the managed object.
|
||||
*
|
||||
* @return Returns a constant reference to the managed object.
|
||||
*/
|
||||
const T& operator*() const { return *ptr_; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the managed object.
|
||||
*
|
||||
* @return Returns a pointer to the managed object.
|
||||
*/
|
||||
T* operator->() { return ptr_; }
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the managed object.
|
||||
*
|
||||
* @return Returns a constant pointer to the managed object.
|
||||
*/
|
||||
const T* operator->() const { return ptr_; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the managed object.
|
||||
*
|
||||
* @return Returns a pointer to the managed object.
|
||||
*/
|
||||
T* get() { return ptr_; }
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the managed object.
|
||||
*
|
||||
* @return Returns a constant pointer to the managed object.
|
||||
*/
|
||||
const T* get() const { return ptr_; }
|
||||
|
||||
/**
|
||||
* Releases the currently managed object.
|
||||
*
|
||||
* Decreases the reference-count of the managed object and does not
|
||||
* reference it anymore.
|
||||
*/
|
||||
void reset() { reset_(0); }
|
||||
|
||||
/**
|
||||
* Releases the currently managed object and manages a new object.
|
||||
*
|
||||
* Decreases the reference-count of the managed object and increases the
|
||||
* reference-count of the newly managed object.
|
||||
*
|
||||
* @param newPtr The newly managed object.
|
||||
*/
|
||||
void reset(T* newPtr) { reset_(newPtr); }
|
||||
|
||||
/**
|
||||
* Checks whether the managed object is less than the object managed by
|
||||
* another reference.
|
||||
*
|
||||
* NULL references are never considered less than another reference.
|
||||
*
|
||||
* @param other Another reference.
|
||||
* @return Returns true if the managed object is less than the object
|
||||
* manages by the other reference, false otherwise.
|
||||
*/
|
||||
bool operator<(const Reference<T>& other) const
|
||||
{
|
||||
if (ptr_)
|
||||
{
|
||||
if (other.ptr_)
|
||||
return *ptr_ < *other.ptr_;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void reset_(T* newPtr)
|
||||
{
|
||||
if (newPtr != ptr_)
|
||||
{
|
||||
free_();
|
||||
set_(newPtr);
|
||||
}
|
||||
}
|
||||
void free_()
|
||||
{
|
||||
if (ptr_)
|
||||
ptr_->decRef();
|
||||
}
|
||||
void set_(T* ptr)
|
||||
{
|
||||
ptr_ = ptr;
|
||||
if (ptr_)
|
||||
ptr_->incRef();
|
||||
}
|
||||
|
||||
private:
|
||||
T* ptr_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
400
external/odbccpp/src/odbc/ResultSet.cpp
vendored
Normal file
400
external/odbccpp/src/odbc/ResultSet.cpp
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
#include <odbc/ResultSetMetaData.h>
|
||||
#include <odbc/ResultSetMetaDataUnicode.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
#include <odbc/internal/UtilInternal.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSet::ResultSet(StatementBase* parent)
|
||||
: parent_(parent, true)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSet::~ResultSet()
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSet::next()
|
||||
{
|
||||
SQLRETURN rc = SQLFetch(parent_->hstmt_);
|
||||
if (rc == SQL_NO_DATA)
|
||||
return false;
|
||||
Exception::checkForError(rc, SQL_HANDLE_STMT, parent_->hstmt_);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ResultSet::close()
|
||||
{
|
||||
EXEC_STMT(SQLFreeStmt, parent_->hstmt_, SQL_CLOSE);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaDataRef ResultSet::getMetaData()
|
||||
{
|
||||
ResultSetMetaDataRef ret(new ResultSetMetaData(parent_.get()));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaDataUnicodeRef ResultSet::getMetaDataUnicode()
|
||||
{
|
||||
ResultSetMetaDataUnicodeRef ret(
|
||||
new ResultSetMetaDataUnicode(parent_.get()));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Boolean ResultSet::getBoolean(unsigned short columnIndex)
|
||||
{
|
||||
bool val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_BIT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Boolean();
|
||||
return Boolean(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Byte ResultSet::getByte(unsigned short columnIndex)
|
||||
{
|
||||
int8_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_STINYINT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Byte();
|
||||
return Byte(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
UByte ResultSet::getUByte(unsigned short columnIndex)
|
||||
{
|
||||
uint8_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_UTINYINT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return UByte();
|
||||
return UByte(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Short ResultSet::getShort(unsigned short columnIndex)
|
||||
{
|
||||
int16_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_SSHORT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Short();
|
||||
return Short(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
UShort ResultSet::getUShort(unsigned short columnIndex)
|
||||
{
|
||||
uint16_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_USHORT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return UShort();
|
||||
return UShort(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Int ResultSet::getInt(unsigned short columnIndex)
|
||||
{
|
||||
int32_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_SLONG, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Int();
|
||||
return Int(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
UInt ResultSet::getUInt(unsigned short columnIndex)
|
||||
{
|
||||
uint32_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_ULONG, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return UInt();
|
||||
return UInt(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Long ResultSet::getLong(unsigned short columnIndex)
|
||||
{
|
||||
int64_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_SBIGINT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Long();
|
||||
return Long(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ULong ResultSet::getULong(unsigned short columnIndex)
|
||||
{
|
||||
uint64_t val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_UBIGINT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return ULong();
|
||||
return ULong(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Decimal ResultSet::getDecimal(unsigned short columnIndex)
|
||||
{
|
||||
SQL_NUMERIC_STRUCT num;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_NUMERIC, &num,
|
||||
sizeof(num), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Decimal();
|
||||
char str[64];
|
||||
odbc::UtilInternal::numericToString(num, str);
|
||||
return Decimal(decimal(str, num.precision, num.scale));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Float ResultSet::getFloat(unsigned short columnIndex)
|
||||
{
|
||||
float val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_FLOAT, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Float();
|
||||
return Float(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Double ResultSet::getDouble(unsigned short columnIndex)
|
||||
{
|
||||
double val;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_DOUBLE, &val,
|
||||
sizeof(val), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Double();
|
||||
return Double(val);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Date ResultSet::getDate(unsigned short columnIndex)
|
||||
{
|
||||
DATE_STRUCT ds;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_TYPE_DATE, &ds,
|
||||
sizeof(ds), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Date();
|
||||
return makeNullable<date>(ds.year, ds.month, ds.day);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Time ResultSet::getTime(unsigned short columnIndex)
|
||||
{
|
||||
TIME_STRUCT ts;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_TYPE_TIME, &ts,
|
||||
sizeof(ts), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Time();
|
||||
return makeNullable<time>(ts.hour, ts.minute, ts.second);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Timestamp ResultSet::getTimestamp(unsigned short columnIndex)
|
||||
{
|
||||
TIMESTAMP_STRUCT ts;
|
||||
SQLLEN ind;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex, SQL_C_TYPE_TIMESTAMP,
|
||||
&ts, sizeof(ts), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Timestamp();
|
||||
return makeNullable<timestamp>(ts.year, ts.month, ts.day, ts.hour,
|
||||
ts.minute, ts.second, ts.fraction / 1000000);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
String ResultSet::getString(unsigned short columnIndex)
|
||||
{
|
||||
SQLRETURN rc;
|
||||
SQLLEN ind;
|
||||
char dummy;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_CHAR, &dummy, sizeof(dummy), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return String();
|
||||
if (ind == 0)
|
||||
return String("");
|
||||
|
||||
string ret;
|
||||
if (ind == SQL_NO_TOTAL)
|
||||
{
|
||||
char buffer[1024];
|
||||
for (;;)
|
||||
{
|
||||
rc = SQLGetData(parent_->hstmt_, columnIndex, SQL_C_CHAR,
|
||||
buffer, sizeof(buffer), &ind);
|
||||
Exception::checkForError(rc, SQL_HANDLE_STMT, parent_->hstmt_);
|
||||
size_t len = (ind == SQL_NO_TOTAL)
|
||||
? sizeof(buffer) - 1
|
||||
: min<size_t>(sizeof(buffer) - 1, ind);
|
||||
ret.append(buffer, len);
|
||||
if (rc == SQL_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.resize(ind + 1);
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_CHAR, &ret[0], ret.size(), &ind);
|
||||
ret.resize(ind);
|
||||
}
|
||||
return String(move(ret));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
NString ResultSet::getNString(unsigned short columnIndex)
|
||||
{
|
||||
SQLRETURN rc;
|
||||
SQLLEN ind;
|
||||
char16_t dummy;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_WCHAR, &dummy, sizeof(dummy), &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return NString();
|
||||
if (ind == 0)
|
||||
return NString(u"");
|
||||
|
||||
u16string ret;
|
||||
if (ind == SQL_NO_TOTAL)
|
||||
{
|
||||
char16_t buffer[1024];
|
||||
for (;;)
|
||||
{
|
||||
rc = SQLGetData(parent_->hstmt_, columnIndex, SQL_C_WCHAR,
|
||||
buffer, sizeof(buffer), &ind);
|
||||
Exception::checkForError(rc, SQL_HANDLE_STMT, parent_->hstmt_);
|
||||
size_t len = (ind == SQL_NO_TOTAL)
|
||||
? sizeof(buffer)/sizeof(char16_t) - 1
|
||||
: min<size_t>(sizeof(buffer)/sizeof(char16_t) - 1, ind/2);
|
||||
ret.append(buffer, len);
|
||||
if (rc == SQL_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.resize(ind/2 + 1);
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_WCHAR, &ret[0], ret.size()*sizeof(char16_t), &ind);
|
||||
ret.resize(ind/2);
|
||||
}
|
||||
return NString(move(ret));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Binary ResultSet::getBinary(unsigned short columnIndex)
|
||||
{
|
||||
SQLRETURN rc;
|
||||
SQLLEN ind;
|
||||
char dummy;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_BINARY, &dummy, 0, &ind);
|
||||
if (ind == SQL_NULL_DATA)
|
||||
return Binary();
|
||||
if (ind == 0)
|
||||
return Binary(vector<char>());
|
||||
|
||||
vector<char> ret;
|
||||
if (ind == SQL_NO_TOTAL)
|
||||
{
|
||||
char buffer[1024];
|
||||
for (;;)
|
||||
{
|
||||
rc = SQLGetData(parent_->hstmt_, columnIndex, SQL_C_BINARY,
|
||||
buffer, sizeof(buffer), &ind);
|
||||
Exception::checkForError(rc, SQL_HANDLE_STMT, parent_->hstmt_);
|
||||
if (ind == SQL_NO_TOTAL)
|
||||
ret.insert(ret.end(), buffer, buffer + sizeof(buffer));
|
||||
else
|
||||
ret.insert(ret.end(), buffer, buffer + ind);
|
||||
if (rc == SQL_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.resize(ind);
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_BINARY, ret.data(), ret.size(), &ind);
|
||||
}
|
||||
return Binary(move(ret));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static size_t convertLength(SQLLEN ind)
|
||||
{
|
||||
switch (ind)
|
||||
{
|
||||
case SQL_NULL_DATA:
|
||||
return ResultSet::NULL_DATA;
|
||||
case SQL_NO_TOTAL:
|
||||
return ResultSet::UNKNOWN_LENGTH;
|
||||
}
|
||||
return ind;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ResultSet::getBinaryLength(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ind;
|
||||
char dummy;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_BINARY, &dummy, 0, &ind);
|
||||
return convertLength(ind);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ResultSet::getBinaryData(unsigned short columnIndex, void* data,
|
||||
size_t size)
|
||||
{
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_BINARY, (SQLPOINTER)data, size, NULL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ResultSet::getStringLength(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ind;
|
||||
char dummy;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_CHAR, &dummy, sizeof(dummy), &ind);
|
||||
return convertLength(ind);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ResultSet::getStringData(unsigned short columnIndex, void* data,
|
||||
size_t size)
|
||||
{
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_CHAR, (SQLPOINTER)data, size, NULL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ResultSet::getNStringLength(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ind;
|
||||
char16_t dummy;
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_WCHAR, &dummy, sizeof(dummy), &ind);
|
||||
size_t ret = convertLength(ind);
|
||||
if (ret == ResultSet::NULL_DATA || ret == ResultSet::UNKNOWN_LENGTH)
|
||||
return ret;
|
||||
return ret / sizeof(char16_t);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ResultSet::getNStringData(unsigned short columnIndex, void* data,
|
||||
size_t size)
|
||||
{
|
||||
EXEC_STMT(SQLGetData, parent_->hstmt_, columnIndex,
|
||||
SQL_C_WCHAR, (SQLPOINTER)data, size * sizeof(char16_t), NULL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
324
external/odbccpp/src/odbc/ResultSet.h
vendored
Normal file
324
external/odbccpp/src/odbc/ResultSet.h
vendored
Normal file
@ -0,0 +1,324 @@
|
||||
#ifndef ODBC_RESULTSET_H_INCLUDED
|
||||
#define ODBC_RESULTSET_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Represents the result set of a SQL query.
|
||||
*/
|
||||
class ODBC_EXPORT ResultSet : public RefCounted
|
||||
{
|
||||
friend class DatabaseMetaData;
|
||||
friend class DatabaseMetaDataBase;
|
||||
friend class DatabaseMetaDataUnicode;
|
||||
friend class PreparedStatement;
|
||||
friend class Statement;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Data length constant that signals that the data is NULL.
|
||||
*/
|
||||
constexpr static std::size_t NULL_DATA = (std::size_t)-1;
|
||||
|
||||
/**
|
||||
* Data length constant that signals that the database could not determine
|
||||
* the length of the data.
|
||||
*/
|
||||
constexpr static std::size_t UNKNOWN_LENGTH = (std::size_t)-2;
|
||||
|
||||
private:
|
||||
ResultSet(StatementBase* parent);
|
||||
~ResultSet();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Advances the cursor to the next row of the ResultSet object and fetches
|
||||
* data for all bound columns.
|
||||
*
|
||||
* @return Returns true if the current row is valid, false otherwise.
|
||||
*/
|
||||
bool next();
|
||||
|
||||
/**
|
||||
* Closes the cursor associated with the current Statement object and
|
||||
* discards all pending results.
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Retrieves a ResultSetMetaData object that contains information about the
|
||||
* number, types and properties of the columns in this ResultSet object.
|
||||
*
|
||||
* @return Returns a ResultSetMetaData object.
|
||||
*/
|
||||
ResultSetMetaDataRef getMetaData();
|
||||
|
||||
/**
|
||||
* Retrieves a ResultSetMetaDataUnicode object that contains information
|
||||
* about the number, types and properties of the columns in this ResultSet
|
||||
* object.
|
||||
*
|
||||
* @return Returns a ResultSetMetaDataUnicode object.
|
||||
*/
|
||||
ResultSetMetaDataUnicodeRef getMetaDataUnicode();
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a boolean.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Boolean getBoolean(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a signed byte.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Byte getByte(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* an unsigned byte.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
UByte getUByte(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a signed short integer.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Short getShort(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* an unsigned short integer.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
UShort getUShort(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a signed integer.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Int getInt(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* an unsigned integer.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
UInt getUInt(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a signed long integer.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Long getLong(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* an unsigned long integer.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
ULong getULong(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a decimal object.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Decimal getDecimal(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a floating point type with single precision.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Float getFloat(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a floating point type with double precision.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Double getDouble(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a date object.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Date getDate(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a time object.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Time getTime(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a timestamp object.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Timestamp getTimestamp(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a string object.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
String getString(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* a string with 16-bit characters.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
NString getNString(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the value of the specified column in the current row as
|
||||
* an object with binary data.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column value.
|
||||
*/
|
||||
Binary getBinary(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the length of the binary data stored in the specified column of
|
||||
* the current row.
|
||||
*
|
||||
* If the binary data is NULL, the constant NULL_DATA is returned. If the
|
||||
* database cannot determine the length, the constant UNKNOWN_LENGTH is
|
||||
* returned.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the length of binary data, NULL_DATA or
|
||||
* UNKNOWN_LENGTH.
|
||||
*/
|
||||
std::size_t getBinaryLength(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the binary data stored in the specified column of the current
|
||||
* row.
|
||||
*
|
||||
* The total length of the binary data can be found by calling
|
||||
* the getBinaryLength() function.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @param data The pointer to a buffer where the read data will be
|
||||
* stored.
|
||||
* @param size The maximum number of bytes to be read.
|
||||
*/
|
||||
void getBinaryData(unsigned short columnIndex, void* data,
|
||||
std::size_t size);
|
||||
|
||||
/**
|
||||
* Retrieves the lengh of the string stored in the specified column of
|
||||
* the current row.
|
||||
*
|
||||
* If the string is NULL, the constant NULL_DATA is returned. If the
|
||||
* database cannot determine the length, the constant UNKNOWN_LENGTH is
|
||||
* returned.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return The length of a string in characters, NULL_DATA or
|
||||
* UNKNOWN_LENGTH.
|
||||
*/
|
||||
std::size_t getStringLength(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the string data stored in the specified column of the current
|
||||
* row.
|
||||
*
|
||||
* The total length of the string can be found by calling the
|
||||
* getStringLength() function.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @param[out] data The pointer to a buffer where the read data will be
|
||||
* stored.
|
||||
* @param size The maximum number of bytes to be read.
|
||||
*/
|
||||
void getStringData(unsigned short columnIndex, void* data,
|
||||
std::size_t size);
|
||||
|
||||
/**
|
||||
* Retrieves the length of the string with 16-bit characters stored in the
|
||||
* specified column of the current row.
|
||||
*
|
||||
* If the string is NULL, the constant NULL_DATA is returned. If the
|
||||
* database cannot determine the length, the constant UNKNOWN_LENGTH is
|
||||
* returned.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return The length of a string in characters, NULL_DATA or
|
||||
* UNKNOWN_LENGTH.
|
||||
*/
|
||||
std::size_t getNStringLength(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Retrieves the 16-bit character string data stored in the specified column
|
||||
* of the current row.
|
||||
*
|
||||
* The total length of the string can be found by calling the
|
||||
* getNStringLength() function.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @param data The pointer to a buffer where read data will be
|
||||
stored.
|
||||
* @param size The maximum number of 16-bit characters to be read.
|
||||
*/
|
||||
void getNStringData(unsigned short columnIndex, void* data,
|
||||
std::size_t size);
|
||||
|
||||
private:
|
||||
StatementBaseRef parent_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
66
external/odbccpp/src/odbc/ResultSetMetaData.cpp
vendored
Normal file
66
external/odbccpp/src/odbc/ResultSetMetaData.cpp
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
#include <vector>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSetMetaData.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaData::ResultSetMetaData(StatementBase* stmt)
|
||||
: ResultSetMetaDataBase(stmt)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getCatalogName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_CATALOG_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getSchemaName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_SCHEMA_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getTableName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_TABLE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getColumnLabel(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_LABEL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getColumnName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getColumnTypeName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_TYPE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string ResultSetMetaData::getStringColAttribute(unsigned short columnIndex,
|
||||
unsigned short field)
|
||||
{
|
||||
vector<char> buffer;
|
||||
buffer.resize(256);
|
||||
while (true)
|
||||
{
|
||||
SQLPOINTER ptr = &buffer[0];
|
||||
SQLSMALLINT bufLen = (SQLSMALLINT)buffer.size();
|
||||
SQLSMALLINT dataLen;
|
||||
EXEC_STMT(SQLColAttributeA, stmt_->hstmt_, columnIndex, field, ptr,
|
||||
bufLen, &dataLen, NULL);
|
||||
if (dataLen < bufLen)
|
||||
break;
|
||||
buffer.resize(dataLen + 1);
|
||||
}
|
||||
return string(&buffer[0]);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
78
external/odbccpp/src/odbc/ResultSetMetaData.h
vendored
Normal file
78
external/odbccpp/src/odbc/ResultSetMetaData.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef ODBC_RESULTSETMETADATA_H_INCLUDED
|
||||
#define ODBC_RESULTSETMETADATA_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/ResultSetMetaDataBase.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Metadata on a result set.
|
||||
*/
|
||||
class ODBC_EXPORT ResultSetMetaData : public ResultSetMetaDataBase
|
||||
{
|
||||
friend class PreparedStatement;
|
||||
friend class ResultSet;
|
||||
|
||||
private:
|
||||
ResultSetMetaData(StatementBase* parent);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns a column's catalog name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's catalog name.
|
||||
*/
|
||||
std::string getCatalogName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's schema name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's schema name.
|
||||
*/
|
||||
std::string getSchemaName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's table name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's table name.
|
||||
*/
|
||||
std::string getTableName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's label.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's label.
|
||||
*/
|
||||
std::string getColumnLabel(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's name.
|
||||
*/
|
||||
std::string getColumnName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's type name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's type name.
|
||||
*/
|
||||
std::string getColumnTypeName(unsigned short columnIndex);
|
||||
|
||||
private:
|
||||
std::string getStringColAttribute(unsigned short columnIndex,
|
||||
unsigned short field);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
128
external/odbccpp/src/odbc/ResultSetMetaDataBase.cpp
vendored
Normal file
128
external/odbccpp/src/odbc/ResultSetMetaDataBase.cpp
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
#include <vector>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSetMetaDataBase.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaDataBase::ResultSetMetaDataBase(StatementBase* stmt)
|
||||
: stmt_(stmt, true)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short ResultSetMetaDataBase::getColumnCount()
|
||||
{
|
||||
SQLSMALLINT ret;
|
||||
EXEC_STMT(SQLNumResultCols, stmt_->hstmt_, &ret);
|
||||
return (unsigned short)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
short ResultSetMetaDataBase::getColumnType(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_TYPE, NULL, 0, NULL, &ret);
|
||||
return (short)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ResultSetMetaDataBase::getColumnLength(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_LENGTH, NULL, 0, NULL, &ret);
|
||||
return (size_t)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ResultSetMetaDataBase::getColumnOctetLength(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_OCTET_LENGTH, NULL, 0, NULL, &ret);
|
||||
return (size_t)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t ResultSetMetaDataBase::getColumnDisplaySize(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &ret);
|
||||
return (size_t)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short ResultSetMetaDataBase::getPrecision(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_PRECISION, NULL, 0, NULL, &ret);
|
||||
return (unsigned short)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned short ResultSetMetaDataBase::getScale(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_SCALE, NULL, 0, NULL, &ret);
|
||||
return (unsigned short)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isAutoIncrement(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_AUTO_UNIQUE_VALUE, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_TRUE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isCaseSensitive(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_CASE_SENSITIVE, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_TRUE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isNamed(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_UNNAMED, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_NAMED;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isNullable(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_NULLABLE, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_NULLABLE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isReadOnly(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_UPDATABLE, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_ATTR_READONLY;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isSearchable(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_SEARCHABLE, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_PRED_SEARCHABLE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ResultSetMetaDataBase::isSigned(unsigned short columnIndex)
|
||||
{
|
||||
SQLLEN ret;
|
||||
EXEC_STMT(SQLColAttribute, stmt_->hstmt_, columnIndex,
|
||||
SQL_DESC_UNSIGNED, NULL, 0, NULL, &ret);
|
||||
return ret == SQL_FALSE;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
157
external/odbccpp/src/odbc/ResultSetMetaDataBase.h
vendored
Normal file
157
external/odbccpp/src/odbc/ResultSetMetaDataBase.h
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
#ifndef ODBC_RESULTSETMETADATABASE_H_INCLUDED
|
||||
#define ODBC_RESULTSETMETADATABASE_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Metadata on a result set.
|
||||
*/
|
||||
class ODBC_EXPORT ResultSetMetaDataBase : public RefCounted
|
||||
{
|
||||
protected:
|
||||
ResultSetMetaDataBase(StatementBase* parent);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the number of columns in the result set.
|
||||
*
|
||||
* @return Returns the number of columns in the result set.
|
||||
*/
|
||||
unsigned short getColumnCount();
|
||||
|
||||
/**
|
||||
* Returns a column's data type.
|
||||
*
|
||||
* See SQLDataTypes for a list of data type constants.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's data type.
|
||||
*/
|
||||
short getColumnType(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's length.
|
||||
*
|
||||
* This is usually the maximum length of a value measured in characters for
|
||||
* strings and measured in bytes for binary data.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's length.
|
||||
*/
|
||||
std::size_t getColumnLength(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's octet length.
|
||||
*
|
||||
* This is usually the maximum length of a value measured in bytes.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's octet length.
|
||||
*/
|
||||
std::size_t getColumnOctetLength(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's display size.
|
||||
*
|
||||
* This is the maximum number of characters to display a value.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's display size.
|
||||
*/
|
||||
std::size_t getColumnDisplaySize(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's precision in case of decimal types.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's precision in case of decimal
|
||||
* types.
|
||||
*/
|
||||
unsigned short getPrecision(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's scale in case of decimal types.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's scale in case of decimal
|
||||
* types.
|
||||
*/
|
||||
unsigned short getScale(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column is auto-incrementing.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column is auto-incrementing,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool isAutoIncrement(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column is case sensitive.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column is case-sensitive, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool isCaseSensitive(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column is named.
|
||||
*
|
||||
* If a column is named, its name can be retrieved with the getColumnName()
|
||||
* function.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column is named, false otherwise.
|
||||
*/
|
||||
bool isNamed(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column can contain NULL values.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column can contain NULL values,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool isNullable(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column in a result set is read-only.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column is read-only, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool isReadOnly(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column can be used in WHERE-clauses with any comparison
|
||||
* operator.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column is searchable, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool isSearchable(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Checks whether a column can contain signed numbers.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns true if the column can contain signed
|
||||
* numbers, false otherwise.
|
||||
*/
|
||||
bool isSigned(unsigned short columnIndex);
|
||||
|
||||
protected:
|
||||
StatementBaseRef stmt_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
67
external/odbccpp/src/odbc/ResultSetMetaDataUnicode.cpp
vendored
Normal file
67
external/odbccpp/src/odbc/ResultSetMetaDataUnicode.cpp
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
#include <vector>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSetMetaDataUnicode.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetMetaDataUnicode::ResultSetMetaDataUnicode(StatementBase* stmt)
|
||||
: ResultSetMetaDataBase(stmt)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getCatalogName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_CATALOG_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getSchemaName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_SCHEMA_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getTableName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_TABLE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getColumnLabel(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_LABEL);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getColumnName(unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getColumnTypeName(
|
||||
unsigned short columnIndex)
|
||||
{
|
||||
return getStringColAttribute(columnIndex, SQL_DESC_TYPE_NAME);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
u16string ResultSetMetaDataUnicode::getStringColAttribute(
|
||||
unsigned short columnIndex, unsigned short field)
|
||||
{
|
||||
vector<char16_t> buffer;
|
||||
buffer.resize(256);
|
||||
while (true)
|
||||
{
|
||||
SQLPOINTER ptr = &buffer[0];
|
||||
SQLSMALLINT bufLen = (SQLSMALLINT)(buffer.size() * sizeof(char16_t));
|
||||
SQLSMALLINT dataLen;
|
||||
EXEC_STMT(SQLColAttributeW, stmt_->hstmt_, columnIndex, field, ptr,
|
||||
bufLen, &dataLen, NULL);
|
||||
if (dataLen < bufLen)
|
||||
break;
|
||||
buffer.resize(dataLen / sizeof(char16_t) + 1);
|
||||
}
|
||||
return u16string(&buffer[0]);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
78
external/odbccpp/src/odbc/ResultSetMetaDataUnicode.h
vendored
Normal file
78
external/odbccpp/src/odbc/ResultSetMetaDataUnicode.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef ODBC_RESULTSETMETADATAUNICODE_H_INCLUDED
|
||||
#define ODBC_RESULTSETMETADATAUNICODE_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/ResultSetMetaDataBase.h>
|
||||
#include <odbc/Types.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Metadata on a result set.
|
||||
*/
|
||||
class ODBC_EXPORT ResultSetMetaDataUnicode : public ResultSetMetaDataBase
|
||||
{
|
||||
friend class PreparedStatement;
|
||||
friend class ResultSet;
|
||||
|
||||
private:
|
||||
ResultSetMetaDataUnicode(StatementBase* parent);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns a column's catalog name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's catalog name.
|
||||
*/
|
||||
std::u16string getCatalogName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's schema name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's schema name.
|
||||
*/
|
||||
std::u16string getSchemaName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's table name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's table name.
|
||||
*/
|
||||
std::u16string getTableName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's label.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's label.
|
||||
*/
|
||||
std::u16string getColumnLabel(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's name.
|
||||
*/
|
||||
std::u16string getColumnName(unsigned short columnIndex);
|
||||
|
||||
/**
|
||||
* Returns a column's type name.
|
||||
*
|
||||
* @param columnIndex The column index starting from 1.
|
||||
* @return Returns the column's type name.
|
||||
*/
|
||||
std::u16string getColumnTypeName(unsigned short columnIndex);
|
||||
|
||||
private:
|
||||
std::u16string getStringColAttribute(unsigned short columnIndex,
|
||||
unsigned short field);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
46
external/odbccpp/src/odbc/Statement.cpp
vendored
Normal file
46
external/odbccpp/src/odbc/Statement.cpp
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/ResultSet.h>
|
||||
#include <odbc/Statement.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
Statement::Statement(Connection* parent) : StatementBase(parent)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Statement::setHandle(void* hstmt)
|
||||
{
|
||||
hstmt_ = hstmt;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Statement::execute(const char* sql)
|
||||
{
|
||||
EXEC_STMT(SQLExecDirectA, hstmt_, (SQLCHAR*)sql, SQL_NTS);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Statement::execute(const char16_t* sql)
|
||||
{
|
||||
EXEC_STMT(SQLExecDirectW, hstmt_, (SQLWCHAR*)sql, SQL_NTS);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef Statement::executeQuery(const char* sql)
|
||||
{
|
||||
ResultSetRef ret(new ResultSet(this));
|
||||
EXEC_STMT(SQLFreeStmt, hstmt_, SQL_CLOSE);
|
||||
EXEC_STMT(SQLExecDirectA, hstmt_, (SQLCHAR*)sql, SQL_NTS);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ResultSetRef Statement::executeQuery(const char16_t* sql)
|
||||
{
|
||||
ResultSetRef ret(new ResultSet(this));
|
||||
EXEC_STMT(SQLFreeStmt, hstmt_, SQL_CLOSE);
|
||||
EXEC_STMT(SQLExecDirectW, hstmt_, (SQLWCHAR*)sql, SQL_NTS);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
62
external/odbccpp/src/odbc/Statement.h
vendored
Normal file
62
external/odbccpp/src/odbc/Statement.h
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef ODBC_STATEMENT_H_INCLUDED
|
||||
#define ODBC_STATEMENT_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/StatementBase.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* SQL Statement wrapper.
|
||||
*
|
||||
* Represents a SQL statement that can be executed.
|
||||
*/
|
||||
class ODBC_EXPORT Statement : public StatementBase
|
||||
{
|
||||
friend class Connection;
|
||||
friend class DatabaseMetaData;
|
||||
|
||||
private:
|
||||
Statement(Connection* parent);
|
||||
|
||||
private:
|
||||
void setHandle(void* hstmt);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Executes the given SQL statement.
|
||||
*
|
||||
* @param sql The SQL statement.
|
||||
*/
|
||||
void execute(const char* sql);
|
||||
|
||||
/**
|
||||
* Executes the given SQL statement.
|
||||
*
|
||||
* @param sql The SQL statement.
|
||||
*/
|
||||
void execute(const char16_t* sql);
|
||||
|
||||
/**
|
||||
* Executes the given SQL statement and returns a ResultSet object.
|
||||
*
|
||||
* @param sql The SQL statement.
|
||||
* @return Returns a ResultSet object that contains the data produced
|
||||
* by the given SQL statement.
|
||||
*/
|
||||
ResultSetRef executeQuery(const char* sql);
|
||||
|
||||
/**
|
||||
* Executes the given SQL statement and returns a ResultSet object.
|
||||
*
|
||||
* @param sql The SQL statement.
|
||||
* @return Returns a ResultSet object that contains the data produced
|
||||
* by the given SQL statement.
|
||||
*/
|
||||
ResultSetRef executeQuery(const char16_t* sql);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
51
external/odbccpp/src/odbc/StatementBase.cpp
vendored
Normal file
51
external/odbccpp/src/odbc/StatementBase.cpp
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
#include <odbc/Connection.h>
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/StatementBase.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
StatementBase::StatementBase(Connection* parent)
|
||||
: parent_(parent, true)
|
||||
, hstmt_(SQL_NULL_HANDLE)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
StatementBase::~StatementBase()
|
||||
{
|
||||
if (hstmt_)
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, hstmt_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned long StatementBase::getMaxRows()
|
||||
{
|
||||
SQLULEN ret;
|
||||
EXEC_STMT(SQLGetStmtAttr, hstmt_, SQL_ATTR_MAX_ROWS,
|
||||
(SQLPOINTER)&ret, 0, NULL);
|
||||
return (unsigned long)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void StatementBase::setMaxRows(unsigned long maxRows)
|
||||
{
|
||||
EXEC_STMT(SQLSetStmtAttr, hstmt_, SQL_ATTR_MAX_ROWS,
|
||||
(SQLPOINTER)(ptrdiff_t)maxRows, SQL_IS_UINTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned long StatementBase::getQueryTimeout()
|
||||
{
|
||||
SQLULEN ret;
|
||||
EXEC_STMT(SQLGetStmtAttr, hstmt_, SQL_ATTR_QUERY_TIMEOUT,
|
||||
(SQLPOINTER)&ret, 0, NULL);
|
||||
return (unsigned long)ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void StatementBase::setQueryTimeout(unsigned long seconds)
|
||||
{
|
||||
EXEC_STMT(SQLSetStmtAttr, hstmt_, SQL_ATTR_QUERY_TIMEOUT,
|
||||
(SQLPOINTER)(ptrdiff_t)seconds, SQL_IS_UINTEGER);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
78
external/odbccpp/src/odbc/StatementBase.h
vendored
Normal file
78
external/odbccpp/src/odbc/StatementBase.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef ODBC_STATEMENTBASE_H_INCLUDED
|
||||
#define ODBC_STATEMENTBASE_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Config.h>
|
||||
#include <odbc/Forwards.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Base class for Statement and PreparedStatement.
|
||||
*/
|
||||
class ODBC_EXPORT StatementBase : public RefCounted
|
||||
{
|
||||
friend class DatabaseMetaData;
|
||||
friend class DatabaseMetaDataBase;
|
||||
friend class DatabaseMetaDataUnicode;
|
||||
friend class ParameterMetaData;
|
||||
friend class PreparedStatement;
|
||||
friend class ResultSet;
|
||||
friend class ResultSetMetaData;
|
||||
friend class ResultSetMetaDataBase;
|
||||
friend class ResultSetMetaDataUnicode;
|
||||
friend class Statement;
|
||||
|
||||
private:
|
||||
StatementBase(Connection* parent);
|
||||
~StatementBase();
|
||||
|
||||
private:
|
||||
ConnectionRef parent_;
|
||||
void* hstmt_;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Gets the maximum number of rows that any ResultSet object created by the
|
||||
* current instance can contain.
|
||||
*
|
||||
* If the returned value equals 0, the driver returns all rows.
|
||||
*
|
||||
* @return Returns the maximum number of rows in a ResultSet object.
|
||||
*/
|
||||
unsigned long getMaxRows();
|
||||
|
||||
/**
|
||||
* Sets the maximum number of rows that any ResultSet object created by the
|
||||
* current instance can contain.
|
||||
*
|
||||
* If the value is set to 0, the driver returns all rows.
|
||||
*
|
||||
* @param maxRows The the maximum number of rows in a ResultSet object.
|
||||
*/
|
||||
void setMaxRows(unsigned long maxRows);
|
||||
|
||||
/**
|
||||
* Retrieves the number of seconds that the Statement object has at its
|
||||
* disposal to finish query execution.
|
||||
*
|
||||
* If the returned value equals 0, there is no limit.
|
||||
*
|
||||
* @return Returns the query timeout.
|
||||
*/
|
||||
unsigned long getQueryTimeout();
|
||||
|
||||
/**
|
||||
* Sets the numer of seconds that the Statement object has at its
|
||||
* disposal to finish query execution.
|
||||
*
|
||||
* If the value is set to 0, there is no limit.
|
||||
*
|
||||
* @param seconds The query timeout in seconds.
|
||||
*/
|
||||
void setQueryTimeout(unsigned long seconds);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
467
external/odbccpp/src/odbc/Types.cpp
vendored
Normal file
467
external/odbccpp/src/odbc/Types.cpp
vendored
Normal file
@ -0,0 +1,467 @@
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/Types.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
decimal::decimal() : value_("0"), precision_(1), scale_(1)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
decimal::decimal(std::int64_t value, std::uint8_t precision, std::uint8_t scale)
|
||||
: decimal(to_string(value), precision, scale)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
decimal::decimal(
|
||||
std::uint64_t value, std::uint8_t precision, std::uint8_t scale)
|
||||
: decimal(to_string(value), precision, scale)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
decimal::decimal(
|
||||
std::string const& value, std::uint8_t precision, std::uint8_t scale)
|
||||
: decimal(value.c_str(), precision, scale)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
decimal::decimal(const char* value, std::uint8_t precision, std::uint8_t scale)
|
||||
: precision_(precision), scale_(scale)
|
||||
{
|
||||
ODBC_CHECK(precision >= 1 && precision <= 38,
|
||||
"precision value must lie within [1,38]");
|
||||
ODBC_CHECK(scale <= precision, "scale value must lie within [0,precision]");
|
||||
|
||||
// decimal = [sign] digit+
|
||||
// sign = "+" | "-"
|
||||
// digit = "0" - "9"
|
||||
|
||||
const char* pos = value;
|
||||
|
||||
// Process the sign
|
||||
bool isNegative = false;
|
||||
if (*pos == '+') {
|
||||
++pos;
|
||||
} else if (*pos == '-') {
|
||||
isNegative = true;
|
||||
++pos;
|
||||
}
|
||||
|
||||
// Process the digits
|
||||
const char* digitsStart = pos;
|
||||
|
||||
// Skip leading zeros
|
||||
while (*pos == '0') {
|
||||
++pos;
|
||||
}
|
||||
|
||||
// Process remaining digits
|
||||
const char* nonZeroDigitsStart = pos;
|
||||
while (*pos) {
|
||||
ODBC_CHECK(('0' <= *pos) && (*pos <= '9'),
|
||||
"Decimal contains an invalid digit at position " << pos - value);
|
||||
++pos;
|
||||
}
|
||||
|
||||
const char* digitsEnd = pos;
|
||||
ODBC_CHECK(digitsStart != digitsEnd, "Decimal does not contain any digits");
|
||||
|
||||
// Special case: Only zeros
|
||||
if (nonZeroDigitsStart == digitsEnd) {
|
||||
value_ = "0";
|
||||
return;
|
||||
}
|
||||
|
||||
// Usual case: some non-zero digits
|
||||
ptrdiff_t numDigits = digitsEnd - nonZeroDigitsStart;
|
||||
ODBC_CHECK(numDigits <= precision, "Decimal cannot have more than "
|
||||
<< precision << " digits, but has " << numDigits);
|
||||
|
||||
if (isNegative)
|
||||
value_.push_back('-');
|
||||
value_.append(nonZeroDigitsStart, digitsEnd);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int8_t decimal::signum() const
|
||||
{
|
||||
switch (value_[0]) {
|
||||
case '-':
|
||||
return -1;
|
||||
case '0':
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string decimal::toString() const
|
||||
{
|
||||
if (scale_ == 0)
|
||||
return value_;
|
||||
|
||||
bool isSigned = (value_[0] == '-');
|
||||
size_t numDigits = value_.length() - (isSigned ? 1 : 0);
|
||||
|
||||
string ret;
|
||||
if (scale_ < numDigits)
|
||||
{
|
||||
ret.reserve(value_.length() + 1);
|
||||
size_t numCharsBeforeDecimalPoint = value_.length() - scale_;
|
||||
ret.append(value_.begin(), value_.begin() + numCharsBeforeDecimalPoint);
|
||||
ret.push_back('.');
|
||||
ret.append(value_.begin() + numCharsBeforeDecimalPoint, value_.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = (isSigned ? 1 : 0) + 2 + scale_;
|
||||
ret.reserve(len);
|
||||
if (isSigned)
|
||||
ret.push_back('-');
|
||||
ret.append("0.");
|
||||
size_t numZeros = scale_ - numDigits;
|
||||
ret.append(numZeros, '0');
|
||||
ret.append(value_.begin() + (isSigned ? 1 : 0), value_.end());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool decimal::operator==(const decimal& other) const
|
||||
{
|
||||
return cmp(other) == 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool decimal::operator!=(const decimal& other) const
|
||||
{
|
||||
return cmp(other) != 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool decimal::operator<(const decimal& other) const
|
||||
{
|
||||
return cmp(other) < 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool decimal::operator>(const decimal& other) const
|
||||
{
|
||||
return cmp(other) > 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool decimal::operator<=(const decimal& other) const
|
||||
{
|
||||
return cmp(other) <= 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool decimal::operator>=(const decimal& other) const
|
||||
{
|
||||
return cmp(other) >= 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int decimal::cmp(const decimal& other) const
|
||||
{
|
||||
// If signums are different, we can decide the relation of the numbers to
|
||||
// each other.
|
||||
int signumThis = signum();
|
||||
int signumOther = other.signum();
|
||||
if (signumThis != signumOther)
|
||||
return signumThis - signumOther;
|
||||
|
||||
// Signums are equals. Let's take a shortcut for the special case that both
|
||||
// numbers are 0.
|
||||
if (signumThis == 0)
|
||||
return 0;
|
||||
|
||||
// When comparing the numbers, we have to consider the scale properly.
|
||||
// We assign positions to each digit. The digit immediately before the the
|
||||
// decimal point is assigned position 0, the digit before that position 1
|
||||
// and so on. The first digit after the decimal point is assigned position
|
||||
// -1 and so on. After that we can compare digit by digit starting with
|
||||
// the digit having the highest position.
|
||||
bool isSigned = (value_[0] == '-');
|
||||
int numDigitsThis = (int)value_.length() - (isSigned ? 1 : 0);
|
||||
int numDigitsOther = (int)other.value_.length() - (isSigned ? 1 : 0);
|
||||
|
||||
int maxDigitThis = numDigitsThis - scale_ - 1;
|
||||
int minDigitThis = -(int)scale_;
|
||||
int maxDigitOther = numDigitsOther - other.scale_ - 1;
|
||||
int minDigitOther = -(int)other.scale_;
|
||||
|
||||
// We iterate over the whole position range of both numbers.
|
||||
int maxDigit = max(maxDigitThis, maxDigitOther);
|
||||
int minDigit = min(minDigitThis, minDigitOther);
|
||||
for (int i = maxDigit; i > minDigit; --i)
|
||||
{
|
||||
// Get the digit at position i of this number. Substitute '0' if
|
||||
// position i is not available.
|
||||
char digitThis;
|
||||
if ((i > maxDigitThis) || (i < minDigitThis))
|
||||
{
|
||||
digitThis = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
int rpos = -minDigitThis + i;
|
||||
digitThis = value_[value_.length() - 1 - rpos];
|
||||
}
|
||||
// Get the digit at position i of the other number. Substitute '0' if
|
||||
// position i is not available.
|
||||
char digitOther;
|
||||
if ((i > maxDigitOther) || (i < minDigitOther))
|
||||
{
|
||||
digitOther = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
int rpos = -minDigitOther + i;
|
||||
digitOther = other.value_[other.value_.length() - 1 - rpos];
|
||||
}
|
||||
// If the digits are different, we are done.
|
||||
if (digitThis != digitOther)
|
||||
return (int)digitThis - (int)digitOther;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ostream& operator<<(ostream& out, const decimal& d)
|
||||
{
|
||||
out << d.toString();
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
date::date() : date(0, 1, 1) {}
|
||||
//------------------------------------------------------------------------------
|
||||
date::date(int year, int month, int day)
|
||||
{
|
||||
ODBC_CHECK((year >= 0) && (year <= 9999), "Invalid year (" << year << ")");
|
||||
ODBC_CHECK((month >= 1) && (month <= 12),
|
||||
"Invalid month (" << month << ")");
|
||||
ODBC_CHECK((day >= 1) && (day <= daysInMonth(year, month)),
|
||||
"Invalid day (" << day << ")");
|
||||
year_ = year;
|
||||
month_ = month;
|
||||
day_ = day;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string date::toString() const
|
||||
{
|
||||
char buffer[32];
|
||||
snprintf(buffer, 32, "%04d-%02d-%02d", year_, month_, day_);
|
||||
return string(buffer);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool date::operator==(const date& other) const
|
||||
{
|
||||
return (year_ == other.year_)
|
||||
&& (month_ == other.month_)
|
||||
&& (day_ == other.day_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool date::operator!=(const date& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool date::operator<(const date& other) const
|
||||
{
|
||||
if (year_ != other.year_)
|
||||
return year_ < other.year_;
|
||||
if (month_ != other.month_)
|
||||
return month_ < other.month_;
|
||||
return day_ < other.day_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool date::operator>(const date& other) const
|
||||
{
|
||||
if (year_ != other.year_)
|
||||
return year_ > other.year_;
|
||||
if (month_ != other.month_)
|
||||
return month_ > other.month_;
|
||||
return day_ > other.day_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool date::operator<=(const date& other) const
|
||||
{
|
||||
return !(*this > other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool date::operator>=(const date& other) const
|
||||
{
|
||||
return !(*this < other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int date::daysInMonth(int year, int month)
|
||||
{
|
||||
switch (month)
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 8:
|
||||
case 10:
|
||||
case 12:
|
||||
return 31;
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
return 30;
|
||||
case 2:
|
||||
return daysInFebruary(year);
|
||||
default:
|
||||
ODBC_FAIL("Invalid month (" << month << ")");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int date::daysInFebruary(int year)
|
||||
{
|
||||
if ((year % 400) == 0)
|
||||
return 29;
|
||||
if ((year % 100) == 0)
|
||||
return 28;
|
||||
if ((year % 4) == 0)
|
||||
return 29;
|
||||
return 28;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ostream& operator<<(ostream& out, const date& d)
|
||||
{
|
||||
out << d.toString();
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
time::time() : time(0, 0, 0) {}
|
||||
//------------------------------------------------------------------------------
|
||||
time::time(int hour, int minute, int second)
|
||||
{
|
||||
ODBC_CHECK((hour >= 0) && (hour <= 23), "Invalid hour (" << hour << ")");
|
||||
ODBC_CHECK((minute >= 0) && (minute <= 59),
|
||||
"Invalid minute (" << minute << ")");
|
||||
ODBC_CHECK((second >= 0) && (second <= 59),
|
||||
"Invalid second (" << second << ")");
|
||||
hour_ = hour;
|
||||
minute_ = minute;
|
||||
second_ = second;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string time::toString() const
|
||||
{
|
||||
char buffer[32];
|
||||
snprintf(buffer, 32, "%02d:%02d:%02d", hour_, minute_, second_);
|
||||
return string(buffer);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool time::operator==(const time& other) const
|
||||
{
|
||||
return (hour_ == other.hour_)
|
||||
&& (minute_ == other.minute_)
|
||||
&& (second_ == other.second_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool time::operator!=(const time& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool time::operator<(const time& other) const
|
||||
{
|
||||
if (hour_ != other.hour_)
|
||||
return hour_ < other.hour_;
|
||||
if (minute_ != other.minute_)
|
||||
return minute_ < other.minute_;
|
||||
return second_ < other.second_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool time::operator>(const time& other) const
|
||||
{
|
||||
if (hour_ != other.hour_)
|
||||
return hour_ > other.hour_;
|
||||
if (minute_ != other.minute_)
|
||||
return minute_ > other.minute_;
|
||||
return second_ > other.second_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool time::operator<=(const time& other) const
|
||||
{
|
||||
return !(*this > other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool time::operator>=(const time& other) const
|
||||
{
|
||||
return !(*this < other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ostream& operator<<(ostream& out, const time& t)
|
||||
{
|
||||
out << t.toString();
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
timestamp::timestamp() : timestamp(0, 1, 1, 0, 0, 0, 0) {}
|
||||
//------------------------------------------------------------------------------
|
||||
timestamp::timestamp(int year, int month, int day, int hour, int minute,
|
||||
int second, int milliseconds) : date(year, month, day),
|
||||
time(hour, minute, second)
|
||||
{
|
||||
ODBC_CHECK((milliseconds >= 0) && (milliseconds <= 999),
|
||||
"Invalid milliseconds (" << milliseconds << ")");
|
||||
milliseconds_ = milliseconds;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string timestamp::toString() const
|
||||
{
|
||||
char buffer[40];
|
||||
snprintf(buffer, 40, "%04d-%02d-%02d %02d:%02d:%02d.%03d",
|
||||
year_, month_, day_, hour_, minute_, second_, milliseconds_);
|
||||
return string(buffer);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool timestamp::operator==(const timestamp& other) const
|
||||
{
|
||||
return date::operator==(other)
|
||||
&& time::operator==(other)
|
||||
&& (milliseconds_ == other.milliseconds_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool timestamp::operator!=(const timestamp& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool timestamp::operator<(const timestamp& other) const
|
||||
{
|
||||
if (date::operator!=(other))
|
||||
return date::operator<(other);
|
||||
if (time::operator!=(other))
|
||||
return time::operator<(other);
|
||||
return milliseconds_ < other.milliseconds_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool timestamp::operator>(const timestamp& other) const
|
||||
{
|
||||
if (date::operator!=(other))
|
||||
return date::operator>(other);
|
||||
if (time::operator!=(other))
|
||||
return time::operator>(other);
|
||||
return milliseconds_ > other.milliseconds_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool timestamp::operator<=(const timestamp& other) const
|
||||
{
|
||||
return !(*this > other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool timestamp::operator>=(const timestamp& other) const
|
||||
{
|
||||
return !(*this < other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ostream& operator<<(ostream& out, const timestamp& ts)
|
||||
{
|
||||
out << ts.toString();
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
960
external/odbccpp/src/odbc/Types.h
vendored
Normal file
960
external/odbccpp/src/odbc/Types.h
vendored
Normal file
@ -0,0 +1,960 @@
|
||||
#ifndef ODBC_TYPES_H_INCLUDED
|
||||
#define ODBC_TYPES_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <odbc/Config.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Specifies the type of an ODBC DSN.
|
||||
*/
|
||||
enum class DSNType
|
||||
{
|
||||
/**
|
||||
* Indicates that both user and system DSNs will be returned.
|
||||
*/
|
||||
ALL,
|
||||
/**
|
||||
* Indicates that only system DSNs will be returned.
|
||||
*/
|
||||
SYSTEM,
|
||||
/**
|
||||
* Indicates that only user DSNs will be returned.
|
||||
*/
|
||||
USER
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Specifies the constants that identify ODBC SQL data types.
|
||||
*/
|
||||
class SQLDataTypes
|
||||
{
|
||||
SQLDataTypes() = delete;
|
||||
|
||||
public:
|
||||
/// 64-bit integer value.
|
||||
static constexpr int BigInt = -5;
|
||||
/// Binary data of fixed length.
|
||||
static constexpr int Binary = -2;
|
||||
/// Single bit binary data.
|
||||
static constexpr int Bit = -7;
|
||||
/// Boolean value.
|
||||
static constexpr int Boolean = 16;
|
||||
/// Character string of fixed string length.
|
||||
static constexpr int Char = 1;
|
||||
/// Year, month, and day fields.
|
||||
static constexpr int Date = 9;
|
||||
/// Year, month, and day fields.
|
||||
static constexpr int DateTime = 9;
|
||||
/// Signed, exact, numeric value.
|
||||
static constexpr int Decimal = 3;
|
||||
/// Double-precision floating point number.
|
||||
static constexpr int Double = 8;
|
||||
/// Floating point number with driver-specific precision.
|
||||
static constexpr int Float = 6;
|
||||
/// Fixed length GUID.
|
||||
static constexpr int Guid = -11;
|
||||
/// 32-bit integer value.
|
||||
static constexpr int Integer = 4;
|
||||
/// Interval data type.
|
||||
static constexpr int Interval = 10;
|
||||
/// Variable length binary data.
|
||||
static constexpr int LongVarBinary = -4;
|
||||
/// Variable length character data.
|
||||
static constexpr int LongVarChar = -1;
|
||||
/// Signed, exact, numeric value.
|
||||
static constexpr int Numeric = 2;
|
||||
/// Single-precision floating point number.
|
||||
static constexpr int Real = 7;
|
||||
/// 16-bit integer value.
|
||||
static constexpr int SmallInt = 5;
|
||||
/// Hour, minute, and second fields.
|
||||
static constexpr int Time = 10;
|
||||
/// Year, month, day, hour, minute, and second fields.
|
||||
static constexpr int Timestamp = 11;
|
||||
/// 8-bit integer value.
|
||||
static constexpr int TinyInt = -6;
|
||||
/// Year, month, and day fields.
|
||||
static constexpr int TypeDate = 91;
|
||||
/// Hour, minute, and second fields.
|
||||
static constexpr int TypeTime = 92;
|
||||
/// Year, month, day, hour, minute, and second fields.
|
||||
static constexpr int TypeTimestamp = 93;
|
||||
/// Variable length binary data.
|
||||
static constexpr int VarBinary = -3;
|
||||
/// Variable-length character string.
|
||||
static constexpr int VarChar = 12;
|
||||
/// Unicode character string of fixed string length.
|
||||
static constexpr int WChar = -8;
|
||||
/// Unicode variable-length character data.
|
||||
static constexpr int WLongVarChar = -10;
|
||||
/// Unicode variable-length character string.
|
||||
static constexpr int WVarChar = -9;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Specifies isolation levels for transactions.
|
||||
*/
|
||||
enum class TransactionIsolationLevel
|
||||
{
|
||||
/**
|
||||
* Indicates that any phenomena such as dirty reads, non-repeatable reads
|
||||
* and phantoms can occur.
|
||||
*/
|
||||
READ_UNCOMMITTED,
|
||||
/**
|
||||
* Prevents from dirty reads, but non-repeatable reads and phantoms can
|
||||
* occur.
|
||||
*/
|
||||
READ_COMMITTED,
|
||||
/**
|
||||
* Prevents from dirty and non-repeatable reads, but phantoms can occur.
|
||||
*/
|
||||
REPEATABLE_READ,
|
||||
/**
|
||||
* Prevents from any phenomena such as dirty reads, non-repeatable reads and
|
||||
* phantoms.
|
||||
*/
|
||||
SERIALIZABLE,
|
||||
/**
|
||||
* Indicates that transactions are not supported by a database.
|
||||
*/
|
||||
NONE
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Represents a decimal number.
|
||||
*
|
||||
* A decimal number has a precision and a scale. The precision is the total
|
||||
* number of digits used to represent a number. The scale is the number of
|
||||
* digits after the decimal point.
|
||||
*
|
||||
* The maximum supported precision is 38. The scale must not be greater than the
|
||||
* precision.
|
||||
*/
|
||||
class ODBC_EXPORT decimal
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a decimal with value 0, precision 1 and scale 1.
|
||||
*/
|
||||
decimal();
|
||||
|
||||
/**
|
||||
* Constructs a decimal from a given integer value applying the given scale.
|
||||
*
|
||||
* Applying the scale means that the value is divided by 10^scale, e.g. 12
|
||||
* is converted to 1.2 if the given scale is 1.
|
||||
*
|
||||
* @param value The value.
|
||||
* @param precision The precision.
|
||||
* @param scale The scale.
|
||||
*/
|
||||
decimal(std::int64_t value, std::uint8_t precision, std::uint8_t scale = 0);
|
||||
|
||||
/**
|
||||
* Constructs a decimal from a given integer value applying the given scale.
|
||||
*
|
||||
* Applying the scale means that the value is divided by 10^scale, e.g. 12
|
||||
* is converted to 1.2 if the given scale is 1.
|
||||
*
|
||||
* @param value The value.
|
||||
* @param precision The precision.
|
||||
* @param scale The scale.
|
||||
*/
|
||||
decimal(std::uint64_t value, std::uint8_t precision,
|
||||
std::uint8_t scale = 0);
|
||||
|
||||
/**
|
||||
* Constructs a decimal from a given value applying the given scale.
|
||||
*
|
||||
* Applying the scale means that the value is divided by 10^scale, e.g. 12
|
||||
* is converted to 1.2 if the given scale is 1.
|
||||
*
|
||||
* @param value The value.
|
||||
* @param precision The precision.
|
||||
* @param scale The scale.
|
||||
*/
|
||||
decimal(const std::string& value, std::uint8_t precision,
|
||||
std::uint8_t scale = 0);
|
||||
|
||||
/**
|
||||
* Constructs a decimal from a given value applying the given scale.
|
||||
*
|
||||
* Applying the scale means that the value is divided by 10^scale, e.g. 12
|
||||
* is converted to 1.2 if the given scale is 1.
|
||||
*
|
||||
* @param value The value.
|
||||
* @param precision The precision.
|
||||
* @param scale The scale.
|
||||
*/
|
||||
decimal(const char* value, std::uint8_t precision, std::uint8_t scale = 0);
|
||||
|
||||
/**
|
||||
* Returns the precision of this decimal number.
|
||||
*
|
||||
* @return Returns the precision of this decimal number.
|
||||
*/
|
||||
std::uint8_t precision() const { return precision_; }
|
||||
|
||||
/**
|
||||
* Returns the scale of this decimal number.
|
||||
*
|
||||
* @return Returns the scale of this decimal number.
|
||||
*/
|
||||
std::uint8_t scale() const { return scale_; }
|
||||
|
||||
/**
|
||||
* Returns the signum of this decimal number.
|
||||
*
|
||||
* The signum is 1 if the number is positive, -1 if the number is negative,
|
||||
* 0 if the number is 0.
|
||||
*
|
||||
* @return Returns the signum of this decimal number.
|
||||
*/
|
||||
std::int8_t signum() const;
|
||||
|
||||
/**
|
||||
* Returns the unscaled value of this decimal.
|
||||
*
|
||||
* In the unscaled value, the decimal point is ommited.
|
||||
*
|
||||
* @return Returns the unscaled value of this decimal number.
|
||||
*/
|
||||
const char* unscaledValue() const { return value_.c_str(); };
|
||||
|
||||
/**
|
||||
* Returns a string representation of this number.
|
||||
*
|
||||
* The string representation has the usual human-readable format with sign
|
||||
* and decimal point.
|
||||
*
|
||||
* @return Returns the human-readable string representation of this value.
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Checks whether this number is equal to another number.
|
||||
*
|
||||
* Only the scaled values are considered by the comparison. Hence, numbers
|
||||
* that have different scale and precisions can still be considered equal.
|
||||
*
|
||||
* @param other Another number.
|
||||
* @return Returns true if this number is equal to the other number,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator==(const decimal& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this number is not equal to another number.
|
||||
*
|
||||
* Only the scaled values are considered by the comparison. Hence, numbers
|
||||
* that have different scale and precisions can still be considered equal.
|
||||
*
|
||||
* @param other Another number.
|
||||
* @return Returns true if this number is not equal to the other
|
||||
* number, false otherwise.
|
||||
*/
|
||||
bool operator!=(const decimal& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this number is less than another number.
|
||||
*
|
||||
* Only the scaled values are considered by the comparison. Hence, numbers
|
||||
* that have different scale and precisions can still be considered equal.
|
||||
*
|
||||
* @param other Another number.
|
||||
* @return Returns true if this number is less than the other number,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator< (const decimal& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this number is greater than another number.
|
||||
*
|
||||
* Only the scaled values are considered by the comparison. Hence, numbers
|
||||
* that have different scale and precisions can still be considered equal.
|
||||
*
|
||||
* @param other Another number.
|
||||
* @return Returns true if this number is greater than the other
|
||||
* number, false otherwise.
|
||||
*/
|
||||
bool operator> (const decimal& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this number is not greater than another number.
|
||||
*
|
||||
* Only the scaled values are considered by the comparison. Hence, numbers
|
||||
* that have different scale and precisions can still be considered equal.
|
||||
*
|
||||
* @param other Another number.
|
||||
* @return Returns true if this number is not greater than the other
|
||||
* number, false otherwise.
|
||||
*/
|
||||
bool operator<=(const decimal& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this number is not les than another number.
|
||||
*
|
||||
* Only the scaled values are considered by the comparison. Hence, numbers
|
||||
* that have different scale and precisions can still be considered equal.
|
||||
*
|
||||
* @param other Another number.
|
||||
* @return Returns true if this number is not less than the other
|
||||
* number, false otherwise.
|
||||
*/
|
||||
bool operator>=(const decimal& other) const;
|
||||
|
||||
private:
|
||||
int cmp(const decimal& other) const;
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
std::uint8_t precision_;
|
||||
std::uint8_t scale_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
std::ostream& operator<<(std::ostream& out, const decimal& d);
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Represents a date consisting of year, month and day in month.
|
||||
*/
|
||||
class ODBC_EXPORT date
|
||||
{
|
||||
friend class timestamp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a date with value 0000-01-01.
|
||||
*/
|
||||
date();
|
||||
|
||||
/**
|
||||
* Constructs a date with the given year, month and day in month.
|
||||
*
|
||||
* @param year The year.
|
||||
* @param month The month.
|
||||
* @param day The day in month.
|
||||
*/
|
||||
date(int year, int month, int day);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the year of this date object.
|
||||
*
|
||||
* @return Returns the year of this date object.
|
||||
*/
|
||||
int year() const { return year_; }
|
||||
|
||||
/**
|
||||
* Returns the month of this date object.
|
||||
*
|
||||
* @return Returns the month of this date object.
|
||||
*/
|
||||
int month() const { return month_; }
|
||||
|
||||
/**
|
||||
* Returns the day of month of this date object.
|
||||
*
|
||||
* @return Returns the day of month of this date object.
|
||||
*/
|
||||
int day() const { return day_; }
|
||||
|
||||
/**
|
||||
* Returns this date as a string in the format yyyy-mm-dd.
|
||||
*
|
||||
* @return Returns this date as a string in the format yyyy-mm-dd.
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Checks whether this date is equal to another date.
|
||||
*
|
||||
* @param other Another date.
|
||||
* @return Returns true if this date is equal to the other date, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator==(const date& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this date is not equal to another date.
|
||||
*
|
||||
* @param other Another date.
|
||||
* @return Returns true if this date is not equal to the other date,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator!=(const date& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this date is before another date.
|
||||
*
|
||||
* @param other Another date.
|
||||
* @return Returns true if this date is before the other date, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator< (const date& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this date is after another date.
|
||||
*
|
||||
* @param other Another date.
|
||||
* @return Returns true if this date is after the other date, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator> (const date& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this date is not after another date.
|
||||
*
|
||||
* @param other Another date.
|
||||
* @return Returns true if this date is not after the other date,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator<=(const date& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this date is not before another date.
|
||||
*
|
||||
* @param other Another date.
|
||||
* @return Returns true if this date is not before the other date,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator>=(const date& other) const;
|
||||
|
||||
private:
|
||||
static int daysInMonth(int year, int month);
|
||||
static int daysInFebruary(int year);
|
||||
|
||||
private:
|
||||
std::int16_t year_;
|
||||
std::uint8_t month_;
|
||||
std::uint8_t day_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
std::ostream& operator<<(std::ostream& out, const date& d);
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Represents a time consisting of hour, minute and second.
|
||||
*/
|
||||
class ODBC_EXPORT time
|
||||
{
|
||||
friend class timestamp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a time with value 00:00:00.
|
||||
*/
|
||||
time();
|
||||
|
||||
/**
|
||||
* Constructs a time with the given hour, minute and second.
|
||||
*
|
||||
* @param hour The hour (0-23).
|
||||
* @param minute The minute (0-59).
|
||||
* @param second The second (0-59).
|
||||
*/
|
||||
time(int hour, int minute, int second);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the hour.
|
||||
*
|
||||
* @return Returns the hour.
|
||||
*/
|
||||
int hour() const { return hour_; }
|
||||
|
||||
/**
|
||||
* Returns the minute.
|
||||
*
|
||||
* @return Returns the minute.
|
||||
*/
|
||||
int minute() const { return minute_; }
|
||||
|
||||
/**
|
||||
* Returns the second.
|
||||
*
|
||||
* @return Returns the second.
|
||||
*/
|
||||
int second() const { return second_; }
|
||||
|
||||
/**
|
||||
* Returns the time in the format hh:mm::ss.
|
||||
*
|
||||
* @return Returns the time in the format hh:mm::ss.
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Checks whether this time is equal to another time.
|
||||
*
|
||||
* @param other Another time.
|
||||
* @return Returns true if this time is equal to the other time, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator==(const time& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this time is not equal to another time.
|
||||
*
|
||||
* @param other Another time.
|
||||
* @return Returns true if this time is not equal to the other time,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator!=(const time& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this time is before another time.
|
||||
*
|
||||
* @param other Another time.
|
||||
* @return Returns true if this time is before the other time, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator< (const time& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this time is after another time.
|
||||
*
|
||||
* @param other Another time.
|
||||
* @return Returns true if this time is after the other time, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator> (const time& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this time is not after another time.
|
||||
*
|
||||
* @param other Another time.
|
||||
* @return Returns true if this time is not after the other time,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator<=(const time& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this time is not before another time.
|
||||
*
|
||||
* @param other Another time.
|
||||
* @return Returns true if this time is not before the other time,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator>=(const time& other) const;
|
||||
|
||||
private:
|
||||
std::uint8_t hour_;
|
||||
std::uint8_t minute_;
|
||||
std::uint8_t second_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
std::ostream& operator<<(std::ostream& out, const time& t);
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Represents a timestamp consisting of year, month, day in month, hour, minute,
|
||||
* second and milliseconds.
|
||||
*/
|
||||
class ODBC_EXPORT timestamp : public date, public time
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a timestamp with value 0000-01-01 00:00:00.000.
|
||||
*/
|
||||
timestamp();
|
||||
|
||||
/**
|
||||
* Creates a timestamp with the given values.
|
||||
*
|
||||
* @param year The year.
|
||||
* @param month The month.
|
||||
* @param day The day.
|
||||
* @param hour The hour.
|
||||
* @param minute The minute.
|
||||
* @param second The second.
|
||||
* @param milliseconds The milliseconds.
|
||||
*/
|
||||
timestamp(int year, int month, int day, int hour, int minute, int second,
|
||||
int milliseconds);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the milliseconds.
|
||||
*
|
||||
* @return Returns the milliseconds.
|
||||
*/
|
||||
int milliseconds() const { return milliseconds_; }
|
||||
|
||||
/**
|
||||
* Returns the timestamp as string in the format yyyy-MM-dd HH:mm:ss.SSS.
|
||||
*
|
||||
* @return Returns the timestamp as string in the format
|
||||
* yyyy-MM-dd HH:mm:ss.SSS.
|
||||
*/
|
||||
std::string toString() const;
|
||||
|
||||
/**
|
||||
* Checks whether this timestamp is equal to another timestamp.
|
||||
*
|
||||
* @param other Another timestamp.
|
||||
* @return Returns true if this timestamp is equal to the other
|
||||
* timestamp, false otherwise.
|
||||
*/
|
||||
bool operator==(const timestamp& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this timestamp is not equal to another timestamp.
|
||||
*
|
||||
* @param other Another timestamp.
|
||||
* @return Returns true if this timestamp is not equal to the other
|
||||
* timestamp, false otherwise.
|
||||
*/
|
||||
bool operator!=(const timestamp& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this timestamp is before another timestamp.
|
||||
*
|
||||
* @param other Another timestamp.
|
||||
* @return Returns true if this timestamp is before the other
|
||||
* timestamp, false otherwise.
|
||||
*/
|
||||
bool operator< (const timestamp& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this timestamp is after another timestamp.
|
||||
*
|
||||
* @param other Another timestamp.
|
||||
* @return Returns true if this timestamp is after the other
|
||||
* timestamp, false otherwise.
|
||||
*/
|
||||
bool operator> (const timestamp& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this timestamp is not after another timestamp.
|
||||
*
|
||||
* @param other Another timestamp.
|
||||
* @return Returns true if this timestamp is not after the other
|
||||
* timestamp, false otherwise.
|
||||
*/
|
||||
bool operator<=(const timestamp& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this timestamp is not before another timestamp.
|
||||
*
|
||||
* @param other Another timestamp.
|
||||
* @return Returns true if this timestamp is not before the other
|
||||
* timestamp, false otherwise.
|
||||
*/
|
||||
bool operator>=(const timestamp& other) const;
|
||||
|
||||
private:
|
||||
std::uint16_t milliseconds_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
std::ostream& operator<<(std::ostream& out, const timestamp& ts);
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Wrapper class for types that don't have a dedicated NULL value.
|
||||
*
|
||||
* @tparam T The type to wrap.
|
||||
*/
|
||||
template<typename T>
|
||||
class Nullable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a NULL value.
|
||||
*/
|
||||
Nullable() : val_(), isNull_(true) { }
|
||||
|
||||
/**
|
||||
* Constructs a non-NULL value.
|
||||
*
|
||||
* @param val The value to copy.
|
||||
*/
|
||||
Nullable(const T& val) : val_(val), isNull_(false) { }
|
||||
|
||||
/**
|
||||
* Constructs a non-NULL value.
|
||||
*
|
||||
* @param val The value to move.
|
||||
*/
|
||||
Nullable(T&& val) : val_(std::move(val)), isNull_(false) { }
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*
|
||||
* @param other The instance to copy.
|
||||
*/
|
||||
Nullable(const Nullable<T>& other);
|
||||
|
||||
/**
|
||||
* Move constructor.
|
||||
*
|
||||
* @param other The instance to move.
|
||||
*/
|
||||
Nullable(Nullable<T>&& other);
|
||||
|
||||
/**
|
||||
* Copy assignment operator.
|
||||
*
|
||||
* @param other The instance to copy.
|
||||
* @return Returns a reference to this instance.
|
||||
*/
|
||||
Nullable<T>& operator=(const Nullable<T>& other);
|
||||
|
||||
/**
|
||||
* Move assignment operator.
|
||||
*
|
||||
* @param other The instance to move.
|
||||
* @return Returns a reference to this instance.
|
||||
*/
|
||||
Nullable<T>& operator=(Nullable<T>&& other);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Checks whether this value is NULL.
|
||||
*
|
||||
* @return Returns true if this value is NULL, false otherwise.
|
||||
*/
|
||||
bool isNull() const { return isNull_; }
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the wrapped value.
|
||||
*
|
||||
* @return Returns a constant reference to the wrapped value.
|
||||
*/
|
||||
const T& operator*() const { return val_; }
|
||||
|
||||
/**
|
||||
* Returns a reference to the wrapped value.
|
||||
*
|
||||
* @return Returns a reference to the wrapped value.
|
||||
*/
|
||||
T& operator*() { return val_; }
|
||||
|
||||
/**
|
||||
* Returns a constant pointer to the wrapped value.
|
||||
*
|
||||
* @return Returns a constant pointer to the wrapped value.
|
||||
*/
|
||||
const T* operator->() const { return &val_; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the wrapped value.
|
||||
*
|
||||
* @return Returns a pointer to the wrapped value.
|
||||
*/
|
||||
T* operator->() { return &val_; }
|
||||
|
||||
/**
|
||||
* Checks whether this value is equal to another value.
|
||||
*
|
||||
* @return Returns true if this value is equal to the other value, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator==(const Nullable<T>& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this value is not equal to another value.
|
||||
*
|
||||
* @return Returns true if this value is not equal to the other value,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator!=(const Nullable<T>& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this value is less than another value.
|
||||
*
|
||||
* A NULL value is never considered less than a non-NULL value.
|
||||
*
|
||||
* @return Returns true if this value is less than the other value, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool operator< (const Nullable<T>& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this value is greater than another value.
|
||||
*
|
||||
* A NULL value is always considered greater than a non-NULL value.
|
||||
*
|
||||
* @return Returns true if this value is greater than the other value,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator> (const Nullable<T>& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this value is not greater than another value.
|
||||
*
|
||||
* A NULL value is always considered greater than a non-NULL value.
|
||||
*
|
||||
* @return Returns true if this value is not greater than the other value,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator<=(const Nullable<T>& other) const;
|
||||
|
||||
/**
|
||||
* Checks whether this value is not less than another value.
|
||||
*
|
||||
* A NULL value is never considered less than a non-NULL value.
|
||||
*
|
||||
* @return Returns true if this value is not less than the other value,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool operator>=(const Nullable<T>& other) const;
|
||||
|
||||
private:
|
||||
T val_;
|
||||
bool isNull_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T, typename... Args>
|
||||
Nullable<T> makeNullable(Args&&... args)
|
||||
{
|
||||
return Nullable<T>(T(args...));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
Nullable<T>::Nullable(const Nullable<T>& other)
|
||||
: val_(other.val_)
|
||||
, isNull_(other.isNull_)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
Nullable<T>::Nullable(Nullable<T>&& other)
|
||||
: val_(std::move(other.val_))
|
||||
, isNull_(other.isNull_)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
Nullable<T>& Nullable<T>::operator=(const Nullable<T>& other)
|
||||
{
|
||||
val_ = other.val_;
|
||||
isNull_ = other.isNull_;
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
Nullable<T>& Nullable<T>::operator=(Nullable<T>&& other)
|
||||
{
|
||||
val_ = std::move(other.val_);
|
||||
isNull_ = other.isNull_;
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool Nullable<T>::operator==(const Nullable<T>& other) const
|
||||
{
|
||||
if (isNull())
|
||||
return other.isNull();
|
||||
if (other.isNull())
|
||||
return false;
|
||||
return **this == *other;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool Nullable<T>::operator!=(const Nullable<T>& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool Nullable<T>::operator<(const Nullable<T>& other) const
|
||||
{
|
||||
if (isNull())
|
||||
return false;
|
||||
if (other.isNull())
|
||||
return true;
|
||||
return **this < *other;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool Nullable<T>::operator>(const Nullable<T>& other) const
|
||||
{
|
||||
if (isNull())
|
||||
return !other.isNull();
|
||||
if (other.isNull())
|
||||
return false;
|
||||
return **this > *other;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool Nullable<T>::operator<=(const Nullable<T>& other) const
|
||||
{
|
||||
return !(*this > other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
bool Nullable<T>::operator>=(const Nullable<T>& other) const
|
||||
{
|
||||
return !(*this < other);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const Nullable<T>& val)
|
||||
{
|
||||
if (val.isNull())
|
||||
out << "<NULL>";
|
||||
else
|
||||
out << *val;
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
typedef Nullable<bool> Boolean;
|
||||
typedef Nullable<std::int8_t> Byte;
|
||||
typedef Nullable<std::uint8_t> UByte;
|
||||
typedef Nullable<std::int16_t> Short;
|
||||
typedef Nullable<std::uint16_t> UShort;
|
||||
typedef Nullable<std::int32_t> Int;
|
||||
typedef Nullable<std::uint32_t> UInt;
|
||||
typedef Nullable<std::int64_t> Long;
|
||||
typedef Nullable<std::uint64_t> ULong;
|
||||
typedef Nullable<decimal> Decimal;
|
||||
typedef Nullable<float> Float;
|
||||
typedef Nullable<double> Double;
|
||||
typedef Nullable<std::string> String;
|
||||
typedef Nullable<std::u16string> NString;
|
||||
typedef Nullable<std::vector<char>> Binary;
|
||||
typedef Nullable<date> Date;
|
||||
typedef Nullable<time> Time;
|
||||
typedef Nullable<timestamp> Timestamp;
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
inline std::ostream& operator<<(std::ostream& out, const NString& val)
|
||||
{
|
||||
if (val.isNull()) {
|
||||
out << "<NULL>";
|
||||
return out;
|
||||
}
|
||||
for (char16_t c : *val)
|
||||
out << ((c <= u'~') ? (char)c : '?');
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
inline std::ostream& operator<<(std::ostream& out, const Binary& val)
|
||||
{
|
||||
if (val.isNull()) {
|
||||
out << "<NULL>";
|
||||
return out;
|
||||
}
|
||||
const char* hexdigits = "0123456789ABCDEF";
|
||||
for (std::size_t i = 0; i < val->size(); ++i)
|
||||
{
|
||||
if ((i % 16) == 0)
|
||||
out << std::endl;
|
||||
else if (((i + 8) % 16) == 0)
|
||||
out << " ";
|
||||
else
|
||||
out << ' ';
|
||||
unsigned char uc = (unsigned char)(*val)[i];
|
||||
out << hexdigits[uc >> 4];
|
||||
out << hexdigits[uc & 0xF];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
60
external/odbccpp/src/odbc/Util.cpp
vendored
Normal file
60
external/odbccpp/src/odbc/Util.cpp
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
#include <sstream>
|
||||
#include <odbc/Util.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace {
|
||||
//------------------------------------------------------------------------------
|
||||
void escape(const char* s, ostream& out)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
switch (*s)
|
||||
{
|
||||
case '"':
|
||||
out << "\"\"";
|
||||
break;
|
||||
default:
|
||||
out << *s;
|
||||
break;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
string Util::quote(const std::string& s)
|
||||
{
|
||||
return quote(s.c_str());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string Util::quote(const char* s)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "\"";
|
||||
escape(s, os);
|
||||
os << "\"";
|
||||
return os.str();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string Util::quote(const std::string& schema, const std::string& table)
|
||||
{
|
||||
return quote(schema.c_str(), table.c_str());
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
string Util::quote(const char* schema, const char* table)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "\"";
|
||||
escape(schema, os);
|
||||
os << "\".\"";
|
||||
escape(table, os);
|
||||
os << "\"";
|
||||
return os.str();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
68
external/odbccpp/src/odbc/Util.h
vendored
Normal file
68
external/odbccpp/src/odbc/Util.h
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef ODBC_UTIL_H_INCLUDED
|
||||
#define ODBC_UTIL_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <string>
|
||||
#include <odbc/Config.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Hosts various utility functions.
|
||||
*/
|
||||
class ODBC_EXPORT Util
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Quotes an identifier.
|
||||
*
|
||||
* The function adds a "-character at the start and end of the string. If
|
||||
* the string contains a "-character, it is escaped by duplicating it, e.g.
|
||||
* a"b becomes "a""b".
|
||||
*
|
||||
* @param s The identifier to quote.
|
||||
* @return Returns the quoted identifier.
|
||||
*/
|
||||
static std::string quote(const std::string& s);
|
||||
|
||||
/**
|
||||
* Quotes an identifier.
|
||||
*
|
||||
* The function adds a "-character at the start and end of the string. If
|
||||
* the string contains a "-character, it is escaped by duplicating it, e.g.
|
||||
* a"b becomes "a""b".
|
||||
*
|
||||
* @param s The identifier to quote.
|
||||
* @return Returns the quoted identifier.
|
||||
*/
|
||||
static std::string quote(const char* s);
|
||||
|
||||
/**
|
||||
* Quotes an schema/table name-pair.
|
||||
*
|
||||
* This function quotes the schema and table and separates then by a dot.
|
||||
*
|
||||
* @param schema The schema.
|
||||
* @param table The table.
|
||||
* @return Returns the quoted schema/table name-pair.
|
||||
*/
|
||||
static std::string quote(
|
||||
const std::string& schema,
|
||||
const std::string& table);
|
||||
|
||||
/**
|
||||
* Quotes an schema/table name-pair.
|
||||
*
|
||||
* This function quotes the schema and table and separates then by a dot.
|
||||
*
|
||||
* @param schema The schema.
|
||||
* @param table The table.
|
||||
* @return Returns the quoted schema/table name-pair.
|
||||
*/
|
||||
static std::string quote(
|
||||
const char* schema,
|
||||
const char* table);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
380
external/odbccpp/src/odbc/internal/Batch.cpp
vendored
Normal file
380
external/odbccpp/src/odbc/internal/Batch.cpp
vendored
Normal file
@ -0,0 +1,380 @@
|
||||
#include <odbc/Exception.h>
|
||||
#include <odbc/internal/Batch.h>
|
||||
#include <odbc/internal/Macros.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
#include <odbc/internal/ParameterData.h>
|
||||
#include <odbc/internal/TypeInfo.h>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
// Batch class
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::addRow()
|
||||
{
|
||||
if (valueTypeInfos_.empty())
|
||||
initialize();
|
||||
else
|
||||
checkAndCompleteValueTypes();
|
||||
|
||||
if (batchBlocks_.empty() || (blockRow_ == rowsPerBlock_))
|
||||
{
|
||||
// We might fetch the blocks from a Batch-object specific pool in a more
|
||||
// sophisticated version.
|
||||
batchBlocks_.emplace_back(rowsPerBlock_ * rowLength_);
|
||||
blockRow_ = 0;
|
||||
}
|
||||
|
||||
dataSize_ += rowLength_;
|
||||
Block& block = batchBlocks_.back();
|
||||
char* dest = block.getData() + rowLength_ * blockRow_;
|
||||
for (size_t i = 0; i < parameters_.size(); ++i)
|
||||
writeParameter(dest + paramDataOffsets_[i], parameters_[i]);
|
||||
++blockRow_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::clear()
|
||||
{
|
||||
if (batchBlocks_.empty())
|
||||
return;
|
||||
|
||||
// Before we can clear the vector with batch blocks, we have to deal with
|
||||
// the buffers on the heap. For the last row, we have to return ownership
|
||||
// to the parameter data. For previous rows, we have to delete the heap
|
||||
// buffer.
|
||||
for (size_t i = 0; i < parameters_.size(); ++i)
|
||||
clearBatchParameter(i);
|
||||
|
||||
// We might want to put the blocks into a Batch-object specific block pool
|
||||
// instead in a more sophisticated version.
|
||||
batchBlocks_.clear();
|
||||
blockRow_ = 0;
|
||||
dataSize_ = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::execute(void* hstmt)
|
||||
{
|
||||
if (batchBlocks_.empty())
|
||||
return;
|
||||
|
||||
// Ensure that the batch is cleared, even if an exception occurs.
|
||||
Clearer clearer(*this);
|
||||
|
||||
NextRowInfo nextRowInfo(rowLength_);
|
||||
for (size_t i = 0; i < (batchBlocks_.size() - 1); ++i)
|
||||
{
|
||||
bindBlockParameters(batchBlocks_[i].getData(), rowsPerBlock_, hstmt);
|
||||
executeBlockBatch(batchBlocks_[i].getData(), rowsPerBlock_,
|
||||
nextRowInfo, hstmt);
|
||||
}
|
||||
bindBlockParameters(batchBlocks_.back().getData(), blockRow_, hstmt);
|
||||
executeBlockBatch(batchBlocks_.back().getData(), blockRow_,
|
||||
nextRowInfo, hstmt);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t Batch::getDataSize() const
|
||||
{
|
||||
return dataSize_;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::writeParameter(char* dest, ParameterData& pd)
|
||||
{
|
||||
int16_t valueType = pd.getValueType();
|
||||
size_t valueSize = TypeInfo::getSizeOfValueFromValueType(valueType);
|
||||
if (valueSize == 0)
|
||||
writeVariableSizeParameter(dest, pd);
|
||||
else
|
||||
writeFixedSizeParameter(dest, pd);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::writeVariableSizeParameter(char* dest, ParameterData& pd)
|
||||
{
|
||||
if (pd.isNull())
|
||||
{
|
||||
memcpy(dest, pd.getLenIndPtr(), sizeof(SQLLEN));
|
||||
}
|
||||
else if (pd.getSize() <= ParameterData::INPLACE_BYTES)
|
||||
{
|
||||
memcpy(dest, pd.getLenIndPtr(), sizeof(SQLLEN));
|
||||
dest += sizeof(SQLLEN);
|
||||
memcpy(dest, pd.getData(), pd.getSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
// We take over the ownership of the heap buffer and store a pointer
|
||||
// to the data on the heap in the data field of the row
|
||||
SQLLEN ind = SQL_LEN_DATA_AT_EXEC((SQLLEN)pd.getSize());
|
||||
memcpy(dest, &ind, sizeof(SQLLEN));
|
||||
dest += sizeof(SQLLEN);
|
||||
const void* data = pd.getData();
|
||||
memcpy(dest, &data, sizeof(data));
|
||||
if (pd.ownsHeapBuffer())
|
||||
pd.releaseHeapBufferOwnership();
|
||||
dataSize_ += pd.getSize();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::writeFixedSizeParameter(char* dest, ParameterData& pd)
|
||||
{
|
||||
memcpy(dest, pd.getLenIndPtr(), sizeof(SQLLEN));
|
||||
if (!pd.isNull())
|
||||
{
|
||||
dest += sizeof(SQLLEN);
|
||||
memcpy(dest, pd.getData(), pd.getSize());
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::clearBatchParameter(size_t index)
|
||||
{
|
||||
// We don't need to do anything for fixed size parameters
|
||||
if (TypeInfo::getSizeOfValueFromValueType(valueTypeInfos_[index].type) != 0)
|
||||
return;
|
||||
|
||||
ParameterData& pd = parameters_[index];
|
||||
|
||||
// If the current parameter uses a heap buffer and has transferred
|
||||
// ownership to this batch, we must transfer back the ownership. Afterwards,
|
||||
// we have to delete all other buffers on the heap. The same buffer might
|
||||
// be used in several rows, so we have to take care to delete it only once.
|
||||
// We use the fact that the same buffer can only be used in consecutive
|
||||
// rows, so we can just remember the last one.
|
||||
const void* preserve = nullptr;
|
||||
const void* last = nullptr;
|
||||
if (pd.usesHeapBuffer() && !pd.ownsHeapBuffer())
|
||||
{
|
||||
pd.restoreHeapBufferOwnership();
|
||||
preserve = pd.getData();
|
||||
}
|
||||
|
||||
size_t offset = paramDataOffsets_[index];
|
||||
for (size_t i = 0; i < (batchBlocks_.size() - 1); ++i)
|
||||
{
|
||||
char* data = batchBlocks_[i].getData() + offset;
|
||||
last = clearBatchParameterBlock(data, rowsPerBlock_, last, preserve);
|
||||
}
|
||||
char* data = batchBlocks_.back().getData() + offset;
|
||||
clearBatchParameterBlock(data, blockRow_, last, preserve);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
const void* Batch::clearBatchParameterBlock(char* data, size_t numRows,
|
||||
const void* last, const void* preserve)
|
||||
{
|
||||
for (size_t i = 0; i < numRows; ++i, data += rowLength_)
|
||||
{
|
||||
SQLLEN len;
|
||||
memcpy(&len, data, sizeof(SQLLEN));
|
||||
if ((len != SQL_NULL_DATA) && (len < 0))
|
||||
{
|
||||
void* buffer;
|
||||
memcpy(&buffer, data + sizeof(SQLLEN), sizeof(void*));
|
||||
if ((buffer != last) && (buffer != preserve))
|
||||
{
|
||||
free(buffer);
|
||||
last = buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return last;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::bindBlockParameters(const char* blockData, size_t numRows,
|
||||
void* hstmt)
|
||||
{
|
||||
EXEC_STMT(SQLFreeStmt, hstmt, SQL_UNBIND);
|
||||
EXEC_STMT(SQLFreeStmt, hstmt, SQL_RESET_PARAMS);
|
||||
EXEC_STMT(SQLSetStmtAttr, hstmt, SQL_ATTR_PARAM_BIND_TYPE,
|
||||
(SQLPOINTER)rowLength_, SQL_IS_UINTEGER);
|
||||
EXEC_STMT(SQLSetStmtAttr, hstmt, SQL_ATTR_PARAMSET_SIZE,
|
||||
(SQLPOINTER)numRows, SQL_IS_UINTEGER);
|
||||
|
||||
for (size_t i = 0; i < valueTypeInfos_.size(); ++i)
|
||||
{
|
||||
const ValueTypeInfo& vti = valueTypeInfos_[i];
|
||||
SQLLEN* lenInd = (SQLLEN*)(blockData + paramDataOffsets_[i]);
|
||||
EXEC_STMT(SQLBindParameter, hstmt, (SQLUSMALLINT)(i + 1),
|
||||
SQL_PARAM_INPUT, vti.type,
|
||||
TypeInfo::getParamTypeForValueType(vti.type),
|
||||
vti.columnSize, vti.decimalDigits,
|
||||
(SQLPOINTER)(lenInd + 1), 0, lenInd);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::executeBlockBatch(const char* blockData, size_t numRows,
|
||||
NextRowInfo& nextRowInfo, void* hstmt)
|
||||
{
|
||||
SQLRETURN rc = SQLExecute(hstmt);
|
||||
char* paramData = nullptr;
|
||||
if (rc == SQL_NEED_DATA)
|
||||
{
|
||||
// For variable row size parameters, determine the first variable size
|
||||
// value of the column.
|
||||
for (size_t i = 0; i < valueTypeInfos_.size(); ++i)
|
||||
{
|
||||
size_t valueSize = TypeInfo::getSizeOfValueFromValueType(
|
||||
valueTypeInfos_[i].type);
|
||||
if (valueSize != 0)
|
||||
continue;
|
||||
size_t nextRow = findNextVarSizeRow(
|
||||
blockData + paramDataOffsets_[i], 0, numRows);
|
||||
nextRowInfo.setNextRow(paramDataOffsets_[i], nextRow);
|
||||
}
|
||||
rc = SQLParamData(hstmt, (SQLPOINTER*)¶mData);
|
||||
}
|
||||
while (rc == SQL_NEED_DATA)
|
||||
{
|
||||
// Compute the offset of the length/indicator field in the row
|
||||
size_t offset = (paramData - sizeof(SQLLEN)) - blockData;
|
||||
|
||||
// Get the row to send
|
||||
size_t nextRow = nextRowInfo.getNextRow(offset);
|
||||
|
||||
// Compute the pointer to the field value. This field contains the
|
||||
// pointer to the buffer on the heap containing the actual data.
|
||||
char* dataPtr = paramData + nextRow * rowLength_;
|
||||
char* data;
|
||||
memcpy(&data, dataPtr, sizeof(char*));
|
||||
|
||||
// Use the length/indicator field to compute the size of the data
|
||||
SQLLEN len;
|
||||
memcpy(&len, dataPtr - sizeof(SQLLEN), sizeof(SQLLEN));
|
||||
len = SQL_LEN_DATA_AT_EXEC(len);
|
||||
|
||||
EXEC_STMT(SQLPutData, hstmt, data, len);
|
||||
|
||||
// Advance to the next row with a value on the heap in the current
|
||||
// column
|
||||
nextRow = findNextVarSizeRow(
|
||||
blockData + offset, nextRow + 1, numRows);
|
||||
nextRowInfo.setNextRow(offset, nextRow);
|
||||
|
||||
rc = SQLParamData(hstmt, (SQLPOINTER*)¶mData);
|
||||
}
|
||||
Exception::checkForError(rc, SQL_HANDLE_STMT, hstmt);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t Batch::findNextVarSizeRow(const char* paramDataFirstRow, size_t startRow,
|
||||
size_t numRows)
|
||||
{
|
||||
const char* data = paramDataFirstRow + startRow * rowLength_;
|
||||
for (size_t row = startRow; row < numRows; ++row, data += rowLength_)
|
||||
{
|
||||
SQLLEN ind;
|
||||
memcpy(&ind, data, sizeof(SQLLEN));
|
||||
if ((ind != SQL_NULL_DATA) && (ind < 0))
|
||||
return row;
|
||||
}
|
||||
return numRows;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::initialize()
|
||||
{
|
||||
assert(!parameters_.empty());
|
||||
valueTypeInfos_.resize(parameters_.size());
|
||||
paramDataOffsets_.resize(parameters_.size());
|
||||
dataSize_ = 0;
|
||||
rowLength_ = 0;
|
||||
for (size_t i = 0; i < parameters_.size(); ++i)
|
||||
{
|
||||
const ParameterData& param = parameters_[i];
|
||||
assert(param.isInitialized());
|
||||
valueTypeInfos_[i] = { param.getValueType(),
|
||||
param.getColumnSize(), param.getDecimalDigits() };
|
||||
paramDataOffsets_[i] = rowLength_;
|
||||
rowLength_ += sizeof(SQLLEN);
|
||||
size_t valueSize =
|
||||
TypeInfo::getSizeOfValueFromValueType(param.getValueType());
|
||||
rowLength_ +=
|
||||
(valueSize == 0) ? ParameterData::INPLACE_BYTES : valueSize;
|
||||
}
|
||||
rowsPerBlock_ = BLOCK_SIZE / rowLength_;
|
||||
if (rowsPerBlock_ < MIN_NUM_ROWS)
|
||||
rowsPerBlock_ = MIN_NUM_ROWS;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::checkAndCompleteValueTypes()
|
||||
{
|
||||
assert(parameters_.size() == valueTypeInfos_.size());
|
||||
for (size_t i = 0; i < parameters_.size(); ++i)
|
||||
{
|
||||
const ParameterData& param = parameters_[i];
|
||||
assert(param.isInitialized());
|
||||
ValueTypeInfo& valTypeInfo = valueTypeInfos_[i];
|
||||
ODBC_CHECK(
|
||||
param.getValueType() == valTypeInfo.type,
|
||||
"Value type of parameter " << (i + 1) << " does not match the "
|
||||
"previous value type used in the batch. Before it was "
|
||||
<< TypeInfo::getValueTypeName(valTypeInfo.type) << ", now it is "
|
||||
<< TypeInfo::getValueTypeName(
|
||||
param.getValueType()) << ".");
|
||||
|
||||
if (param.getValueType() == SQL_C_NUMERIC)
|
||||
{
|
||||
// columnSize and decimalDigits might not be set during the first
|
||||
// call of addRow method. Therefore, we set their values here.
|
||||
if (valTypeInfo.columnSize == 0)
|
||||
{
|
||||
valTypeInfo.columnSize = param.getColumnSize();
|
||||
valTypeInfo.decimalDigits = param.getDecimalDigits();
|
||||
}
|
||||
|
||||
ODBC_CHECK(
|
||||
param.getColumnSize() == valTypeInfo.columnSize &&
|
||||
param.getDecimalDigits() == valTypeInfo.decimalDigits,
|
||||
"Precision and scale values of parameter " << (i + 1) << " do "
|
||||
"not match the previous values used in the batch. Before it "
|
||||
"was numeric(" << valTypeInfo.columnSize << "," <<
|
||||
valTypeInfo.decimalDigits << "), now it is numeric(" <<
|
||||
param.getColumnSize() << ", " << param.getDecimalDigits() <<
|
||||
").");
|
||||
}
|
||||
|
||||
// Update column size for types with variable size
|
||||
if (TypeInfo::getSizeOfValueFromValueType(param.getValueType()) == 0)
|
||||
{
|
||||
valTypeInfo.columnSize =
|
||||
max(valTypeInfo.columnSize, param.getColumnSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Batch::Block class
|
||||
//------------------------------------------------------------------------------
|
||||
Batch::Block::Block(size_t size)
|
||||
{
|
||||
data_ = (char*)malloc(size);
|
||||
if (data_ == nullptr)
|
||||
throw bad_alloc();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Batch::Block::Block(Batch::Block&& other) : data_(other.data_)
|
||||
{
|
||||
other.data_ = nullptr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Batch::Block::~Block()
|
||||
{
|
||||
free(data_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Batch::NextRowInfo class
|
||||
//------------------------------------------------------------------------------
|
||||
void Batch::NextRowInfo::setNextRow(size_t offset, size_t nextRow)
|
||||
{
|
||||
char* data = row_.getData() + offset;
|
||||
memcpy(data, &nextRow, sizeof(size_t));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t Batch::NextRowInfo::getNextRow(size_t offset) const
|
||||
{
|
||||
size_t ret;
|
||||
const char* data = row_.getData() + offset;
|
||||
memcpy(&ret, data, sizeof(size_t));
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
225
external/odbccpp/src/odbc/internal/Batch.h
vendored
Normal file
225
external/odbccpp/src/odbc/internal/Batch.h
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
#ifndef ODBC_INTERNAL_BATCH_H_INCLUDED
|
||||
#define ODBC_INTERNAL_BATCH_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <odbc/Forwards.h>
|
||||
#include <odbc/RefCounted.h>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
class ParameterData;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* A batch of rows consisting of parameter values.
|
||||
*
|
||||
* A batch consists of blocks that are made up by rows.
|
||||
*
|
||||
* A row contains a length/indicator field and a value field for each parameter.
|
||||
* The size of the value field depends on the value type used for the parameter.
|
||||
* The value type must be the same for all parameter values in the same column.
|
||||
*
|
||||
* In case of fixed size value types, the fixed size is used as size for the
|
||||
* value field. In case of variable size value types, the value of
|
||||
* ParameterData::INPLACE_BYTES is used as size.
|
||||
*
|
||||
* When a row is added to the batch, fixed size values and variable size values
|
||||
* with a size of at most ParameterData::INPLACE_BYTES are copied over to the
|
||||
* row. The batch will take over the heap buffer ownership of parameter values
|
||||
* that are larger than ParameterData::INPLACE_BYTES.
|
||||
*/
|
||||
class Batch : public RefCounted
|
||||
{
|
||||
/// The maximum size of a batch block in bytes.
|
||||
constexpr static std::size_t BLOCK_SIZE = 256 * 1024;
|
||||
|
||||
/// Minimum number of rows per batch block, even if that results in blocks
|
||||
/// larger than BLOCK_SIZE.
|
||||
constexpr static std::size_t MIN_NUM_ROWS = 128;
|
||||
|
||||
class NextRowInfo;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param parameters Reference to the PreparedStatement's parameters
|
||||
* vector.
|
||||
*/
|
||||
Batch(std::vector<ParameterData>& parameters) : parameters_(parameters) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~Batch() { clear(); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Adds a row using the current PreparedStatement's parameter values.
|
||||
*
|
||||
* For all but the first row this method will verify that the value types
|
||||
* of the parameters matches the value types in the batch. If there is a
|
||||
* mismatch, an exception will be thrown.
|
||||
*/
|
||||
void addRow();
|
||||
|
||||
/**
|
||||
* Clears the batch.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Executes the batch.
|
||||
*
|
||||
* The batch will be cleared after execution, even if an error occurred.
|
||||
*
|
||||
* @param hstmt The ODBC statement andle.
|
||||
*/
|
||||
void execute(void* hstmt);
|
||||
|
||||
/**
|
||||
* Retrieves the number of bytes required by the batch.
|
||||
*
|
||||
* @return Returns the number of bytes required by the batch.
|
||||
*/
|
||||
std::size_t getDataSize() const;
|
||||
|
||||
private:
|
||||
void writeParameter(char* dest, ParameterData& pd);
|
||||
void writeVariableSizeParameter(char* dest, ParameterData& pd);
|
||||
void writeFixedSizeParameter(char* dest, ParameterData& pd);
|
||||
|
||||
void clearBatchParameter(std::size_t index);
|
||||
const void* clearBatchParameterBlock(
|
||||
char* data,
|
||||
std::size_t numRows,
|
||||
const void* last,
|
||||
const void* preserve);
|
||||
|
||||
void bindBlockParameters(
|
||||
const char* blockData,
|
||||
std::size_t numRows,
|
||||
void* hstmt);
|
||||
void executeBlockBatch(
|
||||
const char* blockData,
|
||||
std::size_t numRows,
|
||||
NextRowInfo& nextRowInfo,
|
||||
void* hstmt);
|
||||
size_t findNextVarSizeRow(
|
||||
const char* paramDataFirstRow,
|
||||
size_t startRow,
|
||||
size_t numRows);
|
||||
|
||||
void initialize();
|
||||
void checkAndCompleteValueTypes();
|
||||
|
||||
private:
|
||||
/**
|
||||
* A block of memory.
|
||||
*
|
||||
* Could be replaced by vector<char> with the desired size. However,
|
||||
* vector<char> has the disadvantage that it unncecessarily initializes
|
||||
* the allocated memory.
|
||||
*/
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
Block(std::size_t size);
|
||||
Block(Block&& other);
|
||||
~Block();
|
||||
|
||||
Block(const Block& other) = delete;
|
||||
Block& operator=(const Block& other) = delete;
|
||||
|
||||
public:
|
||||
char* getData() const { return data_; }
|
||||
|
||||
private:
|
||||
char* data_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class that ensures that the batch is cleared.
|
||||
*/
|
||||
class Clearer
|
||||
{
|
||||
public:
|
||||
Clearer(Batch& parent) : parent_(parent) { }
|
||||
~Clearer() { parent_.clear(); }
|
||||
private:
|
||||
Batch& parent_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class storing the next row that contains a value in a heap buffer
|
||||
* and requires SQLPutData() (for each column).
|
||||
*
|
||||
* Implementing this is a bit tricky. When binding parameters we have to
|
||||
* give the pointer to the data in the first row because this pointer will
|
||||
* be used by the ODBC driver to consume the inplace values.
|
||||
*
|
||||
* This pointer will also be returned by SQLParamData() when we need to send
|
||||
* the data of a value in a heap buffer. We can easily compute the row
|
||||
* offset, but finding the index of the parameter would require a lookup
|
||||
* in some offset-to-index map. Instead we just allocate memory for a
|
||||
* whole row and store the information on the next row at the offset we can
|
||||
* easily compute.
|
||||
*/
|
||||
class NextRowInfo
|
||||
{
|
||||
public:
|
||||
NextRowInfo(std::size_t rowLength) : row_(rowLength) { }
|
||||
|
||||
public:
|
||||
void setNextRow(std::size_t offset, std::size_t nextRow);
|
||||
std::size_t getNextRow(std::size_t offset) const;
|
||||
|
||||
private:
|
||||
Block row_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class for storing parameter value information.
|
||||
*/
|
||||
struct ValueTypeInfo
|
||||
{
|
||||
std::int16_t type;
|
||||
std::size_t columnSize;
|
||||
std::int16_t decimalDigits;
|
||||
};
|
||||
|
||||
private:
|
||||
/// Reference to the PreparedStatement's parameters
|
||||
std::vector<ParameterData>& parameters_;
|
||||
|
||||
/// Parameter value information of the columns. Initialized when the first
|
||||
/// row is added to the batch.
|
||||
std::vector<ValueTypeInfo> valueTypeInfos_;
|
||||
|
||||
/// Offsets of the length/indicator fields in a row, which is immediately
|
||||
/// followed by the value field. Initialized when the first row is added to
|
||||
/// the batch.
|
||||
std::vector<std::size_t> paramDataOffsets_;
|
||||
|
||||
/// The length of a row. Initialized when the first row is added to the
|
||||
/// batch.
|
||||
std::size_t rowLength_;
|
||||
|
||||
/// Number of rows per block. Calculated when the first row is added to the
|
||||
/// batch.
|
||||
std::size_t rowsPerBlock_;
|
||||
|
||||
/// Vector with batch blocks. Will grow on demand.
|
||||
std::vector<Block> batchBlocks_;
|
||||
|
||||
/// The number of rows in the last block (in batchBlocks_.back()).
|
||||
std::size_t blockRow_;
|
||||
|
||||
/// The number of bytes required for the batch.
|
||||
std::size_t dataSize_;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
43
external/odbccpp/src/odbc/internal/Macros.h
vendored
Normal file
43
external/odbccpp/src/odbc/internal/Macros.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef ODBC_INTERNAL_MACROS_H_INCLUDED
|
||||
#define ODBC_INTERNAL_MACROS_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <sstream>
|
||||
//------------------------------------------------------------------------------
|
||||
#define EXEC_DBC(function, handle, ...) \
|
||||
do { \
|
||||
SQLRETURN rc = function(handle, ##__VA_ARGS__); \
|
||||
::odbc::Exception::checkForError(rc, SQL_HANDLE_DBC, handle); \
|
||||
} while (false)
|
||||
//------------------------------------------------------------------------------
|
||||
#define EXEC_ENV(function, handle, ...) \
|
||||
do { \
|
||||
SQLRETURN rc = function(handle, ##__VA_ARGS__); \
|
||||
::odbc::Exception::checkForError(rc, SQL_HANDLE_ENV, handle); \
|
||||
} while (false)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define EXEC_STMT(function, handle, ...) \
|
||||
do { \
|
||||
SQLRETURN rc = function(handle, ##__VA_ARGS__); \
|
||||
::odbc::Exception::checkForError(rc, SQL_HANDLE_STMT, handle); \
|
||||
} while (false)
|
||||
//------------------------------------------------------------------------------
|
||||
#define ODBC_FAIL(msg) \
|
||||
do { \
|
||||
::std::ostringstream out; \
|
||||
out << msg; \
|
||||
throw ::odbc::Exception(out.str()); \
|
||||
} while (false)
|
||||
//------------------------------------------------------------------------------
|
||||
#define ODBC_CHECK(condition, msg) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
::std::ostringstream out; \
|
||||
out << msg; \
|
||||
throw ::odbc::Exception(out.str()); \
|
||||
} \
|
||||
} while (false)
|
||||
//------------------------------------------------------------------------------
|
||||
#define IS_FLAG_SET(value, flag) (((value & flag) == flag))
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
12
external/odbccpp/src/odbc/internal/Odbc.h
vendored
Normal file
12
external/odbccpp/src/odbc/internal/Odbc.h
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef ODBC_INTERNAL_ODBC_H_INCLUDED
|
||||
#define ODBC_INTERNAL_ODBC_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
# define NOMINMAX
|
||||
# define DNOMINMAX
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
190
external/odbccpp/src/odbc/internal/ParameterData.cpp
vendored
Normal file
190
external/odbccpp/src/odbc/internal/ParameterData.cpp
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
#include <new>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
#include <odbc/internal/ParameterData.h>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
ParameterData::ParameterData()
|
||||
: state_(UNINITIALIZED)
|
||||
, valueType_(0)
|
||||
, columnSize_(0)
|
||||
, decimalDigits_(0)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ParameterData::ParameterData(ParameterData&& other)
|
||||
: state_(other.state_)
|
||||
, valueType_(other.valueType_)
|
||||
, columnSize_(other.columnSize_)
|
||||
, decimalDigits_(other.decimalDigits_)
|
||||
, size_(other.size_)
|
||||
{
|
||||
switch (state_)
|
||||
{
|
||||
case UNINITIALIZED:
|
||||
case IS_NULL:
|
||||
break;
|
||||
case NORMAL_INPLACE:
|
||||
memcpy(inplaceData_, other.inplaceData_, size_);
|
||||
break;
|
||||
case NORMAL_HEAP_OWNING:
|
||||
case NORMAL_HEAP_NOT_OWNING:
|
||||
capacity_ = other.capacity_;
|
||||
heapData_ = other.heapData_;
|
||||
break;
|
||||
}
|
||||
other.state_ = UNINITIALIZED;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ParameterData::~ParameterData()
|
||||
{
|
||||
if (state_ == NORMAL_HEAP_OWNING)
|
||||
free(heapData_);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ParameterData& ParameterData::operator=(ParameterData&& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
if (state_ == NORMAL_HEAP_OWNING)
|
||||
free(heapData_);
|
||||
|
||||
state_ = other.state_;
|
||||
valueType_ = other.valueType_;
|
||||
columnSize_ = other.columnSize_;
|
||||
decimalDigits_ = other.decimalDigits_;
|
||||
size_ = other.size_;
|
||||
switch (state_)
|
||||
{
|
||||
case UNINITIALIZED:
|
||||
break;
|
||||
case IS_NULL:
|
||||
break;
|
||||
case NORMAL_INPLACE:
|
||||
memcpy(inplaceData_, other.inplaceData_, size_);
|
||||
break;
|
||||
case NORMAL_HEAP_OWNING:
|
||||
case NORMAL_HEAP_NOT_OWNING:
|
||||
capacity_ = other.capacity_;
|
||||
heapData_ = other.heapData_;
|
||||
break;
|
||||
}
|
||||
other.state_ = UNINITIALIZED;
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::setValue(int16_t type, const void* value, size_t size)
|
||||
{
|
||||
// TODO: Maybe we'd like to set the value on the heap even if it fitted into
|
||||
// the inplace buffer. This would avoid re-allocations if a value slightly
|
||||
// larger then the inplace buffer is set.
|
||||
if (size <= INPLACE_BYTES)
|
||||
setValueInplace(value, size);
|
||||
else
|
||||
setValueOnHeap(value, size);
|
||||
valueType_ = type;
|
||||
columnSize_ = 0;
|
||||
decimalDigits_ = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::setNull(int16_t type)
|
||||
{
|
||||
if (state_ == NORMAL_HEAP_OWNING)
|
||||
free(heapData_);
|
||||
valueType_ = type;
|
||||
state_ = IS_NULL;
|
||||
size_ = SQL_NULL_DATA;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::clear()
|
||||
{
|
||||
if (state_ == NORMAL_HEAP_OWNING)
|
||||
free(heapData_);
|
||||
state_ = UNINITIALIZED;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
const void* ParameterData::getData() const
|
||||
{
|
||||
switch (state_)
|
||||
{
|
||||
case UNINITIALIZED:
|
||||
case IS_NULL:
|
||||
assert(false);
|
||||
return nullptr;
|
||||
case NORMAL_INPLACE:
|
||||
return inplaceData_;
|
||||
case NORMAL_HEAP_OWNING:
|
||||
case NORMAL_HEAP_NOT_OWNING:
|
||||
return heapData_;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool ParameterData::usesHeapBuffer() const
|
||||
{
|
||||
return (state_ == NORMAL_HEAP_OWNING) || (state_ == NORMAL_HEAP_NOT_OWNING);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::releaseHeapBufferOwnership()
|
||||
{
|
||||
assert(state_ == NORMAL_HEAP_OWNING);
|
||||
state_ = NORMAL_HEAP_NOT_OWNING;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::restoreHeapBufferOwnership()
|
||||
{
|
||||
assert(state_ == NORMAL_HEAP_NOT_OWNING);
|
||||
state_ = NORMAL_HEAP_OWNING;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::setValueInplace(const void* value, size_t size)
|
||||
{
|
||||
if (state_ == NORMAL_HEAP_OWNING)
|
||||
free(heapData_);
|
||||
state_ = NORMAL_INPLACE;
|
||||
size_ = size;
|
||||
memcpy(inplaceData_, value, size);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ParameterData::setValueOnHeap(const void* value, size_t size)
|
||||
{
|
||||
if (state_ != NORMAL_HEAP_OWNING)
|
||||
{
|
||||
void* data = malloc(size);
|
||||
if (data == nullptr)
|
||||
throw bad_alloc();
|
||||
memcpy(data, value, size);
|
||||
capacity_ = size;
|
||||
heapData_ = data;
|
||||
state_ = NORMAL_HEAP_OWNING;
|
||||
size_ = size;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t reallocIfLess = (size_t)(LOAD_FACTOR * (double)capacity_);
|
||||
if ((size > capacity_) || (size < reallocIfLess))
|
||||
{
|
||||
void* data = malloc(size);
|
||||
if (data == nullptr)
|
||||
throw bad_alloc();
|
||||
memcpy(data, value, size);
|
||||
free(heapData_);
|
||||
capacity_ = size;
|
||||
heapData_ = data;
|
||||
size_ = size;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(heapData_, value, size);
|
||||
size_ = size;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
284
external/odbccpp/src/odbc/internal/ParameterData.h
vendored
Normal file
284
external/odbccpp/src/odbc/internal/ParameterData.h
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
#ifndef ODBC_INTERNAL_PARAMETERDATA_H_INCLUDED
|
||||
#define ODBC_INTERNAL_PARAMETERDATA_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <cstddef>
|
||||
#include <cinttypes>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Class that holds the data of a parameter.
|
||||
*
|
||||
* The data of a parameter consists of its type and its value, which can be
|
||||
* NULL.
|
||||
*
|
||||
* This class has a small inplace buffer that can hold numeric, date/time-
|
||||
* related types and short strings without the need for additional memory
|
||||
* allocation from the heap. Larger values are allocated from the heap.
|
||||
*
|
||||
* The data of this class is intended to be transferrable to a block with batch
|
||||
* data. Values in the inplace buffer are just copied over. If a value is
|
||||
* located in a buffer allocated from the heap, the ownership of the heap buffer
|
||||
* is transferred to the batch block.
|
||||
*
|
||||
* As the data in the buffer can be re-added (i.e. without the user setting a
|
||||
* new value for the next row), we have to keep the pointer to the data, but
|
||||
* have to mark that we don't own the heap buffer anymore.
|
||||
*
|
||||
* Ownership of the buffer can also be transferred back to a ParameterData
|
||||
* object. This happens if a batch is executed/cleared and a ParameterData
|
||||
* object holds a pointer to the memory buffer in the batch.
|
||||
*/
|
||||
class ParameterData
|
||||
{
|
||||
public:
|
||||
// Size of the inplace buffer
|
||||
static constexpr std::size_t INPLACE_BYTES = 32;
|
||||
|
||||
// Required load factor so that no re-allocation occurs if a buffer
|
||||
// allocated from the heap receives new content.
|
||||
static constexpr double LOAD_FACTOR = 0.75;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates an uninitialized instance.
|
||||
*/
|
||||
ParameterData();
|
||||
|
||||
ParameterData(const ParameterData& other) = delete;
|
||||
|
||||
/**
|
||||
* Creates an instance and moves the data of another instance over to this
|
||||
* instance.
|
||||
*
|
||||
* @param other Another instance.
|
||||
*/
|
||||
ParameterData(ParameterData&& other);
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~ParameterData();
|
||||
|
||||
ParameterData& operator=(const ParameterData& other) = delete;
|
||||
|
||||
/**
|
||||
* Moves the parameter data of another instance to this instance.
|
||||
*
|
||||
* @param other Another instance.
|
||||
* @return Returns a reference to this instance.
|
||||
*/
|
||||
ParameterData& operator=(ParameterData&& other);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Sets the type and value of the parameter.
|
||||
*
|
||||
* @param type The ODBC-C-type of the value.
|
||||
* @param value Pointer to the value.
|
||||
* @param size Size of the value in bytes.
|
||||
*/
|
||||
void setValue(std::int16_t type, const void* value, std::size_t size);
|
||||
|
||||
/**
|
||||
* Sets the type of this parameter and sets the value to NULL.
|
||||
*
|
||||
* @param type The ODBC-C-type of the value.
|
||||
*/
|
||||
void setNull(std::int16_t type);
|
||||
|
||||
/**
|
||||
* Clears the parameter.
|
||||
*
|
||||
* The instance will be uninitialized after this method has been called.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Checks whether the value has been initialized.
|
||||
*
|
||||
* @return True if the value has been initialized, false otherwise.
|
||||
*/
|
||||
bool isInitialized() const { return state_ != UNINITIALIZED; }
|
||||
|
||||
/**
|
||||
* Returns the ODBC-C-type of the value.
|
||||
*
|
||||
* @return The ODBC-C-type of the value.
|
||||
*/
|
||||
std::int16_t getValueType() const { return valueType_; }
|
||||
|
||||
/**
|
||||
* Returns the size of the parameter. If the parameter type is SQL_DECIMAL,
|
||||
* SQL_NUMERIC, SQL_FLOAT, SQL_REAL or SQL_DOUBLE the returned value
|
||||
* represents the maximum precision of the corrresponding parameter. If the
|
||||
* parameter type is SQL_CHAR, SQL_VARCHAR, SQL_LONGVARCHAR, SQL_BINARY,
|
||||
* SQL_VARBINARY, SQL_LONGVARBINARY, SQL_TYPE_DATE, SQL_TYPE_TIME or
|
||||
* SQL_TYPE_TIMESTAMP the returned value represents the maximum length of
|
||||
* the corresponding parameter in bytes.
|
||||
*
|
||||
* @return The column size.
|
||||
*/
|
||||
std::size_t getColumnSize() const { return columnSize_; }
|
||||
|
||||
/**
|
||||
* Sets the column size of this parameter. If the parameter type is
|
||||
* SQL_DECIMAL, SQL_NUMERIC, SQL_FLOAT, SQL_REAL or SQL_DOUBLE the value
|
||||
* represents the maximum precision of the corrresponding parameter. If the
|
||||
* parameter type is SQL_CHAR, SQL_VARCHAR, SQL_LONGVARCHAR, SQL_BINARY,
|
||||
* SQL_VARBINARY, SQL_LONGVARBINARY, SQL_TYPE_DATE, SQL_TYPE_TIME or
|
||||
* SQL_TYPE_TIMESTAMP the value represents the maximum length of the
|
||||
* corresponding parameter in bytes.
|
||||
*
|
||||
* @param value The column size.
|
||||
*/
|
||||
void setColumnSize(std::size_t value) { columnSize_ = value; }
|
||||
|
||||
/**
|
||||
* Returns the number of decimal digits of this parameter. If the parameter
|
||||
* type is SQL_DECIMAL or SQL_NUMERIC the value represents the scale of the
|
||||
* corresponding parameter. If the parameter type is SQL_TYPE_TIME or
|
||||
* SQL_TYPE_TIMESTAMP the value represents the precision of the
|
||||
* corresponding parameter.
|
||||
*
|
||||
* @return The number of decimal digits.
|
||||
*/
|
||||
std::int16_t getDecimalDigits() const { return decimalDigits_; }
|
||||
|
||||
/**
|
||||
* Sets the number of decimal digits of this parameter. If the parameter
|
||||
* type is SQL_DECIMAL or SQL_NUMERIC the value represents the scale of the
|
||||
* corresponding parameter. If the parameter type is SQL_TYPE_TIME or
|
||||
* SQL_TYPE_TIMESTAMP the value represents the precision of the
|
||||
* corresponding parameter.
|
||||
*
|
||||
* @param value The number of decimal digits.
|
||||
*/
|
||||
void setDecimalDigits(std::int16_t value) { decimalDigits_ = value; }
|
||||
|
||||
/**
|
||||
* Checks whether the value is NULL.
|
||||
*
|
||||
* @return True if the value is NULL, false otherwise.
|
||||
*/
|
||||
bool isNull() const { return state_ == IS_NULL; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the data.
|
||||
*
|
||||
* The result is undefined if the value is either uninitialized or NULL.
|
||||
*
|
||||
* @return Returns a pointer to the data.
|
||||
*/
|
||||
const void* getData() const;
|
||||
|
||||
/**
|
||||
* Returns the size of the data in bytes.
|
||||
*
|
||||
* The result is undefined if the value is either uninitialized or NULL.
|
||||
*
|
||||
* @return The size of the data in bytes.
|
||||
*/
|
||||
std::size_t getSize() const { return size_; }
|
||||
|
||||
/**
|
||||
* Returns a pointer to the value's length or NULL indicator.
|
||||
*
|
||||
* The result is undefined if the value is uninitialized.
|
||||
*
|
||||
* @return A pointer to the value's length or NULL indicator.
|
||||
*/
|
||||
const void* getLenIndPtr() const { return &size_; }
|
||||
|
||||
/**
|
||||
* Checks whether the data is located in a buffer on the heap.
|
||||
*
|
||||
* @return True if the data is located in a buffer on the heap, false
|
||||
* if the data is in the inplace buffer or if the value is NULL.
|
||||
*/
|
||||
bool usesHeapBuffer() const;
|
||||
|
||||
/**
|
||||
* Checks whether this instance owns a buffer on the heap.
|
||||
*
|
||||
* @return True if this instance owns a buffer on the heap, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool ownsHeapBuffer() const { return state_ == NORMAL_HEAP_OWNING; }
|
||||
|
||||
/**
|
||||
* Returns the capacity of the buffer on the heap.
|
||||
*
|
||||
* This method must only be called if usesHeapBuffer() returns true.
|
||||
*
|
||||
* @return Returns the capacity of the buffer on the heap.
|
||||
*/
|
||||
std::size_t getHeapBufferCapacity() const { return capacity_; }
|
||||
|
||||
/**
|
||||
* Releases the heap buffer ownership.
|
||||
*
|
||||
* This method must only be called if ownsHeapBuffer() returns true.
|
||||
* Afterwards the caller is responsible for the buffer on the heap. This
|
||||
* means the caller has either to free that memory or he has to return
|
||||
* ownership to this instance via restoreHeapBufferOwnership().
|
||||
*
|
||||
* The pointer to the buffer can be retrieved via getData().
|
||||
*/
|
||||
void releaseHeapBufferOwnership();
|
||||
|
||||
/**
|
||||
* Restores the heap buffer ownership.
|
||||
*
|
||||
* This method must only be called if usesHeapBuffer() return true and
|
||||
* ownsHeapBuffer() returns false.
|
||||
*
|
||||
* After calling this method, this instance will manage the lifetime of the
|
||||
* heap buffer again.
|
||||
*/
|
||||
void restoreHeapBufferOwnership();
|
||||
|
||||
private:
|
||||
void setValueInplace(const void* value, std::size_t size);
|
||||
void setValueOnHeap(const void* value, std::size_t size);
|
||||
|
||||
private:
|
||||
enum State : std::uint8_t
|
||||
{
|
||||
/// Uninitialized
|
||||
UNINITIALIZED,
|
||||
/// Value is NULL
|
||||
IS_NULL,
|
||||
/// Normal value stored in-place
|
||||
NORMAL_INPLACE,
|
||||
/// Normal value stored in buffer on heap that is ownerd by this object
|
||||
NORMAL_HEAP_OWNING,
|
||||
/// Normal value stored in buffer on heap whose ownership has been
|
||||
/// transferred
|
||||
NORMAL_HEAP_NOT_OWNING,
|
||||
};
|
||||
|
||||
private:
|
||||
// We have the following invariants:
|
||||
// - inplaceData_ is the active union member iff state_ is NORMAL_INPLACE
|
||||
// - the structure is the active union member iff state_ is
|
||||
// NORMAL_HEAP_OWNING or NORMAL_HEAP_NOT_OWNING
|
||||
State state_;
|
||||
std::int16_t valueType_;
|
||||
std::size_t columnSize_;
|
||||
std::int16_t decimalDigits_;
|
||||
std::size_t size_;
|
||||
union
|
||||
{
|
||||
char inplaceData_[INPLACE_BYTES];
|
||||
struct
|
||||
{
|
||||
std::size_t capacity_;
|
||||
void* heapData_;
|
||||
};
|
||||
};
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
272
external/odbccpp/src/odbc/internal/TypeInfo.h
vendored
Normal file
272
external/odbccpp/src/odbc/internal/TypeInfo.h
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
#ifndef ODBC_INTERNAL_TYPEINFO_H_INCLUDED
|
||||
#define ODBC_INTERNAL_TYPEINFO_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Types.h>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Structure that contains the ODBC value type and parameter type for a C++
|
||||
* type.
|
||||
*
|
||||
* @tparam T The C++ type.
|
||||
*/
|
||||
template<typename T>
|
||||
struct TypeToOdbc
|
||||
{
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<bool>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_BIT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_BIT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::uint8_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_UTINYINT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_TINYINT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::int8_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_STINYINT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_TINYINT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::uint16_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_USHORT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_SMALLINT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::int16_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_SSHORT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_SMALLINT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::uint32_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_ULONG;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_INTEGER;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::int32_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_SLONG;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_INTEGER;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::uint64_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_UBIGINT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_BIGINT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<std::int64_t>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_SBIGINT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_BIGINT;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<float>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_FLOAT;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_REAL;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<double>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_DOUBLE;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_DOUBLE;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<date>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_TYPE_DATE;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_TYPE_DATE;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<time>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_TYPE_TIME;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_TYPE_TIME;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<timestamp>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_TYPE_TIMESTAMP;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_TYPE_TIMESTAMP;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template<>
|
||||
struct TypeToOdbc<decimal>
|
||||
{
|
||||
constexpr static std::int16_t VALUETYPE = SQL_C_NUMERIC;
|
||||
constexpr static std::int16_t PARAMTYPE = SQL_DECIMAL;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
struct TypeInfo
|
||||
{
|
||||
/**
|
||||
* Returns the parameter type to use for a given value type.
|
||||
*
|
||||
* @param valueType The ODBC value type.
|
||||
* @return The parameter type to use for a given value type.
|
||||
*/
|
||||
static std::int16_t getParamTypeForValueType(std::int16_t valueType)
|
||||
{
|
||||
switch (valueType)
|
||||
{
|
||||
case SQL_C_CHAR:
|
||||
return SQL_LONGVARCHAR;
|
||||
case SQL_C_WCHAR:
|
||||
return SQL_WLONGVARCHAR;
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
return SQL_SMALLINT;
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
return SQL_INTEGER;
|
||||
case SQL_C_FLOAT:
|
||||
return SQL_REAL;
|
||||
case SQL_C_DOUBLE:
|
||||
return SQL_DOUBLE;
|
||||
case SQL_C_BIT:
|
||||
return SQL_BIT;
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
return SQL_TINYINT;
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
return SQL_BIGINT;
|
||||
case SQL_C_BINARY:
|
||||
return SQL_LONGVARBINARY;
|
||||
case SQL_C_TYPE_DATE:
|
||||
return SQL_TYPE_DATE;
|
||||
case SQL_C_TYPE_TIME:
|
||||
return SQL_TYPE_TIME;
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
return SQL_TYPE_TIMESTAMP;
|
||||
case SQL_C_NUMERIC:
|
||||
return SQL_DECIMAL;
|
||||
}
|
||||
assert(false);
|
||||
return SQL_UNKNOWN_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a human-readable name for a value type.
|
||||
*
|
||||
* @param valueType The ODBC value type.
|
||||
* @return A human-readable name for the value type.
|
||||
*/
|
||||
static const char* getValueTypeName(std::int16_t valueType)
|
||||
{
|
||||
switch (valueType)
|
||||
{
|
||||
case SQL_C_CHAR:
|
||||
return "CLOB";
|
||||
case SQL_C_WCHAR:
|
||||
return "NCLOB";
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
return "SHORT";
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
return "INTEGER";
|
||||
case SQL_C_FLOAT:
|
||||
return "REAL";
|
||||
case SQL_C_DOUBLE:
|
||||
return "DOUBLE";
|
||||
case SQL_C_BIT:
|
||||
return "BOOLEAN";
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
return "TINYINT";
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
return "BIGINT";
|
||||
case SQL_C_BINARY:
|
||||
return "BLOB";
|
||||
case SQL_C_TYPE_DATE:
|
||||
return "DATE";
|
||||
case SQL_C_TYPE_TIME:
|
||||
return "TIME";
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
return "TIMESTAMP";
|
||||
case SQL_C_NUMERIC:
|
||||
return "DECIMAL";
|
||||
}
|
||||
assert(false);
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value's size in bytes of a given value type.
|
||||
*
|
||||
* This method will return 0 if values of the given type are not of fixed
|
||||
* size.
|
||||
*
|
||||
* @param valueType The ODBC value type.
|
||||
* @return A value's size in bytes of a given value type or 0 if a
|
||||
* value of this type does not have a fixed size.
|
||||
*/
|
||||
static std::size_t getSizeOfValueFromValueType(std::int16_t valueType)
|
||||
{
|
||||
switch (valueType)
|
||||
{
|
||||
case SQL_C_CHAR:
|
||||
case SQL_C_WCHAR:
|
||||
case SQL_C_BINARY:
|
||||
return 0;
|
||||
case SQL_C_BIT:
|
||||
case SQL_C_STINYINT:
|
||||
case SQL_C_UTINYINT:
|
||||
return 1;
|
||||
case SQL_C_SSHORT:
|
||||
case SQL_C_USHORT:
|
||||
return 2;
|
||||
case SQL_C_SLONG:
|
||||
case SQL_C_ULONG:
|
||||
case SQL_C_FLOAT:
|
||||
return 4;
|
||||
case SQL_C_SBIGINT:
|
||||
case SQL_C_UBIGINT:
|
||||
case SQL_C_DOUBLE:
|
||||
return 8;
|
||||
case SQL_C_TYPE_DATE:
|
||||
return sizeof(SQL_DATE_STRUCT);
|
||||
case SQL_C_TYPE_TIME:
|
||||
return sizeof(SQL_TIME_STRUCT);
|
||||
case SQL_C_TYPE_TIMESTAMP:
|
||||
return sizeof(SQL_TIMESTAMP_STRUCT);
|
||||
case SQL_C_NUMERIC:
|
||||
return sizeof(SQL_NUMERIC_STRUCT);
|
||||
}
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
114
external/odbccpp/src/odbc/internal/UtilInternal.cpp
vendored
Normal file
114
external/odbccpp/src/odbc/internal/UtilInternal.cpp
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <odbc/internal/Odbc.h>
|
||||
#include <odbc/internal/UtilInternal.h>
|
||||
//------------------------------------------------------------------------------
|
||||
using namespace std;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
static uint32_t fromLittleEndianArray(const SQLCHAR* number)
|
||||
{
|
||||
uint32_t ret =
|
||||
(static_cast<unsigned char>(number[0]) << 0)
|
||||
| (static_cast<unsigned char>(number[1]) << 8)
|
||||
| (static_cast<unsigned char>(number[2]) << 16)
|
||||
| (static_cast<unsigned char>(number[3]) << 24);
|
||||
return ret;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void toLittleEndianArray(uint32_t val, SQLCHAR* target)
|
||||
{
|
||||
target[0] = val & 0xFF;
|
||||
target[1] = (val >> 8) & 0xFF;
|
||||
target[2] = (val >> 16) & 0xFF;
|
||||
target[3] = (val >> 24) & 0xFF;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
template<int N>
|
||||
static bool allZero(const uint32_t(&number)[N])
|
||||
{
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (number[i] != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void UtilInternal::numericToString(const SQL_NUMERIC_STRUCT& num, char* str)
|
||||
{
|
||||
static_assert((SQL_MAX_NUMERIC_LEN % 4) == 0,
|
||||
"SQL_MAX_NUMERIC_LEN is not a multiple of 4");
|
||||
|
||||
// Translate to base 2^32
|
||||
constexpr int NUM_DIGITS = SQL_MAX_NUMERIC_LEN / 4;
|
||||
uint32_t digits[NUM_DIGITS];
|
||||
for (int i = 0; i < NUM_DIGITS; ++i) {
|
||||
digits[i] = fromLittleEndianArray(num.val + 4 * i);
|
||||
}
|
||||
|
||||
// Perform an Euclidean division by 10
|
||||
char* pos = str;
|
||||
while (!allZero(digits))
|
||||
{
|
||||
uint64_t carry = 0;
|
||||
for (int i = NUM_DIGITS - 1; i >= 0; --i)
|
||||
{
|
||||
uint64_t with_carry = digits[i] + (carry << 32);
|
||||
digits[i] = static_cast<uint32_t>(with_carry / 10);
|
||||
carry = with_carry % 10;
|
||||
}
|
||||
*pos = '0' + static_cast<char>(carry);
|
||||
++pos;
|
||||
}
|
||||
// Treat the special case in which the number is 0
|
||||
if (pos == str) {
|
||||
*pos = '0';
|
||||
++pos;
|
||||
} else if (num.sign == 0) {
|
||||
// Append the sign (only if not 0)
|
||||
*pos = '-';
|
||||
++pos;
|
||||
}
|
||||
|
||||
// Reverse and terminate the string
|
||||
reverse(str, pos);
|
||||
*pos = '\0';
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void UtilInternal::decimalToNumeric(const decimal& dec, SQL_NUMERIC_STRUCT& num)
|
||||
{
|
||||
static_assert((SQL_MAX_NUMERIC_LEN % 4) == 0,
|
||||
"SQL_MAX_NUMERIC_LEN is not a multiple of 4");
|
||||
|
||||
num.scale = dec.scale();
|
||||
num.precision = dec.precision();
|
||||
num.sign = (dec.signum() == -1) ? 0 : 1;
|
||||
|
||||
constexpr int NUM_DIGITS = SQL_MAX_NUMERIC_LEN / 4;
|
||||
uint32_t digits[NUM_DIGITS];
|
||||
memset(digits, 0, NUM_DIGITS * sizeof(uint32_t));
|
||||
|
||||
const char* pos = dec.unscaledValue();
|
||||
// Skip the sign
|
||||
if (dec.signum() == -1)
|
||||
++pos;
|
||||
while (*pos)
|
||||
{
|
||||
uint64_t value = *pos - '0';
|
||||
for (int i = 0; i < NUM_DIGITS; i++)
|
||||
{
|
||||
value = value + static_cast<uint64_t>(digits[i]) * 10;
|
||||
digits[i] = static_cast<uint32_t>(value);
|
||||
value = value >> 32;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_DIGITS; ++i) {
|
||||
toLittleEndianArray(digits[i], num.val + 4 * i);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
20
external/odbccpp/src/odbc/internal/UtilInternal.h
vendored
Normal file
20
external/odbccpp/src/odbc/internal/UtilInternal.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef ODBC_INTERNAL_UTILINTERNAL_H_INCLUDED
|
||||
#define ODBC_INTERNAL_UTILINTERNAL_H_INCLUDED
|
||||
//------------------------------------------------------------------------------
|
||||
#include <odbc/Types.h>
|
||||
#include <cinttypes>
|
||||
//------------------------------------------------------------------------------
|
||||
typedef struct tagSQL_NUMERIC_STRUCT SQL_NUMERIC_STRUCT;
|
||||
//------------------------------------------------------------------------------
|
||||
namespace odbc {
|
||||
//------------------------------------------------------------------------------
|
||||
class UtilInternal
|
||||
{
|
||||
public:
|
||||
static void numericToString(const SQL_NUMERIC_STRUCT& num, char* str);
|
||||
static void decimalToNumeric(const decimal& dec, SQL_NUMERIC_STRUCT& num);
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
} // namespace odbc
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
||||
@ -1,5 +1,3 @@
|
||||
FIND_PACKAGE(ODBCCPP REQUIRED)
|
||||
|
||||
########################################################
|
||||
# Files
|
||||
|
||||
@ -76,6 +74,7 @@ INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/src/gui/codeeditors
|
||||
${CMAKE_SOURCE_DIR}/external
|
||||
${CMAKE_SOURCE_DIR}/external/nlohmann
|
||||
${CMAKE_SOURCE_DIR}/external/odbccpp/src
|
||||
|
||||
${CMAKE_BINARY_DIR}/src/core
|
||||
${CMAKE_BINARY_DIR}/src/gui
|
||||
@ -86,7 +85,6 @@ INCLUDE_DIRECTORIES (SYSTEM
|
||||
${PROJ_INCLUDE_DIR}
|
||||
${GDAL_INCLUDE_DIR}
|
||||
${ODBC_INCLUDE_DIRS}
|
||||
${ODBCCPP_INCLUDE_DIR}
|
||||
${QCA_INCLUDE_DIR}
|
||||
${QTKEYCHAIN_INCLUDE_DIR}
|
||||
)
|
||||
@ -99,13 +97,13 @@ TARGET_COMPILE_DEFINITIONS(hanaprovider_a PUBLIC ODBC_STATIC)
|
||||
|
||||
TARGET_LINK_LIBRARIES(hanaprovider
|
||||
qgis_core
|
||||
${ODBCCPP_LIBRARY}
|
||||
odbccpp
|
||||
${ODBC_LIBRARIES}
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(hanaprovider_a
|
||||
qgis_core
|
||||
${ODBCCPP_LIBRARY}
|
||||
odbccpp
|
||||
${ODBC_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user