Codebase list mariadb-connector-odbc / 0f69c33
New upstream version 3.1.1 Bernhard Schmidt 4 years ago
84 changed file(s) with 24368 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 # Building the Connector/ODBC
1
2 Following are build instructions for various operating systems.
3
4 ## Windows
5
6 Prior to start building on Windows you need to have following tools installed:
7 - Microsoft Visual Studio https://visualstudio.microsoft.com/downloads/
8 - Git https://git-scm.com/download/win
9 - cmake https://cmake.org/download/
10
11 ```
12 git clone https://github.com/MariaDB/mariadb-connector-odbc.git
13 cd mariadb-connector-odbc
14 cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONC_WITH_UNIT_TESTS=Off -DCONC_WITH_MSI=OFF .
15 cmake --build . --config RelWithDebInfo
16 msiexec.exe /i wininstall\mariadb-connector-odbc-3.0.6-win32.msi
17 ```
18
19 ## CentOS
20
21 ```
22 sudo yum -y install git cmake make gcc openssl-devel unixODBC unixODBC-devel
23 git clone https://github.com/MariaDB/mariadb-connector-odbc.git
24 mkdir build && cd build
25 cmake ../mariadb-connector-odbc/ -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONC_WITH_UNIT_TESTS=Off -DCMAKE_INSTALL_PREFIX=/usr/local
26 cmake --build . --config RelWithDebInfo
27 sudo make install
28 ```
29
30 ## Debian & Ubuntu
31
32 ```
33 sudo apt-get update
34 sudo sh apt-get install -y git cmake make gcc libssl-dev unixodbc-dev
35 git clone https://github.com/MariaDB/mariadb-connector-odbc.git
36 mkdir build && cd build
37 cmake ../mariadb-connector-odbc/ -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONC_WITH_UNIT_TESTS=Off -DCMAKE_INSTALL_PREFIX=/usr/local
38 cmake --build . --config RelWithDebInfo
39 sudo make install
40 ```
0 # ************************************************************************************
1 # Copyright (C) 2013,2019 MariaDB Corporation AB
2 #
3 # This library is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU Library General Public
5 # License as published by the Free Software Foundation; either
6 # version 2.1 of the License, or (at your option) any later version.
7 #
8 # This library is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # Library General Public License for more details.
12 #
13 # You should have received a copy of the GNU Library General Public
14 # License along with this library; if not see <http://www.gnu.org/licenses>
15 # or write to the Free Software Foundation, Inc.,
16 # 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 # *************************************************************************************/
18 PROJECT(mariadb_connector_odbc C)
19
20 cmake_minimum_required(VERSION 2.8)
21
22 SET(MARIADB_ODBC_VERSION_MAJOR 3)
23 SET(MARIADB_ODBC_VERSION_MINOR 1)
24 SET(MARIADB_ODBC_VERSION_PATCH 1)
25 SET(MARIADB_ODBC_VERSION_QUALITY "ga")
26
27 SET(MARIADB_ODBC_VERSION "03.01.0001")
28
29 SET(MARIADB_DEFAULT_PLUGINS_SUBDIR "plugin")
30 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/ma_odbc_version.h.in
31 ${CMAKE_SOURCE_DIR}/ma_odbc_version.h)
32
33 SET (MARIADB_ODBC_SOURCES odbc_3_api.c
34 ma_error.c
35 ma_connection.c
36 ma_helper.c
37 ma_debug.c
38 ma_dsn.c
39 ma_driver.c
40 ma_info.c
41 ma_environment.c
42 ma_parse.c
43 ma_statement.c
44 ma_desc.c
45 ma_string.c
46 ma_result.c
47 ma_common.c
48 ma_server.c
49 ma_legacy_helpers.c
50 ma_typeconv.c
51 ma_bulk.c)
52
53 SET(DSN_DIALOG_FILES ${CMAKE_SOURCE_DIR}/dsn/odbc_dsn.c
54 ${CMAKE_SOURCE_DIR}/dsn/odbc_dsn.rc
55 ${CMAKE_SOURCE_DIR}/dsn/resource.h
56 ma_dsn.c
57 ma_driver.c
58 ma_error.c
59 ma_common.c)
60
61 # This has to be before C/C's cmake run, or it will build with /MD
62 IF(WIN32)
63 IF (MSVC)
64 SET(CONFIG_TYPES "DEBUG" "RELEASE" "RELWITHDEBINFO" "MINSIZEREL")
65 FOREACH(BUILD_TYPE ${CONFIG_TYPES})
66 FOREACH(COMPILER CXX C)
67 SET(COMPILER_FLAGS "${CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}}")
68 IF (NOT COMPILER_FLAGS STREQUAL "")
69 STRING(REPLACE "/MD" "/MT" COMPILER_FLAGS ${COMPILER_FLAGS})
70 IF (BUILD_TYPE STREQUAL "Debug")
71 SET(COMPILER_FLAGS "${COMPILER_FLAGS} /RTC1 /RTCc")
72 STRING(REPLACE "/Zi" "/ZI" COMPILER_FLAGS ${COMPILER_FLAGS})
73 ENDIF()
74 MESSAGE (STATUS "CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE}= ${COMPILER_FLAGS}")
75 SET(CMAKE_${COMPILER}_FLAGS_${BUILD_TYPE} ${COMPILER_FLAGS} CACHE
76 STRING "overwritten by mariadb-odbc" FORCE)
77 ENDIF()
78 ENDFOREACH()
79 ENDFOREACH()
80 ENDIF()
81 ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
82 ENDIF()
83
84 IF(EXISTS ${CMAKE_SOURCE_DIR}/libmariadb)
85 IF(GIT_BUILD_SRCPKG)
86 # We don't want conn/c (wrong) src pkg to be built.
87 SET(GIT_BUILD_SRCPKG FALSE)
88 SET(ODBC_GIT_BUILD_SRCPKG TRUE)
89 ENDIF()
90 INCLUDE(${CMAKE_SOURCE_DIR}/cmake/connector_c.cmake)
91 ELSE()
92 SET(USE_SYSTEM_INSTALLED_LIB TRUE)
93 MESSAGE(STATUS "There is no Connector/C sub-project folder, linking against libmariadb installed on the system")
94 ENDIF()
95
96 IF(WIN32)
97 #ADD_OPTION(WITH_MSI "Build MSI installation package" OFF)
98 ADD_OPTION(WITH_SIGNCODE "Digitally sign files" OFF)
99 ENDIF()
100
101 #ADD_OPTION(WITH_UNIT_TESTS "build test suite" ON)
102 #ADD_OPTION(WITH_SSL "Enables use of TLS/SSL library" ON)
103
104 IF(WITH_SIGNCODE)
105 IF(WIN32 AND NOT SIGN_OPTIONS)
106 SET(SIGN_OPTIONS /a /t http://timestamp.verisign.com/scripts/timstamp.dll)
107 ELSE()
108 SEPARATE_ARGUMENTS(SIGN_OPTIONS)
109 ENDIF()
110 MARK_AS_ADVANCED(SIGN_OPTIONS)
111 ENDIF()
112
113 #Debug log is controlled by conenction option solely
114 ADD_DEFINITIONS(-DMAODBC_DEBUG)
115
116 INCLUDE(${CMAKE_SOURCE_DIR}/cmake/SearchLibrary.cmake)
117 INCLUDE(${CMAKE_SOURCE_DIR}/cmake/SetValueMacro.cmake)
118
119 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libmariadb/include)
120 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/libmariadb/include)
121
122 IF(WIN32)
123 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/dsn)
124 SET(ODBC_LIBS odbc32)
125 SET(ODBC_INSTLIBS odbccp32)
126 SET(MARIADB_ODBC_SOURCES ${MARIADB_ODBC_SOURCES}
127 ma_dll.c
128 ma_platform_win32.c
129 ma_error.h
130 ma_connection.h
131 ma_helper.h
132 ma_debug.h
133 ma_dsn.h
134 ma_driver.h
135 ma_info.h
136 ma_environment.h
137 ma_parse.h
138 ma_statement.h
139 ma_desc.h
140 ma_string.h
141 ma_odbc.h
142 ma_odbc_version.h
143 ma_result.h
144 ma_server.h
145 ma_legacy_helpers.h
146 ma_typeconv.h
147 ma_bulk.h)
148 SET(DSN_DIALOG_FILES ${DSN_DIALOG_FILES}
149 ma_platform_win32.c)
150
151 SET(PLATFORM_DEPENDENCIES ws2_32 Shlwapi)
152 IF (MSVC)
153 MESSAGE(STATUS "MSVC_VERSION= ${MSVC_VERSION}")
154 IF (NOT(MSVC_VERSION LESS 1900))
155 MESSAGE(STATUS "Configuring to link connector against legacy_stdio_definitions")
156 SET(PLATFORM_DEPENDENCIES ${PLATFORM_DEPENDENCIES} legacy_stdio_definitions)
157 ENDIF()
158 ENDIF()
159 ELSE()
160 SEARCH_LIBRARY(LIB_MATH floor m)
161 SET(PLATFORM_DEPENDENCIES ${LIB_MATH})
162 SET (MARIADB_ODBC_SOURCES ${MARIADB_ODBC_SOURCES} ma_platform_posix.c)
163 ENDIF()
164
165 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
166
167 IF(NOT CMAKE_BUILD_TYPE)
168 SET(CMAKE_BUILD_TYPE "RelWithDebInfo")
169 ENDIF()
170
171 IF(NOT WIN32)
172 # Looking for DM(UnixODBC) files
173 INCLUDE(${CMAKE_SOURCE_DIR}/cmake/FindDM.cmake)
174 MESSAGE(STATUS "DM_FOUND: ${DM_FOUND}, ODBC_LIB_DIR: ${ODBC_LIB_DIR}, ODBC_INCLUDE_DIR: ${ODBC_INCLUDE_DIR}")
175
176 IF(APPLE)
177 SET(ODBC_LIB_DIR "/usr/local/Cellar/libiodbc/3.52.12/lib/")
178 SET(ODBC_INCLUDE_DIR "/usr/local/Cellar/libiodbc/3.52.12/include")
179 SET(DM_FOUND TRUE)
180 ENDIF()
181
182 IF(DM_FOUND)
183 INCLUDE_DIRECTORIES(${ODBC_INCLUDE_DIR})
184 LINK_DIRECTORIES(${ODBC_LIB_DIR})
185 ELSE()
186 MESSAGE(FATAL_ERROR "Driver Manager was not found")
187 ENDIF()
188 ENDIF()
189
190 IF(APPLE)
191 # Looking for iconv files
192 INCLUDE(${CMAKE_SOURCE_DIR}/cmake/FindIconv.cmake)
193 IF(ICONV_FOUND)
194 INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
195 SET(PLATFORM_DEPENDENCIES ${PLATFORM_DEPENDENCIES} ${ICONV_LIBRARIES})
196 ELSE()
197 MESSAGE(FATAL_ERROR "iconv was not found")
198 ENDIF()
199 ENDIF()
200
201 SET(CPACK_PACKAGE_VERSION ${MARIADB_ODBC_VERSION_MAJOR}.${MARIADB_ODBC_VERSION_MINOR}.${MARIADB_ODBC_VERSION_PATCH})
202
203 SET(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
204 #SET(CPACK_COMPONENTS_ALL ClientPlugins ODBCLibs Documentation)
205 SET(CPACK_COMPONENTS_ALL ODBCLibs Documentation)
206 SET(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE 1)
207
208 # TODO: Make it optional
209 # Disable dbug information for release builds
210 #SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DDBUG_OFF")
211 #SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF")
212 #SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
213 #SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF")
214
215
216 # We need to determine the last parameter for SQLColAttribute:
217 # Older UnixODBC version expect SQLPOINTER while Windows expects SQLLEN *
218 TRY_COMPILE(COMPILE_OK ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/cmake/sqlcolattribute.c)
219 MESSAGE(STATUS "Checking if SQLColAttribute expects SQLPOINTER ${COMPILE_OK}")
220 IF(COMPILE_OK)
221 ADD_DEFINITIONS(-DSQLCOLATTRIB_SQLPOINTER)
222 ELSE()
223 ADD_DEFINITIONS(-DSQLCOLATTRIB_SQLLEN_PTR)
224 ENDIF()
225
226 # This is interim, we port ascii version to Linux first
227 IF(WIN32)
228 SET(UNICODE "W")
229 ELSE()
230 IF (DIRECT_LINK_TESTS)
231 ADD_DEFINITIONS(-DHAVE_UNICODE)
232 ENDIF()
233
234 ENDIF()
235
236 IF(WIN32 OR WITH_OPENSSL)
237 IF(WITH_OPENSSL)
238 FIND_PACKAGE(OpenSSL)
239
240 IF(OPENSSL_FOUND)
241 MESSAGE(STATUS "Configuring to build with OpenSSL")
242
243 ADD_DEFINITIONS(-DHAVE_OPENSSL)
244 INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
245 SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
246
247 IF(OPENSSL_CRYPTO_LIBRARIES)
248 SET(SSL_LIBRARIES ${SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
249 ENDIF()
250
251 SET(PLATFORM_DEPENDENCIES ${PLATFORM_DEPENDENCIES} ${SSL_LIBRARIES})
252 ELSE()
253 MESSAGE(FATAL_ERROR "OpenSSL not found. Please install OpenSSL or disable SSL support via option -DWITH_OPENSSL=Off")
254 ENDIF()
255 ELSE()
256 MESSAGE(STATUS "Configuring SSL support using SChannel")
257 SET(PLATFORM_DEPENDENCIES ${PLATFORM_DEPENDENCIES} version.lib)
258 ENDIF()
259 ELSE()
260 MESSAGE(STATUS "Configuring to build without SSL support")
261 ENDIF()
262
263 SET(LIBRARY_NAME "maodbc")
264 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/mariadb-odbc-driver.def.in
265 ${CMAKE_SOURCE_DIR}/mariadb-odbc-driver-uni.def)
266
267 IF(MARIADB_LINK_DYNAMIC)# OR USE_SYSTEM_INSTALLED_LIB)
268 IF(USE_SYSTEM_INSTALLED_LIB)
269 SET(MARIADB_CLIENT_TARGET_NAME mariadb)
270 ELSE()
271 SET(MARIADB_CLIENT_TARGET_NAME libmariadb)
272 ENDIF()
273 MESSAGE(STATUS "Linking Connector/C library dynamically(${MARIADB_CLIENT_TARGET_NAME})")
274 ELSE()
275 SET(MARIADB_CLIENT_TARGET_NAME mariadbclient)
276 MESSAGE(STATUS "Linking Connector/C library statically(${MARIADB_CLIENT_TARGET_NAME})")
277 ENDIF()
278
279 IF(WIN32)
280 ADD_LIBRARY(${LIBRARY_NAME} SHARED ${MARIADB_ODBC_SOURCES} ${CMAKE_SOURCE_DIR}/mariadb-odbc-driver-uni.def maodbcu.rc)
281 ELSE()
282 MESSAGE(STATUS "Version script: ${CMAKE_SOURCE_DIR}/maodbc.def")
283 ADD_LIBRARY(${LIBRARY_NAME} SHARED ${MARIADB_ODBC_SOURCES} maodbcu.rc)
284
285 IF(APPLE)
286 SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-Wl")
287 ELSE()
288 SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/maodbc.def")
289 ENDIF()
290 ENDIF()
291
292 SET_TARGET_PROPERTIES(${LIBRARY_NAME} PROPERTIES LANGUAGE C)
293 TARGET_LINK_LIBRARIES(${LIBRARY_NAME} ${MARIADB_CLIENT_TARGET_NAME} ${ODBC_INSTLIBS} ${PLATFORM_DEPENDENCIES})
294
295 # Currently on Windows only
296 IF(WIN32)
297 ADD_CUSTOM_COMMAND(TARGET maodbc POST_BUILD
298 COMMAND ${CMAKE_COMMAND} ARGS -DDRIVER_LIB_DIR=$<TARGET_FILE_DIR:maodbc>
299 -DPLUGINS_LIB_DIR=$<TARGET_FILE_DIR:dialog>
300 -DPLUGINS_SUBDIR_NAME=${MARIADB_DEFAULT_PLUGINS_SUBDIR}
301 -DFILE_IN=${CMAKE_SOURCE_DIR}/wininstall/binaries_dir.xml.in
302 -DFILE_OUT=${CMAKE_SOURCE_DIR}/wininstall/binaries_dir.xml
303 -P ${CMAKE_SOURCE_DIR}/cmake/ConfigureFile.cmake
304 )
305 ####### MAODBCS #######
306 ADD_LIBRARY(maodbcs SHARED ${DSN_DIALOG_FILES} ${CMAKE_SOURCE_DIR}/dsn/mariadb_odbc_setup.def)
307 SET_TARGET_PROPERTIES(maodbcs PROPERTIES LANGUAGE C)
308 TARGET_LINK_LIBRARIES(maodbcs comctl32 ${MARIADB_LIB} maodbc ${ODBC_INSTLIBS})
309
310 ADD_EXECUTABLE(dsn_test dsn_test.c)
311 TARGET_LINK_LIBRARIES(dsn_test ${MARIADB_LIB})
312 ENDIF()
313
314
315 SET(CPACK_PACKAGE_NAME "mariadb_connector_odbc")
316 IF(WIN32)
317 ADD_SUBDIRECTORY(wininstall)
318 ELSE()
319 IF(APPLE)
320 MESSAGE(STATUS "Configuring to generate PKG package")
321 ADD_SUBDIRECTORY(osxinstall)
322 ENDIF()
323 IF(NOT DEFINED INSTALL_LIB_SUFFIX)
324 SET(INSTALL_LIB_SUFFIX "lib")
325 IF("${CMAKE_SIZEOF_VOID_P}" EQUAL "8" AND EXISTS "/usr/lib64/")
326 SET(INSTALL_LIB_SUFFIX "lib")
327 ENDIF()
328 ENDIF()
329
330 INSTALL(TARGETS
331 maodbc
332 LIBRARY DESTINATION ./${INSTALL_LIB_SUFFIX}
333 COMPONENT ODBCLibs)
334
335 INSTALL(FILES
336 ${CMAKE_SOURCE_DIR}/COPYING
337 ${CMAKE_SOURCE_DIR}/README
338 DESTINATION
339 ./share/doc/${CPACK_PACKAGE_NAME}/
340 COMPONENT Documentation)
341 ENDIF()
342
343 # Tests. Checking if we have them. May be not the case if we are building from source package
344 IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
345 ADD_SUBDIRECTORY(test)
346 IF(NOT WIN32)
347 # Configuring ini files for testing with UnixODBC
348 SET_VALUE(TEST_DRIVER "maodbc_test")
349 SET_VALUE(TEST_DSN "maodbc_test")
350 SET_VALUE(TEST_PORT "3306")
351 SET_VALUE(TEST_SERVER "localhost")
352 SET_VALUE(TEST_SOCKET "")
353 SET_VALUE(TEST_SCHEMA "test")
354 SET_VALUE(TEST_UID "root")
355 SET_VALUE(TEST_PASSWORD "")
356
357 MESSAGE(STATUS "Configurig Test Driver: ${TEST_DRIVER}, Test DSN: ${TEST_DSN}, tcp://${TEST_UID}@${TEST_SERVER}:${TEST_PORT}/${TEST_SCHEMA} socket: ${TEST_SOCKET}")
358
359 ADD_CUSTOM_COMMAND(TARGET maodbc POST_BUILD
360 COMMAND ${CMAKE_COMMAND} ARGS -DDRIVER_LIB_LOCATION=$<TARGET_FILE:maodbc>
361 -DTEST_DRIVER=${TEST_DRIVER}
362 -DFILE_IN=${CMAKE_SOURCE_DIR}/test/odbcinst.ini.in
363 -DFILE_OUT=${CMAKE_BINARY_DIR}/test/odbcinst.ini
364 -P ${CMAKE_SOURCE_DIR}/cmake/ConfigureFile.cmake
365 )
366
367 ADD_CUSTOM_COMMAND(TARGET maodbc POST_BUILD
368 COMMAND ${CMAKE_COMMAND} ARGS -DTEST_DRIVER=${TEST_DRIVER}
369 -DTEST_DSN=${TEST_DSN}
370 -DTEST_PORT=${TEST_PORT}
371 -DTEST_SERVER=${TEST_SERVER}
372 -DTEST_SOCKET=${TEST_SOCKET}
373 -DTEST_SCHEMA=${TEST_SCHEMA}
374 -DTEST_UID=${TEST_UID}
375 -DTEST_PASSWORD=${TEST_PASSWORD}
376 -DFILE_IN=${CMAKE_SOURCE_DIR}/test/odbc.ini.in
377 -DFILE_OUT=${CMAKE_BINARY_DIR}/test/odbc.ini
378 -P ${CMAKE_SOURCE_DIR}/cmake/ConfigureFile.cmake
379 )
380 ENDIF()
381 ENDIF()
382
383 # Packaging
384 SET(CPACK_PACKAGE_VERSION_MAJOR "${MARIADB_ODBC_VERSION_MAJOR}")
385 SET(CPACK_PACKAGE_VERSION_MINOR "${MARIADB_ODBC_VERSION_MINOR}")
386 SET(CPACK_PACKAGE_VERSION_MINOR "${MARIADB_ODBC_VERSION_PATCH}")
387 SET(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
388 SET(CPACK_PACKAGE_DESCRIPTION "MariaDB Connector/ODBC. ODBC driver library for connecting to MariaDB and MySQL servers")
389 IF(NOT SYSTEM_NAME)
390 STRING(TOLOWER ${CMAKE_SYSTEM_NAME} SYSTEM_NAME)
391 ENDIF()
392 MESSAGE(STATUS "${SYSTEM_NAME}")
393 SET(CPACK_PACKAGE_FILE_NAME "mariadb-connector-odbc-${CPACK_PACKAGE_VERSION}-${MARIADB_ODBC_VERSION_QUALITY}-${SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
394 SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
395 SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
396 SET(CPACK_SOURCE_PACKAGE_FILE_NAME "mariadb-connector-odbc-${CPACK_PACKAGE_VERSION}-${MARIADB_ODBC_VERSION_QUALITY}-src")
397 SET(CPACK_PACKAGE_CONTACT "info@mariadb.com")
398 SET(CPACK_PACKAGE_VENDOR "MariaDB Corporation AB")
399 SET(CPACK_SOURCE_IGNORE_FILES
400 /test/
401 /.git/
402 .gitignore
403 .gitmodules
404 .gitattributes
405 CMakeCache.txt
406 cmake_dist.cmake
407 CPackSourceConfig.cmake
408 CPackConfig.cmake
409 /.build/
410 cmake_install.cmake
411 CTestTestfile.cmake
412 /CMakeFiles/
413 /version_resources/
414 .*vcxproj
415 .*gz$
416 .*zip$
417 .*so$
418 .*so.2
419 .*so.3
420 .*dll$
421 .*a$
422 .*pdb$
423 .*sln$
424 .*sdf$
425 Makefile$
426 /autom4te.cache/
427 /.travis/
428 .travis.yml
429 /libmariadb/
430 /_CPack_Packages/
431 )
432
433 # Build source packages
434 IF(GIT_BUILD_SRCPKG OR ODBC_GIT_BUILD_SRCPKG)
435 IF(WIN32)
436 EXECUTE_PROCESS(COMMAND git archive --format=zip --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip --worktree-attributes -v HEAD)
437 ELSE()
438 EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=zip --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.zip -v HEAD)
439 EXECUTE_PROCESS(COMMAND git archive ${GIT_BRANCH} --format=tar --prefix=${CPACK_SOURCE_PACKAGE_FILE_NAME}/ --output=${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar -v HEAD)
440 EXECUTE_PROCESS(COMMAND gzip -9 -f ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar)
441 ENDIF()
442 ENDIF()
443
444 IF(WIN32)
445 SET(DEFAULT_GENERATOR "ZIP")
446 ELSE()
447 SET(DEFAULT_GENERATOR "TGZ")
448 ENDIF()
449
450 IF(NOT CPACK_GENERATOR)
451 SET(CPACK_GENERATOR "${DEFAULT_GENERATOR}")
452 ENDIF()
453 IF(NOT CPACK_SOURCE_GENERATOR)
454 SET(CPACK_SOURCE_GENERATOR "${DEFAULT_GENERATOR}")
455 ENDIF()
456
457 MESSAGE(STATUS "License File: ${CPACK_RESOURCE_FILE_LICENSE}")
458 MESSAGE(STATUS "ReadMe File: ${CPACK_PACKAGE_DESCRIPTION_FILE}")
459 MESSAGE(STATUS "Source Package Filename: ${CPACK_SOURCE_PACKAGE_FILE_NAME}.${CPACK_SOURCE_GENERATOR}")
460
461 INCLUDE(CPack)
462
0 GNU LESSER GENERAL PUBLIC LICENSE
1 Version 2.1, February 1999
2
3 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
4 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
5 Everyone is permitted to copy and distribute verbatim copies
6 of this license document, but changing it is not allowed.
7
8 [This is the first released version of the Lesser GPL. It also counts
9 as the successor of the GNU Library Public License, version 2, hence
10 the version number 2.1.]
11
12 Preamble
13
14 The licenses for most software are designed to take away your
15 freedom to share and change it. By contrast, the GNU General Public
16 Licenses are intended to guarantee your freedom to share and change
17 free software--to make sure the software is free for all its users.
18
19 This license, the Lesser General Public License, applies to some
20 specially designated software packages--typically libraries--of the
21 Free Software Foundation and other authors who decide to use it. You
22 can use it too, but we suggest you first think carefully about whether
23 this license or the ordinary General Public License is the better
24 strategy to use in any particular case, based on the explanations below.
25
26 When we speak of free software, we are referring to freedom of use,
27 not price. Our General Public Licenses are designed to make sure that
28 you have the freedom to distribute copies of free software (and charge
29 for this service if you wish); that you receive source code or can get
30 it if you want it; that you can change the software and use pieces of
31 it in new free programs; and that you are informed that you can do
32 these things.
33
34 To protect your rights, we need to make restrictions that forbid
35 distributors to deny you these rights or to ask you to surrender these
36 rights. These restrictions translate to certain responsibilities for
37 you if you distribute copies of the library or if you modify it.
38
39 For example, if you distribute copies of the library, whether gratis
40 or for a fee, you must give the recipients all the rights that we gave
41 you. You must make sure that they, too, receive or can get the source
42 code. If you link other code with the library, you must provide
43 complete object files to the recipients, so that they can relink them
44 with the library after making changes to the library and recompiling
45 it. And you must show them these terms so they know their rights.
46
47 We protect your rights with a two-step method: (1) we copyright the
48 library, and (2) we offer you this license, which gives you legal
49 permission to copy, distribute and/or modify the library.
50
51 To protect each distributor, we want to make it very clear that
52 there is no warranty for the free library. Also, if the library is
53 modified by someone else and passed on, the recipients should know
54 that what they have is not the original version, so that the original
55 author's reputation will not be affected by problems that might be
56 introduced by others.
57
58 Finally, software patents pose a constant threat to the existence of
59 any free program. We wish to make sure that a company cannot
60 effectively restrict the users of a free program by obtaining a
61 restrictive license from a patent holder. Therefore, we insist that
62 any patent license obtained for a version of the library must be
63 consistent with the full freedom of use specified in this license.
64
65 Most GNU software, including some libraries, is covered by the
66 ordinary GNU General Public License. This license, the GNU Lesser
67 General Public License, applies to certain designated libraries, and
68 is quite different from the ordinary General Public License. We use
69 this license for certain libraries in order to permit linking those
70 libraries into non-free programs.
71
72 When a program is linked with a library, whether statically or using
73 a shared library, the combination of the two is legally speaking a
74 combined work, a derivative of the original library. The ordinary
75 General Public License therefore permits such linking only if the
76 entire combination fits its criteria of freedom. The Lesser General
77 Public License permits more lax criteria for linking other code with
78 the library.
79
80 We call this license the "Lesser" General Public License because it
81 does Less to protect the user's freedom than the ordinary General
82 Public License. It also provides other free software developers Less
83 of an advantage over competing non-free programs. These disadvantages
84 are the reason we use the ordinary General Public License for many
85 libraries. However, the Lesser license provides advantages in certain
86 special circumstances.
87
88 For example, on rare occasions, there may be a special need to
89 encourage the widest possible use of a certain library, so that it becomes
90 a de-facto standard. To achieve this, non-free programs must be
91 allowed to use the library. A more frequent case is that a free
92 library does the same job as widely used non-free libraries. In this
93 case, there is little to gain by limiting the free library to free
94 software only, so we use the Lesser General Public License.
95
96 In other cases, permission to use a particular library in non-free
97 programs enables a greater number of people to use a large body of
98 free software. For example, permission to use the GNU C Library in
99 non-free programs enables many more people to use the whole GNU
100 operating system, as well as its variant, the GNU/Linux operating
101 system.
102
103 Although the Lesser General Public License is Less protective of the
104 users' freedom, it does ensure that the user of a program that is
105 linked with the Library has the freedom and the wherewithal to run
106 that program using a modified version of the Library.
107
108 The precise terms and conditions for copying, distribution and
109 modification follow. Pay close attention to the difference between a
110 "work based on the library" and a "work that uses the library". The
111 former contains code derived from the library, whereas the latter must
112 be combined with the library in order to run.
113
114 GNU LESSER GENERAL PUBLIC LICENSE
115 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
116
117 0. This License Agreement applies to any software library or other
118 program which contains a notice placed by the copyright holder or
119 other authorized party saying it may be distributed under the terms of
120 this Lesser General Public License (also called "this License").
121 Each licensee is addressed as "you".
122
123 A "library" means a collection of software functions and/or data
124 prepared so as to be conveniently linked with application programs
125 (which use some of those functions and data) to form executables.
126
127 The "Library", below, refers to any such software library or work
128 which has been distributed under these terms. A "work based on the
129 Library" means either the Library or any derivative work under
130 copyright law: that is to say, a work containing the Library or a
131 portion of it, either verbatim or with modifications and/or translated
132 straightforwardly into another language. (Hereinafter, translation is
133 included without limitation in the term "modification".)
134
135 "Source code" for a work means the preferred form of the work for
136 making modifications to it. For a library, complete source code means
137 all the source code for all modules it contains, plus any associated
138 interface definition files, plus the scripts used to control compilation
139 and installation of the library.
140
141 Activities other than copying, distribution and modification are not
142 covered by this License; they are outside its scope. The act of
143 running a program using the Library is not restricted, and output from
144 such a program is covered only if its contents constitute a work based
145 on the Library (independent of the use of the Library in a tool for
146 writing it). Whether that is true depends on what the Library does
147 and what the program that uses the Library does.
148
149 1. You may copy and distribute verbatim copies of the Library's
150 complete source code as you receive it, in any medium, provided that
151 you conspicuously and appropriately publish on each copy an
152 appropriate copyright notice and disclaimer of warranty; keep intact
153 all the notices that refer to this License and to the absence of any
154 warranty; and distribute a copy of this License along with the
155 Library.
156
157 You may charge a fee for the physical act of transferring a copy,
158 and you may at your option offer warranty protection in exchange for a
159 fee.
160
161 2. You may modify your copy or copies of the Library or any portion
162 of it, thus forming a work based on the Library, and copy and
163 distribute such modifications or work under the terms of Section 1
164 above, provided that you also meet all of these conditions:
165
166 a) The modified work must itself be a software library.
167
168 b) You must cause the files modified to carry prominent notices
169 stating that you changed the files and the date of any change.
170
171 c) You must cause the whole of the work to be licensed at no
172 charge to all third parties under the terms of this License.
173
174 d) If a facility in the modified Library refers to a function or a
175 table of data to be supplied by an application program that uses
176 the facility, other than as an argument passed when the facility
177 is invoked, then you must make a good faith effort to ensure that,
178 in the event an application does not supply such function or
179 table, the facility still operates, and performs whatever part of
180 its purpose remains meaningful.
181
182 (For example, a function in a library to compute square roots has
183 a purpose that is entirely well-defined independent of the
184 application. Therefore, Subsection 2d requires that any
185 application-supplied function or table used by this function must
186 be optional: if the application does not supply it, the square
187 root function must still compute square roots.)
188
189 These requirements apply to the modified work as a whole. If
190 identifiable sections of that work are not derived from the Library,
191 and can be reasonably considered independent and separate works in
192 themselves, then this License, and its terms, do not apply to those
193 sections when you distribute them as separate works. But when you
194 distribute the same sections as part of a whole which is a work based
195 on the Library, the distribution of the whole must be on the terms of
196 this License, whose permissions for other licensees extend to the
197 entire whole, and thus to each and every part regardless of who wrote
198 it.
199
200 Thus, it is not the intent of this section to claim rights or contest
201 your rights to work written entirely by you; rather, the intent is to
202 exercise the right to control the distribution of derivative or
203 collective works based on the Library.
204
205 In addition, mere aggregation of another work not based on the Library
206 with the Library (or with a work based on the Library) on a volume of
207 a storage or distribution medium does not bring the other work under
208 the scope of this License.
209
210 3. You may opt to apply the terms of the ordinary GNU General Public
211 License instead of this License to a given copy of the Library. To do
212 this, you must alter all the notices that refer to this License, so
213 that they refer to the ordinary GNU General Public License, version 2,
214 instead of to this License. (If a newer version than version 2 of the
215 ordinary GNU General Public License has appeared, then you can specify
216 that version instead if you wish.) Do not make any other change in
217 these notices.
218
219 Once this change is made in a given copy, it is irreversible for
220 that copy, so the ordinary GNU General Public License applies to all
221 subsequent copies and derivative works made from that copy.
222
223 This option is useful when you wish to copy part of the code of
224 the Library into a program that is not a library.
225
226 4. You may copy and distribute the Library (or a portion or
227 derivative of it, under Section 2) in object code or executable form
228 under the terms of Sections 1 and 2 above provided that you accompany
229 it with the complete corresponding machine-readable source code, which
230 must be distributed under the terms of Sections 1 and 2 above on a
231 medium customarily used for software interchange.
232
233 If distribution of object code is made by offering access to copy
234 from a designated place, then offering equivalent access to copy the
235 source code from the same place satisfies the requirement to
236 distribute the source code, even though third parties are not
237 compelled to copy the source along with the object code.
238
239 5. A program that contains no derivative of any portion of the
240 Library, but is designed to work with the Library by being compiled or
241 linked with it, is called a "work that uses the Library". Such a
242 work, in isolation, is not a derivative work of the Library, and
243 therefore falls outside the scope of this License.
244
245 However, linking a "work that uses the Library" with the Library
246 creates an executable that is a derivative of the Library (because it
247 contains portions of the Library), rather than a "work that uses the
248 library". The executable is therefore covered by this License.
249 Section 6 states terms for distribution of such executables.
250
251 When a "work that uses the Library" uses material from a header file
252 that is part of the Library, the object code for the work may be a
253 derivative work of the Library even though the source code is not.
254 Whether this is true is especially significant if the work can be
255 linked without the Library, or if the work is itself a library. The
256 threshold for this to be true is not precisely defined by law.
257
258 If such an object file uses only numerical parameters, data
259 structure layouts and accessors, and small macros and small inline
260 functions (ten lines or less in length), then the use of the object
261 file is unrestricted, regardless of whether it is legally a derivative
262 work. (Executables containing this object code plus portions of the
263 Library will still fall under Section 6.)
264
265 Otherwise, if the work is a derivative of the Library, you may
266 distribute the object code for the work under the terms of Section 6.
267 Any executables containing that work also fall under Section 6,
268 whether or not they are linked directly with the Library itself.
269
270 6. As an exception to the Sections above, you may also combine or
271 link a "work that uses the Library" with the Library to produce a
272 work containing portions of the Library, and distribute that work
273 under terms of your choice, provided that the terms permit
274 modification of the work for the customer's own use and reverse
275 engineering for debugging such modifications.
276
277 You must give prominent notice with each copy of the work that the
278 Library is used in it and that the Library and its use are covered by
279 this License. You must supply a copy of this License. If the work
280 during execution displays copyright notices, you must include the
281 copyright notice for the Library among them, as well as a reference
282 directing the user to the copy of this License. Also, you must do one
283 of these things:
284
285 a) Accompany the work with the complete corresponding
286 machine-readable source code for the Library including whatever
287 changes were used in the work (which must be distributed under
288 Sections 1 and 2 above); and, if the work is an executable linked
289 with the Library, with the complete machine-readable "work that
290 uses the Library", as object code and/or source code, so that the
291 user can modify the Library and then relink to produce a modified
292 executable containing the modified Library. (It is understood
293 that the user who changes the contents of definitions files in the
294 Library will not necessarily be able to recompile the application
295 to use the modified definitions.)
296
297 b) Use a suitable shared library mechanism for linking with the
298 Library. A suitable mechanism is one that (1) uses at run time a
299 copy of the library already present on the user's computer system,
300 rather than copying library functions into the executable, and (2)
301 will operate properly with a modified version of the library, if
302 the user installs one, as long as the modified version is
303 interface-compatible with the version that the work was made with.
304
305 c) Accompany the work with a written offer, valid for at
306 least three years, to give the same user the materials
307 specified in Subsection 6a, above, for a charge no more
308 than the cost of performing this distribution.
309
310 d) If distribution of the work is made by offering access to copy
311 from a designated place, offer equivalent access to copy the above
312 specified materials from the same place.
313
314 e) Verify that the user has already received a copy of these
315 materials or that you have already sent this user a copy.
316
317 For an executable, the required form of the "work that uses the
318 Library" must include any data and utility programs needed for
319 reproducing the executable from it. However, as a special exception,
320 the materials to be distributed need not include anything that is
321 normally distributed (in either source or binary form) with the major
322 components (compiler, kernel, and so on) of the operating system on
323 which the executable runs, unless that component itself accompanies
324 the executable.
325
326 It may happen that this requirement contradicts the license
327 restrictions of other proprietary libraries that do not normally
328 accompany the operating system. Such a contradiction means you cannot
329 use both them and the Library together in an executable that you
330 distribute.
331
332 7. You may place library facilities that are a work based on the
333 Library side-by-side in a single library together with other library
334 facilities not covered by this License, and distribute such a combined
335 library, provided that the separate distribution of the work based on
336 the Library and of the other library facilities is otherwise
337 permitted, and provided that you do these two things:
338
339 a) Accompany the combined library with a copy of the same work
340 based on the Library, uncombined with any other library
341 facilities. This must be distributed under the terms of the
342 Sections above.
343
344 b) Give prominent notice with the combined library of the fact
345 that part of it is a work based on the Library, and explaining
346 where to find the accompanying uncombined form of the same work.
347
348 8. You may not copy, modify, sublicense, link with, or distribute
349 the Library except as expressly provided under this License. Any
350 attempt otherwise to copy, modify, sublicense, link with, or
351 distribute the Library is void, and will automatically terminate your
352 rights under this License. However, parties who have received copies,
353 or rights, from you under this License will not have their licenses
354 terminated so long as such parties remain in full compliance.
355
356 9. You are not required to accept this License, since you have not
357 signed it. However, nothing else grants you permission to modify or
358 distribute the Library or its derivative works. These actions are
359 prohibited by law if you do not accept this License. Therefore, by
360 modifying or distributing the Library (or any work based on the
361 Library), you indicate your acceptance of this License to do so, and
362 all its terms and conditions for copying, distributing or modifying
363 the Library or works based on it.
364
365 10. Each time you redistribute the Library (or any work based on the
366 Library), the recipient automatically receives a license from the
367 original licensor to copy, distribute, link with or modify the Library
368 subject to these terms and conditions. You may not impose any further
369 restrictions on the recipients' exercise of the rights granted herein.
370 You are not responsible for enforcing compliance by third parties with
371 this License.
372
373 11. If, as a consequence of a court judgment or allegation of patent
374 infringement or for any other reason (not limited to patent issues),
375 conditions are imposed on you (whether by court order, agreement or
376 otherwise) that contradict the conditions of this License, they do not
377 excuse you from the conditions of this License. If you cannot
378 distribute so as to satisfy simultaneously your obligations under this
379 License and any other pertinent obligations, then as a consequence you
380 may not distribute the Library at all. For example, if a patent
381 license would not permit royalty-free redistribution of the Library by
382 all those who receive copies directly or indirectly through you, then
383 the only way you could satisfy both it and this License would be to
384 refrain entirely from distribution of the Library.
385
386 If any portion of this section is held invalid or unenforceable under any
387 particular circumstance, the balance of the section is intended to apply,
388 and the section as a whole is intended to apply in other circumstances.
389
390 It is not the purpose of this section to induce you to infringe any
391 patents or other property right claims or to contest validity of any
392 such claims; this section has the sole purpose of protecting the
393 integrity of the free software distribution system which is
394 implemented by public license practices. Many people have made
395 generous contributions to the wide range of software distributed
396 through that system in reliance on consistent application of that
397 system; it is up to the author/donor to decide if he or she is willing
398 to distribute software through any other system and a licensee cannot
399 impose that choice.
400
401 This section is intended to make thoroughly clear what is believed to
402 be a consequence of the rest of this License.
403
404 12. If the distribution and/or use of the Library is restricted in
405 certain countries either by patents or by copyrighted interfaces, the
406 original copyright holder who places the Library under this License may add
407 an explicit geographical distribution limitation excluding those countries,
408 so that distribution is permitted only in or among countries not thus
409 excluded. In such case, this License incorporates the limitation as if
410 written in the body of this License.
411
412 13. The Free Software Foundation may publish revised and/or new
413 versions of the Lesser General Public License from time to time.
414 Such new versions will be similar in spirit to the present version,
415 but may differ in detail to address new problems or concerns.
416
417 Each version is given a distinguishing version number. If the Library
418 specifies a version number of this License which applies to it and
419 "any later version", you have the option of following the terms and
420 conditions either of that version or of any later version published by
421 the Free Software Foundation. If the Library does not specify a
422 license version number, you may choose any version ever published by
423 the Free Software Foundation.
424
425 14. If you wish to incorporate parts of the Library into other free
426 programs whose distribution conditions are incompatible with these,
427 write to the author to ask for permission. For software which is
428 copyrighted by the Free Software Foundation, write to the Free
429 Software Foundation; we sometimes make exceptions for this. Our
430 decision will be guided by the two goals of preserving the free status
431 of all derivatives of our free software and of promoting the sharing
432 and reuse of software generally.
433
434 NO WARRANTY
435
436 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
437 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
438 EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
439 OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
440 KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
441 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
442 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
443 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
444 THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
445
446 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
447 WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
448 AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
449 FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
450 CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
451 LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
452 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
453 FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
454 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
455 DAMAGES.
456
457 END OF TERMS AND CONDITIONS
458
459 How to Apply These Terms to Your New Libraries
460
461 If you develop a new library, and you want it to be of the greatest
462 possible use to the public, we recommend making it free software that
463 everyone can redistribute and change. You can do so by permitting
464 redistribution under these terms (or, alternatively, under the terms of the
465 ordinary General Public License).
466
467 To apply these terms, attach the following notices to the library. It is
468 safest to attach them to the start of each source file to most effectively
469 convey the exclusion of warranty; and each file should have at least the
470 "copyright" line and a pointer to where the full notice is found.
471
472 <one line to give the library's name and a brief idea of what it does.>
473 Copyright (C) <year> <name of author>
474
475 This library is free software; you can redistribute it and/or
476 modify it under the terms of the GNU Lesser General Public
477 License as published by the Free Software Foundation; either
478 version 2.1 of the License, or (at your option) any later version.
479
480 This library is distributed in the hope that it will be useful,
481 but WITHOUT ANY WARRANTY; without even the implied warranty of
482 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
483 Lesser General Public License for more details.
484
485 You should have received a copy of the GNU Lesser General Public
486 License along with this library; if not, write to the Free Software
487 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
488
489 Also add information on how to contact you by electronic and paper mail.
490
491 You should also get your employer (if you work as a programmer) or your
492 school, if any, to sign a "copyright disclaimer" for the library, if
493 necessary. Here is a sample; alter the names:
494
495 Yoyodyne, Inc., hereby disclaims all copyright interest in the
496 library `Frob' (a library for tweaking knobs) written by James Random Hacker.
497
498 <signature of Ty Coon>, 1 April 1990
499 Ty Coon, President of Vice
500
501 That's all there is to it!
0 MariaDB Connector/ODBC 3.1 GA
1
2 This is a GA release of the MariaDB Connector/ODBC.
3 MariaDB Connector/ODBC is released under version 2.1 of the
4 GNU Lesser Public License.
5
6 License information can be found in the COPYING file.
7
8 To report issues: https://jira.mariadb.org/projects/ODBC/issues/
0 # MariaDB Connector/ODBC 3.1
1 <p align="center">
2 <a href="http://mariadb.com/">
3 <img src="https://mariadb.com/kb/static/images/logo-2018-black.png">
4 </a>
5 </p>
6
7
8 ## Status
9 [![License (LGPL version 2.1)](https://img.shields.io/badge/license-GNU%20LGPL%20version%202.1-green.svg?style=flat-square)](http://opensource.org/licenses/LGPL-2.1)
10
11 This is a GA release of the MariaDB Connector/ODBC.
12 MariaDB Connector/ODBC is released under version 2.1 of the
13 GNU Lesser Public License.
14
15 License information can be found in the COPYING file.
16
17 Tracker link <a href="https://jira.mariadb.org/projects/ODBC/issues/">https://jira.mariadb.org/projects/ODBC/issues/</a>
18
19 ## Documentation
20
21 For a Getting started guide, API docs, recipes, etc. see the [About MariaDB connector/ODBC](https://mariadb.com/kb/en/mariadb/about-mariadb-connector-odbc/)
0 environment:
1 matrix:
2 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
3 DB: 10.3.11
4 CMAKE_PARAM_G: 'Visual Studio 14 2015 Win64'
5
6 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
7 DB: 10.3.11
8 CMAKE_PARAM_G: 'Visual Studio 15 2017 Win64'
9
10 # scripts that are called at very beginning, before repo cloning
11 init:
12 - git config --global core.autocrlf input
13 - wmic cpu get NumberOfCores
14 - wmic ComputerSystem get TotalPhysicalMemory
15
16 clone_folder: c:\maodbc
17 platform: x64
18 configuration: Release
19
20 build_script:
21 # build libmariadb separately first because otherwise the Wix installer build might look for files that aren't available yet
22 - cd libmariadb
23 - cmake --build . --config RelWithDebInfo --parallel 2
24 # build odbc
25 - cd ..
26 - cmake --build . --config RelWithDebInfo --parallel 2
27
28 # scripts to run before build
29 before_build:
30 - cd c:\maodbc
31 - git submodule init
32 - git submodule update
33 - mkdir win64
34 - cd win64
35 - cmake .. -G "%CMAKE_PARAM_G%" -DCONC_WITH_MSI=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWITH_SIGNCODE=0
36
37 after_build:
38 # download and install MariaDB Server
39 - set FILE=http://mariadb.mirrors.ovh.net/MariaDB/mariadb-%DB%/winx64-packages/mariadb-%DB%-winx64.msi
40 - ps: Start-FileDownload $Env:FILE -FileName server.msi -Timeout 900000
41 - msiexec /i server.msi INSTALLDIR=c:\mariadb-server SERVICENAME=mariadb /qn
42 # create test database
43 - c:\mariadb-server\bin\mysql.exe -e "CREATE DATABASE odbc_test" --user=root
44 # install built odbc driver
45 - ps: $msifile = Get-ChildItem $env:APPVEYOR_BUILD_FOLDER\win64\wininstall\mariadb-connector-odbc*.msi | Select-Object -First 1
46 - ps: Push-AppveyorArtifact $msifile.FullName -FileName $msifile.Name
47 - ps: Write $msifile
48 - ps: msiexec /i $msifile INSTALLDIR=c:\mariadb-odbc /qn
49 # add ODBC DSN with the built driver
50 # notice that it isn't possible to currently use Add-OdbcDsn in PowerShell. It will give an error because of missing properties. Therefore the
51 # DSN is added to registry below.
52 #- ps: Add-OdbcDsn -Name "test" -DriverName "MariaDB ODBC 3.1 Driver" -DsnType "System" -SetPropertyValue @("Server=localhost", "PORT=3306", "Database=odbc_test")
53 - ps: New-Item -Path "HKCU:\Software\ODBC"
54 - ps: New-Item -Path "HKCU:\Software\ODBC\ODBC.INI"
55 - ps: $regPath = "HKCU:\Software\ODBC\ODBC.INI\test"
56 - ps: New-Item -Path $regPath
57 - ps: New-ItemProperty -Path $regPath -Name "CONN_TIMEOUT" -Value "0"
58 - ps: New-ItemProperty -Path $regPath -Name "DATABASE" -Value "odbc_test"
59 - ps: New-ItemProperty -Path $regPath -Name "DESCRIPTION" -Value "MariaDB ODBC test"
60 - ps: New-ItemProperty -Path $regPath -Name "Driver" -Value "MariaDB ODBC 3.1 Driver"
61 - ps: New-ItemProperty -Path $regPath -Name "OPTIONS" -Value "0"
62 - ps: New-ItemProperty -Path $regPath -Name "PORT" -Value "0"
63 - ps: New-ItemProperty -Path $regPath -Name "PWD" -Value ""
64 - ps: New-ItemProperty -Path $regPath -Name "SERVER" -Value "localhost"
65 - ps: New-ItemProperty -Path $regPath -Name "SSLVERIFY" -Value "0"
66 - ps: New-ItemProperty -Path $regPath -Name "TCPIP" -Value "1"
67 - ps: New-ItemProperty -Path $regPath -Name "UID" -Value "root"
68 - ps: New-Item -Path "HKCU:\Software\ODBC\ODBC.INI\ODBC Data Sources"
69 - ps: New-ItemProperty -Path "HKCU:\Software\ODBC\ODBC.INI\ODBC Data Sources" -Name "test" -Value "MariaDB ODBC 3.1 Driver"
70
71 - timeout /T 1
72 # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
73 - cd test
74 - ctest -V
75
76 on_finish:
77 # - dir
78 # - dir RelWithDebInfo
79 # - dir wininstall
80 # - dir libmariadb\RelWithDebInfo
81 # - dir release
82 # - dir libmariadb
83 # - dir libmariadb\release
84 # - dir wininstall
85 # - type wininstall\mariadb_odbc.xml
0 CONFIGURE_FILE(${FILE_IN} ${FILE_OUT} @ONLY)
0 # Copyright (C) 2015 MariaDB Corporation AB
1 #
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of the GNU Library General Public
4 # License as published by the Free Software Foundation; either
5 # version 2.1 of the License, or (at your option) any later version.
6 #
7 # This library is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 # Library General Public License for more details.
11 #
12 # You should have received a copy of the GNU Library General Public
13 # License along with this library; if not see <http://www.gnu.org/licenses>
14 # or write to the Free Software Foundation, Inc.,
15 # 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
16
17 # FindDM.cmake
18 #
19 # Cmake script to look for driver manager includes and libraries on platforms others than Windows
20 # We expect that the driver manager is UnixODBC
21
22 IF(WITH_IODBC)
23 SET(ODBC_CONFIG_EXEC iodbc-config)
24 SET(ODBC_CONFIG_INCLUDES --cflags)
25 SET(ODBC_CONFIG_LIBS --libs)
26 SET(ODBC_LIBS iodbc)
27 SET(ODBC_INSTLIBS iodbcinst)
28 ELSE() #UnixODBC
29 SET(ODBC_CONFIG_EXEC odbc_config)
30 SET(ODBC_CONFIG_INCLUDES --include-prefix)
31 SET(ODBC_CONFIG_LIBS --lib-prefix)
32 SET(ODBC_LIBS odbc)
33 SET(ODBC_INSTLIBS odbcinst)
34 ENDIF()
35
36 FIND_PROGRAM(ODBC_CONFIG ${ODBC_CONFIG_EXEC}
37 PATH
38 /usr/bin
39 ${DM_DIR}
40 )
41
42 IF(ODBC_CONFIG)
43 MESSAGE(STATUS "Found ${ODBC_CONFIG_EXEC}: ${ODBC_CONFIG}")
44 EXECUTE_PROCESS(COMMAND ${ODBC_CONFIG} ${ODBC_CONFIG_INCLUDES}
45 OUTPUT_VARIABLE result)
46 STRING(REPLACE "\n" "" ODBC_INCLUDE_DIR ${result})
47 EXECUTE_PROCESS(COMMAND ${ODBC_CONFIG} ${ODBC_CONFIG_LIBS}
48 OUTPUT_VARIABLE result)
49 STRING(REPLACE "\n" "" ODBC_LIB_DIR ${result})
50
51 IF(WITH_IODBC)
52 STRING(REPLACE "-I" "" ODBC_INCLUDE_DIR ${ODBC_INCLUDE_DIR})
53 STRING(REPLACE "-L" "" ODBC_LIB_DIR ${ODBC_LIB_DIR})
54 STRING(REPLACE " -liodbc -liodbcinst" "" ODBC_LIB_DIR ${ODBC_LIB_DIR})
55 ENDIF()
56 ELSE()
57 MESSAGE(STATUS "${ODBC_CONFIG_EXEC} is not found ")
58 # Try to find the include directory, giving precedence to special variables
59 SET(LIB_PATHS /usr/local /usr)
60
61 IF("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
62 SET(LIB_PATHS "${LIB_PATHS}" "/usr/lib/x86_64-linux-gnu")
63
64 IF(EXISTS "/usr/lib64/")
65 SET(LIB_SUFFIX "lib64" "x86_64-linux-gnu")
66 ELSE()
67 SET(LIB_SUFFIX "lib" "x86_64-linux-gnu")
68 ENDIF()
69
70 ELSE()
71 SET(LIB_PATHS "${LIB_PATHS}" "/usr/local/lib/i386-linux-gnu" "/usr/lib/i386-linux-gnu" "/usr/local/lib/i686-linux-gnu" "/usr/lib/i686-linux-gnu")
72 SET(LIB_SUFFIX "lib" "i386-linux-gnu" "i686-linux-gnu")
73 ENDIF()
74
75 FIND_PATH(ODBC_INCLUDE_DIR sql.h
76 HINTS ${DM_INCLUDE_DIR}
77 ${DM_DIR}
78 ENV DM_INCLUDE_DIR
79 ENV DM_DIR
80 PATHS /usr/local
81 /usr
82 PATH_SUFFIXES include include/iodbc
83 NO_DEFAULT_PATH
84 DOC "Driver Manager Includes")
85 # Giving chance to cmake_(environment)path
86 FIND_PATH(ODBC_INCLUDE_DIR sql.h
87 DOC "Driver Manager Includes")
88
89 IF(ODBC_INCLUDE_DIR)
90 MESSAGE(STATUS "Found ODBC Driver Manager includes: ${ODBC_INCLUDE_DIR}")
91 ENDIF()
92 # Try to find DM libraries, giving precedence to special variables
93 FIND_PATH(ODBC_LIB_DIR "lib${ODBC_LIBS}.so"
94 HINTS ${DM_LIB_DIR}
95 ${DM_DIR}
96 ENV DM_LIB_DIR
97 ENV DM_DIR
98 PATHS ${LIB_PATHS}
99 PATH_SUFFIXES ${LIB_SUFFIX}
100 NO_DEFAULT_PATH
101 DOC "Driver Manager Libraries")
102 FIND_PATH(ODBC_LIB_DIR "lib${ODBC_LIBS}.so"
103 DOC "Driver Manager Libraries")
104 FIND_PATH(ODBCINST_LIB_DIR "lib${ODBC_INSTLIBS}.so"
105 HINTS ${DM_LIB_DIR}
106 ${DM_DIR}
107 ENV DM_LIB_DIR
108 ENV DM_DIR
109 PATHS ${LIB_PATHS}
110 PATH_SUFFIXES ${LIB_SUFFIX}
111 NO_DEFAULT_PATH
112 DOC "Driver Manager Libraries")
113 FIND_PATH(ODBCINST_LIB_DIR "lib${ODBC_INSTLIBS}.so"
114 DOC "Driver Manager Libraries")
115 ENDIF()
116
117 IF(ODBC_LIB_DIR AND ODBC_INCLUDE_DIR)
118 MESSAGE(STATUS "Found ODBC Driver Manager libraries: ${ODBC_LIB_DIR} ${ODBCINST_LIB_DIR}")
119 SET(DM_FOUND TRUE)
120 ENDIF()
0 # Copyright (c) 2010 Michael Bell <michael.bell@web.de>
1
2 if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
3 # Already in cache, be silent
4 set(ICONV_FIND_QUIETLY TRUE)
5 endif (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
6
7 IF(APPLE)
8 find_path(ICONV_INCLUDE_DIR iconv.h PATHS
9 /opt/local/include/
10 /usr/include/
11 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/
12 NO_CMAKE_SYSTEM_PATH)
13 ELSE()
14 find_path(ICONV_INCLUDE_DIR iconv.h)
15 ENDIF()
16
17 IF(APPLE)
18 find_library(ICONV_LIBRARIES NAMES iconv libiconv c PATHS
19 /opt/local/lib/
20 /usr/lib/
21 NO_CMAKE_SYSTEM_PATH)
22 SET(ICONV_EXTERNAL TRUE)
23 ELSE()
24 find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2)
25 IF(ICONV_LIBRARIES)
26 SET(ICONV_EXTERNAL TRUE)
27 ELSE()
28 find_library(ICONV_LIBRARIES NAMES c)
29 ENDIF()
30 ENDIF()
31
32 if (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
33 set (ICONV_FOUND TRUE)
34 endif (ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
35
36 set(CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIR})
37 IF(ICONV_EXTERNAL)
38 set(CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARIES})
39 ENDIF()
40
41 if (ICONV_FOUND)
42 include(CheckCSourceCompiles)
43 CHECK_C_SOURCE_COMPILES("
44 #include <iconv.h>
45 int main(){
46 iconv_t conv = 0;
47 const char* in = 0;
48 size_t ilen = 0;
49 char* out = 0;
50 size_t olen = 0;
51 iconv(conv, &in, &ilen, &out, &olen);
52 return 0;
53 }
54 " ICONV_SECOND_ARGUMENT_IS_CONST )
55 endif (ICONV_FOUND)
56
57 set (CMAKE_REQUIRED_INCLUDES)
58 set (CMAKE_REQUIRED_LIBRARIES)
59
60 if (ICONV_FOUND)
61 if (NOT ICONV_FIND_QUIETLY)
62 message (STATUS "Found Iconv: ${ICONV_LIBRARIES}")
63 endif (NOT ICONV_FIND_QUIETLY)
64 else (ICONV_FOUND)
65 if (Iconv_FIND_REQUIRED)
66 message (FATAL_ERROR "Could not find Iconv")
67 endif (Iconv_FIND_REQUIRED)
68 endif (ICONV_FOUND)
69
70 MARK_AS_ADVANCED(
71 ICONV_INCLUDE_DIR
72 ICONV_LIBRARIES
73 ICONV_EXTERNAL
74 ICONV_SECOND_ARGUMENT_IS_CONST
75 )
0 INCLUDE(CheckFunctionExists)
1 INCLUDE(CheckLibraryExists)
2
3 FUNCTION(SEARCH_LIBRARY library_name function liblist)
4 IF(${${library_name}})
5 RETURN()
6 ENDIF()
7 CHECK_FUNCTION_EXISTS(${function} ${function}_IS_SYS_FUNC)
8 # check if function is part of libc
9 IF(HAVE_${function}_IS_SYS_FUNC)
10 SET(${library_name} "" PARENT_SCOPE)
11 RETURN()
12 ENDIF()
13 FOREACH(lib ${liblist})
14 CHECK_LIBRARY_EXISTS(${lib} ${function} "" HAVE_${function}_IN_${lib})
15 IF(HAVE_${function}_IN_${lib})
16 SET(${library_name} ${lib} PARENT_SCOPE)
17 SET(HAVE_${library_name} 1 PARENT_SCOPE)
18 RETURN()
19 ENDIF()
20 ENDFOREACH()
21 ENDFUNCTION()
22
0 # Macro that checks if variable is defined, otherwise checks env for same name, otherwise uses default value
1 MACRO(SET_VALUE _variable _default_value)
2 IF (NOT ${_variable})
3 IF(DEFINED ENV{${_variable}})
4 SET(${_variable} $ENV{${_variable}})
5 ELSE()
6 SET(${_variable} ${_default_value})
7 ENDIF()
8 ENDIF()
9 ENDMACRO(SET_VALUE)
10
0 INCLUDE(FindGit)
1
2 IF(NOT EXISTS ${CMAKE_SOURCE_DIR}/libmariadb/CMakeLists.txt AND GIT_EXECUTABLE)
3 EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule init
4 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
5 EXECUTE_PROCESS(COMMAND "${GIT_EXECUTABLE}" submodule update
6 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
7 ENDIF()
8 IF(NOT EXISTS ${CMAKE_SOURCE_DIR}/libmariadb/CMakeLists.txt)
9 MESSAGE(FATAL_ERROR "No MariaDB Connector/C! Run
10 git submodule init
11 git submodule update
12 Then restart the build.
13 ")
14 ENDIF()
15
16 SET(OPT CONC_)
17
18 IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
19 SET(CONC_WITH_RTC ON)
20 ENDIF()
21
22 SET(CONC_WITH_SIGNCODE ${SIGNCODE})
23 SET(SIGN_OPTIONS ${SIGNTOOL_PARAMETERS})
24
25 IF(TARGET zlib)
26 GET_PROPERTY(ZLIB_LIBRARY_LOCATION TARGET zlib PROPERTY LOCATION)
27 ELSE()
28 SET(ZLIB_LIBRARY_LOCATION ${ZLIB_LIBRARY})
29 ENDIF()
30
31 SET(CONC_WITH_CURL OFF)
32 SET(CONC_WITH_MYSQLCOMPAT ON)
33
34 IF (INSTALL_LAYOUT STREQUAL "RPM")
35 SET(CONC_INSTALL_LAYOUT "RPM")
36 ELSE()
37 SET(CONC_INSTALL_LAYOUT "DEFAULT")
38 ENDIF()
39
40 SET(PLUGIN_INSTALL_DIR ${INSTALL_PLUGINDIR})
41 SET(MARIADB_UNIX_ADDR ${MYSQL_UNIX_ADDR})
42
43 MESSAGE("== Configuring MariaDB Connector/C")
44 ADD_SUBDIRECTORY(libmariadb)
0 # toolchain file for building a 32bit version on a 64bit host
1
2 # Usage:
3 # cmake -DCMAKE_TOOLCHAIN_FILE=linux_86.toolchain.cmake
4
5 set(CMAKE_SYSTEM_NAME Linux)
6 set(CMAKE_SYSTEM_VERSION 1)
7 set(CMAKE_SYSTEM_PROCESSOR "i686")
8
9 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32" CACHE STRING "c++ flags")
10 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32" CACHE STRING "c flags")
0 #include <sql.h>
1 #include <sqlext.h>
2
3 SQLRETURN SQL_API SQLColAttribute(SQLHSTMT StatementHandle,
4 SQLUSMALLINT ColumnNumber,
5 SQLUSMALLINT FieldIdentifier,
6 SQLPOINTER CharacterAttributePtr,
7 SQLSMALLINT BufferLength,
8 SQLSMALLINT *StringLengthPtr,
9 SQLPOINTER NumericAttributePtr )
10 {
11 return SQL_SUCCESS;
12 }
13
14 int main() {
15 return 0;
16 }
0 /************************************************************************************
1 Copyright (C) 2013,2014 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 #ifndef _ma_odbc_setup_h_
20 #define _ma_odbc_setup_h_
21
22 #define MA_WIN_SET_VALUE(Page, Field, Value) \
23 Edit_SetText(GetDlgItem(hwndTab[(Page)],(Field)), (Value));
24
25 #define MA_WIN_SET_MAXLEN(Page, Field, Value) \
26 Edit_LimitText(GetDlgItem(hwndTab[(Page)],(Field)), (Value));
27
28
29
30 typedef struct
31 {
32 MADB_DsnKey *Key;
33 int Page;
34 int Item;
35 int MaxLength; /* For DSN_TYPE_CBOXGROUP that is the bit it represents */
36 my_bool Mandatory;
37 } MADB_DsnMap;
38
39 #endif /* _ma_odbc_setup_h_ */
0 LIBRARY maodbcs.dll
1 EXPORTS
2 ConfigDSN
3 DSNDialog
4 DSNPrompt
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #define WIN32_LEAN_AND_MEAN
19
20 #include <Windows.h>
21 #include <stdlib.h>
22 #include <CommCtrl.h>
23 #include <tchar.h>
24 #include <windowsx.h>
25 #include <winuser.h>
26 #include <shobjidl.h>
27 #include "resource.h"
28 #include <ma_odbc.h>
29 #include <ma_odbc_setup.h>
30
31 #pragma comment(lib, "ComCtl32.lib")
32
33 #define LASTPAGE 5
34
35 HINSTANCE hInstance;
36 unsigned int CurrentPage= 0;
37 SQLHANDLE Environment= NULL;
38 my_bool DBFilled= FALSE;
39 my_bool CSFilled= FALSE;
40 my_bool ConnectionOK= FALSE;
41 my_bool notCanceled= TRUE;
42
43 char DSNStr[2048];
44 HWND hwndTab[7], hwndMain;
45 const int *EffectiveDisabledPages= NULL,
46 *EffectiveDisabledControls= NULL;
47 BOOL OpenCurSelection= TRUE;
48
49 /* On Windows we are supposed to have schannel, or we can have openssl */
50 #if defined(_WIN32) || defined(HAVE_OPENSSL)
51 # define SSL_DISABLED 0
52 #else
53 # define SSL_DISABLED 1
54 #endif
55
56 const int DisabledPages[MAODBC_PROMPT_REQUIRED + 1][LASTPAGE + 1]= {
57 { 0, 0, 0, 0, SSL_DISABLED, 0},
58 { 0, 0, 0, 0, SSL_DISABLED, 0},
59 { 1, 0, 1, 1, 1, 1}
60 };
61 const int PromptDisabledControls[]= { txtDsnName, 0 },
62 EmptyDisabledControls[]= { 0 };
63 const int* DisabledControls[]= {
64 EmptyDisabledControls,
65 PromptDisabledControls,
66 EmptyDisabledControls
67 };
68
69 MADB_DsnMap DsnMap[] = {
70 {&DsnKeys[0], 0, txtDsnName, 64, 1},
71 {&DsnKeys[1], 0, txtDSNDescription, 64, 0},
72 {&DsnKeys[5], 1, rbPipe, 0, 0},
73 {&DsnKeys[6], 1, rbTCP, 0, 0},
74 {&DsnKeys[7], 1, txtServerName, 128, 0},
75 {&DsnKeys[8], 1, txtUserName, 64, 0},
76 {&DsnKeys[9], 1, txtPassword, 64, 0},
77 {&DsnKeys[10], 1, cbDatabase, 0, 0},
78 {&DsnKeys[11], 1, txtPort, 5, 0},
79 {&DsnKeys[12], 2, txtInitCmd, 2048, 0},
80 {&DsnKeys[13], 2, txtConnectionTimeOut, 5, 0},
81 {&DsnKeys[14], 2, ckReconnect, 0, 0},
82 {&DsnKeys[15], 2, ckConnectPrompt, 0, 0},
83 {&DsnKeys[16], 2, cbCharset, 0, 0},
84 {&DsnKeys[18], 3, txtPluginDir, 260, 0},
85 {&DsnKeys[19], 4, txtSslKey, 260, 0},
86 {&DsnKeys[20], 4, txtSslCert, 260, 0},
87 {&DsnKeys[21], 4, txtSslCertAuth, 260, 0},
88 {&DsnKeys[22], 4, txtSslCaPath, 260, 0},
89 {&DsnKeys[23], 4, txtSslCipher, 32, 0},
90 {&DsnKeys[24], 4, cbSslVerify, 0, 0},
91 {&DsnKeys[32], 4, cbTls11, 1, 0},
92 {&DsnKeys[32], 4, cbTls12, 2, 0},
93 {&DsnKeys[32], 4, cbTls13, 4, 0},
94 {&DsnKeys[33], 4, cbForceTls, 0, 0},
95 {NULL, 0, 0, 0, 0}
96 };
97
98 #define CBGROUP_BIT(MapIdx) (char)(DsnMap[MapIdx].MaxLength)
99 #define IS_CB_CHECKED(MapIdx) GetButtonState(DsnMap[MapIdx].Page, DsnMap[MapIdx].Item)
100 #define CBGROUP_SETBIT(_Dsn, MapIdx) *GET_FIELD_PTR(_Dsn, DsnMap[MapIdx].Key, char)|= CBGROUP_BIT(MapIdx)
101 #define CBGROUP_RESETBIT(_Dsn, MapIdx) *GET_FIELD_PTR(_Dsn, DsnMap[MapIdx].Key, char)&= ~CBGROUP_BIT(MapIdx)
102
103 MADB_OptionsMap OptionsMap[]= {
104 {1, rbPipe, MADB_OPT_FLAG_NAMED_PIPE},
105 {2, ckReconnect, MADB_OPT_FLAG_AUTO_RECONNECT},
106 {2, ckConnectPrompt, MADB_OPT_FLAG_NO_PROMPT},
107 {2, ckCompressed, MADB_OPT_FLAG_COMPRESSED_PROTO},
108 {2, ckUseMycnf, MADB_OPT_FLAG_USE_CNF},
109 {3, ckIgnoreSchema, MADB_OPT_FLAG_NO_SCHEMA},
110 {3, ckIgnoreSpace, MADB_OPT_FLAG_IGNORE_SPACE},
111 {3, ckMultiStmt, MADB_OPT_FLAG_MULTI_STATEMENTS},
112 {LASTPAGE, ckIgnoreSchema, MADB_OPT_FLAG_NO_SCHEMA},
113 {LASTPAGE, ckEnableDynamicCursor, MADB_OPT_FLAG_DYNAMIC_CURSOR},
114 {LASTPAGE, ckDisableDriverCursor, MADB_OPT_FLAG_NO_DEFAULT_CURSOR},
115 {LASTPAGE, ckDontCacheForwardCursor, MADB_OPT_FLAG_NO_CACHE},
116 {LASTPAGE, ckForwardCursorOnly, MADB_OPT_FLAG_FORWARD_CURSOR},
117 {LASTPAGE, ckReturnMatchedRows, MADB_OPT_FLAG_FOUND_ROWS},
118 {LASTPAGE, ckEnableSQLAutoIsNull, MADB_OPT_FLAG_AUTO_IS_NULL},
119 {LASTPAGE, ckPadCharFullLength, MADB_OPT_FLAG_PAD_SPACE},
120 {LASTPAGE, ckNullDate, MADB_OPT_FLAG_ZERO_DATE_TO_MIN},
121 {LASTPAGE, ckDebug, MADB_OPT_FLAG_DEBUG},
122 {LASTPAGE, ckReturnMatchedRows, MADB_OPT_FLAG_FOUND_ROWS},
123 {LASTPAGE, ckIgnoreSpace, MADB_OPT_FLAG_IGNORE_SPACE},
124 /* last element */
125 {0, 0, 0}
126 };
127
128 void GetDialogFields(void);
129 HBRUSH hbrBg= NULL;
130
131 my_bool SetDialogFields()
132 {
133 int i= 0;
134 MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);
135
136 while (DsnMap[i].Key)
137 {
138 switch (DsnMap[i].Key->Type) {
139 case DSN_TYPE_STRING:
140 case DSN_TYPE_COMBO:
141 {
142 char *Val= *(char **)((char *)Dsn + DsnMap[i].Key->DsnOffset);
143 if (Val && Val[0])
144 SetDlgItemText(hwndTab[DsnMap[i].Page], DsnMap[i].Item, Val);
145 break;
146 }
147 case DSN_TYPE_INT:
148 {
149 int Val= *(int *)((char *)Dsn + DsnMap[i].Key->DsnOffset);
150 SetDlgItemInt(hwndTab[DsnMap[i].Page], DsnMap[i].Item, Val, 0);
151 }
152 break;
153 case DSN_TYPE_BOOL:
154 {
155 my_bool Val= *(my_bool *)((char *)Dsn + DsnMap[i].Key->DsnOffset);
156 SendDlgItemMessage(hwndTab[DsnMap[i].Page], DsnMap[i].Item, BM_SETCHECK,
157 Val ? BST_CHECKED : BST_UNCHECKED, 0);
158 }
159 break;
160 case DSN_TYPE_CBOXGROUP:
161 SendDlgItemMessage(hwndTab[DsnMap[i].Page], DsnMap[i].Item, BM_SETCHECK,
162 (*GET_FIELD_PTR(Dsn, DsnMap[i].Key, char) & CBGROUP_BIT(i)) != '\0' ? BST_CHECKED : BST_UNCHECKED, 0);
163 }
164 i++;
165 }
166 i= 0;
167 while (OptionsMap[i].Item != 0)
168 {
169 my_bool Val= (Dsn->Options & OptionsMap[i].value) ? 1 : 0;
170 SendDlgItemMessage(hwndTab[OptionsMap[i].Page], OptionsMap[i].Item, BM_SETCHECK,
171 Val ? BST_CHECKED : BST_UNCHECKED, 0);
172 if (Val && OptionsMap[i].Item == rbPipe)
173 {
174 SendMessage(GetDlgItem(hwndTab[OptionsMap[i].Page], lblServerName), WM_SETTEXT, 0, (LPARAM)"Named pipe:");
175 ShowWindow(GetDlgItem(hwndTab[OptionsMap[i].Page], lblPort), SW_HIDE);
176 ShowWindow(GetDlgItem(hwndTab[OptionsMap[i].Page], txtPort), SW_HIDE);
177 }
178 i++;
179 }
180 return TRUE;
181
182 }
183
184 char *GetFieldStrVal(int Dialog, int Field, char* (*allocator)(size_t))
185 {
186 int rc;
187 int len= Edit_GetTextLength(GetDlgItem(hwndTab[Dialog], Field));
188 char *p;
189
190 if (allocator)
191 {
192 p= allocator(len * sizeof(char) + 2);
193 }
194 else
195 {
196 p= (char *)MADB_CALLOC(len * sizeof(char) + 2);
197 }
198
199 if (p)
200 rc= Edit_GetText(GetDlgItem(hwndTab[Dialog], Field), p, len + 1);
201 return p;
202 }
203
204 int GetFieldIntVal(int Dialog, int Field)
205 {
206 int rc= 0;
207 char *p= GetFieldStrVal(Dialog, Field, NULL);
208 if (p)
209 {
210 rc= atoi(p);
211 free(p);
212 }
213 return rc;
214 }
215
216 my_bool GetButtonState(int Dialog, int Button)
217 {
218 return (my_bool)IsDlgButtonChecked(hwndTab[Dialog], Button);
219 }
220
221 my_bool SaveDSN(HWND hDlg, MADB_Dsn *Dsn)
222 {
223 if (Dsn->SaveFile != NULL || MADB_SaveDSN(Dsn))
224 return TRUE;
225 MessageBox(hDlg, Dsn->ErrorMsg, "Error", MB_OK);
226 return FALSE;
227 }
228
229
230 unsigned int GetNextActiveTab(int current_page, int offset)
231 {
232 unsigned int result= current_page + offset;
233
234 for (; result >= 0 && result <= LASTPAGE && EffectiveDisabledPages[result] != 0; result+= offset)
235 {
236 if (offset > 1)
237 {
238 offset= 1;
239 }
240 else if (offset < -1)
241 {
242 offset= -1;
243 }
244 }
245
246 if (result < 0 || result > LASTPAGE)
247 {
248 result= current_page;
249 }
250
251 return result;
252 }
253
254
255 #define DISABLE_CONTROLS(page_map) i= 0;\
256 /* Assuming that controls in the #page_map are sorted by tab page */\
257 while (page_map[i].Item && page_map[i].Page != CurrentPage && ++i);\
258 \
259 while (page_map[i].Item && page_map[i].Page == CurrentPage)\
260 {\
261 int j= 0;\
262 while (EffectiveDisabledControls[j])\
263 {\
264 if (EffectiveDisabledControls[j] == page_map[i].Item)\
265 {\
266 EnableWindow(GetDlgItem(hwndTab[CurrentPage], EffectiveDisabledControls[j]), FALSE);\
267 }\
268 ++j;\
269 }\
270 ++i;\
271 } 1
272
273 void DisableControls(MADB_Dsn *Dsn)
274 {
275 int i;
276
277 DISABLE_CONTROLS(DsnMap);
278 DISABLE_CONTROLS(OptionsMap);
279 }
280
281
282 void SetPage(HWND hDlg, int value)
283 {
284 MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);
285 unsigned int new_page= GetNextActiveTab(CurrentPage, value);
286
287 /* Save if last page or all following pages are disabled */
288 if (value > 0 && (CurrentPage == LASTPAGE || new_page== CurrentPage))
289 {
290 GetDialogFields();
291 if (Dsn->isPrompt || SaveDSN(hDlg, Dsn))
292 {
293 SendMessage(hwndMain, WM_DESTROY, 0, 0);
294 }
295 return;
296 }
297
298 ShowWindow(hwndTab[CurrentPage != (unsigned int)(-1) ? CurrentPage : 0], SW_HIDE);
299
300 CurrentPage= new_page;
301
302 ShowWindow(hwndTab[CurrentPage], SW_SHOW);
303
304 DisableControls(Dsn);
305
306 /* Disabling prev button if needed*/
307 new_page= GetNextActiveTab(CurrentPage, -1);
308 EnableWindow(GetDlgItem(hwndTab[CurrentPage], PB_PREV), (CurrentPage != new_page) ? TRUE : FALSE);
309
310 /* Switching caption of the Next/Finish button if needed*/
311 new_page= GetNextActiveTab(CurrentPage, 1);
312 SendMessage(GetDlgItem(hwndTab[CurrentPage], PB_NEXT), WM_SETTEXT, 0, (CurrentPage == new_page) ? (LPARAM)"Finish" : (LPARAM)"Next >");
313 SetFocus(hwndTab[CurrentPage]);
314
315 /* If not a prompt - disable finish button in case of empty DS name(for prompt it may be empty/invalid)
316 TODO: I think it rather has to check if the name is valid DS name */
317 if (Dsn->isPrompt == MAODBC_CONFIG && CurrentPage == new_page)
318 {
319 EnableWindow(GetDlgItem(hwndTab[CurrentPage], PB_NEXT),
320 Edit_GetTextLength(GetDlgItem(hwndTab[0], txtDsnName)) ? TRUE : FALSE);
321 }
322 }
323
324 void GetDialogFields()
325 {
326 int i= 0;
327 MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);
328
329 while (DsnMap[i].Key)
330 {
331 switch (DsnMap[i].Key->Type) {
332 case DSN_TYPE_STRING:
333 case DSN_TYPE_COMBO:
334 {
335 char **p= (char **)((char *)Dsn + DsnMap[i].Key->DsnOffset);
336
337 if (Dsn->isPrompt != 0 && Dsn->free != NULL)
338 {
339 Dsn->free(*p);
340 }
341 *p= GetFieldStrVal(DsnMap[i].Page, DsnMap[i].Item, Dsn->allocator && Dsn->isPrompt ? Dsn->allocator : NULL);
342 }
343 break;
344 case DSN_TYPE_INT:
345 *(int *)((char *)Dsn + DsnMap[i].Key->DsnOffset)= GetFieldIntVal(DsnMap[i].Page, DsnMap[i].Item);
346 break;
347 case DSN_TYPE_BOOL:
348 *GET_FIELD_PTR(Dsn, DsnMap[i].Key, my_bool)= IS_CB_CHECKED(i);
349 break;
350 case DSN_TYPE_CBOXGROUP:
351 if (IS_CB_CHECKED(i) != '\0')
352 {
353 CBGROUP_SETBIT(Dsn, i);
354 }
355 else
356 {
357 CBGROUP_RESETBIT(Dsn, i);
358 }
359 }
360 ++i;
361 }
362 i= 0;
363 Dsn->Options= 0;
364 while (OptionsMap[i].Item != 0)
365 {
366 if (GetButtonState(OptionsMap[i].Page, OptionsMap[i].Item))
367 Dsn->Options|= OptionsMap[i].value;
368 i++;
369 }
370 }
371
372 void DSN_Set_Database(SQLHANDLE Connection)
373 {
374 MADB_Stmt *Stmt= NULL;
375 SQLRETURN ret= SQL_ERROR;
376 char Database[65];
377 MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);
378
379
380 if (DBFilled)
381 return;
382
383 GetDialogFields();
384
385 if (SQLAllocHandle(SQL_HANDLE_STMT, Connection, (SQLHANDLE *)&Stmt) != SQL_SUCCESS)
386 goto end;
387
388 if (SQLExecDirect((SQLHSTMT)Stmt, (SQLCHAR *)"SHOW DATABASES", SQL_NTS) != SQL_SUCCESS)
389 goto end;
390
391 SQLBindCol(Stmt, 1, SQL_C_CHAR, Database, 65, 0);
392 ComboBox_ResetContent(GetDlgItem(hwndTab[1], cbDatabase));
393 while (SQLFetch(Stmt) == SQL_SUCCESS)
394 ComboBox_InsertString(GetDlgItem(hwndTab[1], cbDatabase), -1, Database);
395 if (Dsn->Catalog)
396 {
397 int Idx= ComboBox_FindString(GetDlgItem(hwndTab[2], cbDatabase), 0, Dsn->Catalog);
398 ComboBox_SetCurSel(GetDlgItem(hwndTab[2], cbDatabase), Idx);
399 }
400 ComboBox_SetMinVisible(GetDlgItem(hwndTab[1], cbDatabase),5);
401 DBFilled= TRUE;
402
403 end:
404 if (Stmt)
405 SQLFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE)Stmt);
406 }
407
408 void DSN_Set_CharacterSets(SQLHANDLE Connection)
409 {
410 MADB_Stmt *Stmt= NULL;
411 SQLRETURN ret= SQL_ERROR;
412 char Charset[65];
413 MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);
414
415 if (CSFilled)
416 return;
417
418 GetDialogFields();
419
420 if (SQLAllocHandle(SQL_HANDLE_STMT, Connection, (SQLHANDLE *)&Stmt) != SQL_SUCCESS)
421 goto end;
422
423 if (SQLExecDirect((SQLHSTMT)Stmt,
424 (SQLCHAR *)"select character_set_name from information_schema.collations "
425 "WHERE character_set_name NOT LIKE 'utf16%' AND "
426 "character_set_name NOT LIKE 'utf32%' AND "
427 "character_set_name NOT LIKE 'ucs2' "
428 "group by character_set_name order by character_set_name"
429 , SQL_NTS) != SQL_SUCCESS)
430 goto end;
431
432 SQLBindCol(Stmt, 1, SQL_C_CHAR, Charset, 65, 0);
433 ComboBox_ResetContent(GetDlgItem(hwndTab[2], cbCharset));
434
435 while (SQLFetch(Stmt) == SQL_SUCCESS)
436 ComboBox_InsertString(GetDlgItem(hwndTab[2], cbCharset), -1, Charset);
437 if (Dsn->CharacterSet)
438 {
439 int Idx= ComboBox_FindString(GetDlgItem(hwndTab[2], cbCharset), 0, Dsn->CharacterSet);
440 ComboBox_SetCurSel(GetDlgItem(hwndTab[2], cbCharset), Idx);
441 }
442 ComboBox_SetMinVisible(GetDlgItem(hwndTab[2], cbCharset),5);
443 CSFilled= TRUE;
444
445 end:
446 if (Stmt)
447 SQLFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE)Stmt);
448 }
449
450
451 static SQLRETURN TestDSN(MADB_Dsn *Dsn, SQLHANDLE *Conn)
452 {
453 SQLHANDLE Connection= NULL;
454 SQLRETURN Result;
455 char * InitCommand= Dsn->InitCommand;
456
457 Dsn->InitCommand= NULL;
458
459 SQLAllocHandle(SQL_HANDLE_DBC, Environment, (SQLHANDLE *)&Connection);
460 assert(Connection != NULL);
461 Result= ((MADB_Dbc *)Connection)->Methods->ConnectDB((MADB_Dbc *)Connection, Dsn);
462
463 Dsn->InitCommand= InitCommand;
464
465 if (Conn != NULL)
466 {
467 *Conn= Connection;
468 }
469 else
470 {
471 SQLDisconnect(Connection);
472 SQLFreeHandle(SQL_HANDLE_DBC, Connection);
473 }
474
475 return Result;
476 }
477
478
479 void MADB_WIN_TestDsn(my_bool ShowSuccess)
480 {
481 SQLHANDLE Connection;
482 SQLRETURN ret;
483 MADB_Dsn *Dsn= (MADB_Dsn *)GetWindowLongPtr(GetParent(hwndTab[0]), DWLP_USER);
484
485 GetDialogFields();
486
487 ret= TestDSN(Dsn, &Connection);
488
489 if (ShowSuccess)
490 {
491 char Info[1024];
492 if (SQL_SUCCEEDED(ret))
493 {
494 _snprintf(Info, 1024, "Connection successfully established\n\nServer information: %s", mysql_get_server_info(((MADB_Dbc *)Connection)->mariadb));
495 MessageBox(hwndTab[CurrentPage], Info, "Connection test", MB_ICONINFORMATION| MB_OK);
496 }
497 else
498 {
499 MessageBox(hwndTab[CurrentPage], ((MADB_Dbc *)Connection)->Error.SqlErrorMsg, "Connection test", MB_ICONINFORMATION| MB_OK);
500 }
501 }
502
503 if (SQL_SUCCEEDED(ret))
504 {
505 ConnectionOK= TRUE;
506 DSN_Set_CharacterSets(Connection);
507 DSN_Set_Database(Connection);
508
509 SQLDisconnect(Connection);
510 }
511
512 SQLFreeHandle(SQL_HANDLE_DBC, Connection);
513 }
514
515
516 INT_PTR SelectPath(HWND ParentWnd, int BoundEditId, const wchar_t *Caption, BOOL FolderPath, BOOL OpenCurrentSelection)
517 {
518 if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)))
519 {
520 IFileDialog *PathDialog;
521
522 if (SUCCEEDED(CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
523 &IID_IFileOpenDialog, (void**)&PathDialog)))
524 {
525 HWND BoundEditWnd= GetDlgItem(ParentWnd, BoundEditId);
526 DWORD DialogOptions;
527 TCHAR Path[MAX_PATH];
528 IShellItem *SelectedItem;
529 int Length;
530 LPWSTR wPath;
531
532 if (FolderPath && SUCCEEDED(PathDialog->lpVtbl->GetOptions(PathDialog, &DialogOptions)))
533 {
534 PathDialog->lpVtbl->SetOptions(PathDialog, DialogOptions | FOS_PICKFOLDERS);
535 }
536
537 Edit_GetText(BoundEditWnd, Path, sizeof(Path));
538 Length= MultiByteToWideChar(GetACP(), 0, Path, -1, NULL, 0);
539
540 wPath= (SQLWCHAR *)malloc(Length * sizeof(SQLWCHAR));
541 if (wPath == NULL)
542 {
543 return FALSE;
544 }
545
546 MultiByteToWideChar(GetACP(), 0, Path, -1, wPath, Length);
547
548 SHCreateItemFromParsingName(wPath, NULL, &IID_IShellItem, (void**)&SelectedItem);
549 if (OpenCurrentSelection)
550 {
551 PathDialog->lpVtbl->SetFolder(PathDialog, SelectedItem);
552 }
553 else
554 {
555 PathDialog->lpVtbl->SetDefaultFolder(PathDialog, SelectedItem);
556 }
557 SelectedItem->lpVtbl->Release(SelectedItem);
558
559 free(wPath);
560
561 PathDialog->lpVtbl->SetTitle(PathDialog, Caption);
562
563 if (SUCCEEDED(PathDialog->lpVtbl->Show(PathDialog, ParentWnd)))
564 {
565 if (SUCCEEDED(PathDialog->lpVtbl->GetResult(PathDialog, &SelectedItem)))
566 {
567 LPWSTR SelectedValue;
568 if (SUCCEEDED(SelectedItem->lpVtbl->GetDisplayName(SelectedItem, SIGDN_FILESYSPATH, &SelectedValue)))
569 {
570 BOOL Error;
571
572 /* TODO: I guess conversions from/to utf8 has to be done when syncing edits with DSN */
573 WideCharToMultiByte(GetACP(), 0, SelectedValue, -1, Path, sizeof(Path), NULL, &Error);
574 Edit_SetText(BoundEditWnd, Path);
575 CoTaskMemFree(SelectedValue);
576
577 return TRUE;
578 }
579 SelectedItem->lpVtbl->Release(SelectedItem);
580 }
581 }
582 PathDialog->lpVtbl->Release(PathDialog);
583 }
584 CoUninitialize();
585 }
586
587 return FALSE;
588 }
589
590
591 INT_PTR CALLBACK DialogDSNProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
592 {
593 INT_PTR res;
594
595 switch(uMsg)
596 {
597 case WM_CTLCOLORDLG:
598 if (!hbrBg)
599 hbrBg= CreateSolidBrush(RGB(255,255,255));
600 return (INT_PTR)hbrBg;
601 break;
602 case WM_CTLCOLORSTATIC:
603 {
604 HDC hdcStatic = (HDC)wParam;
605 SetTextColor(hdcStatic, RGB(0, 0, 0));
606 SetBkMode(hdcStatic, TRANSPARENT);
607 return (INT_PTR)hbrBg;
608 }
609 case WM_COMMAND:
610 switch(LOWORD(wParam))
611 {
612 case IDCANCEL:
613 SendMessage(GetParent(hDlg), WM_CLOSE, 0, 0);
614 notCanceled= FALSE;
615 return TRUE;
616 case PB_PREV:
617 SetPage(hDlg, -1);
618 return TRUE;
619 case PB_NEXT:
620 SetPage(hDlg, 1);
621 return TRUE;
622 case pbTestDSN:
623 MADB_WIN_TestDsn(TRUE);
624 return TRUE;
625 case cbDatabase:
626 case cbCharset:
627 if(HIWORD(wParam) == CBN_DROPDOWN)
628 if (!ConnectionOK)
629 {
630 MessageBox(hwndTab[CurrentPage], "To load catalogs and character sets please test connection first",
631 "Warning", MB_OK);
632 return FALSE;
633 }
634 return TRUE;
635 case pbPlugindirBrowse:
636 return SelectPath(hDlg, txtPluginDir, L"Select Plugins Directory", /* Folder*/ TRUE, TRUE);
637 case pbCaPathBrowse:
638 res= SelectPath(hDlg, txtSslCaPath, L"Select CA Path", TRUE, OpenCurSelection);
639 OpenCurSelection= OpenCurSelection && !res;
640 return res;
641 case pbKeyBrowse:
642 res= SelectPath(hDlg, txtSslKey, L"Select Client Private Key File", /* File */ FALSE, OpenCurSelection);
643 OpenCurSelection= OpenCurSelection && !res;
644 return res;
645 case pbCertBrowse:
646 res= SelectPath(hDlg, txtSslCert, L"Select Public Key Certificate File", FALSE, OpenCurSelection);
647 OpenCurSelection= OpenCurSelection && !res;
648 return res;
649 case pbCaCertBrowse:
650 res= SelectPath(hDlg, txtSslCertAuth, L"Select Certificate Authority Certificate File", FALSE,OpenCurSelection);
651 OpenCurSelection= OpenCurSelection && !res;
652 return res;
653 case rbTCP:
654 case rbPipe:
655 if (HIWORD(wParam) == BN_CLICKED)
656 {
657 SendMessage(GetDlgItem(hwndTab[CurrentPage], lblServerName), WM_SETTEXT, 0,
658 (LOWORD(wParam) == rbTCP) ? (LPARAM)"Server name:" : (LPARAM)"Named pipe:");
659 ShowWindow(GetDlgItem(hwndTab[CurrentPage], lblPort),
660 (LOWORD(wParam) == rbTCP) ? SW_SHOW : SW_HIDE);
661 ShowWindow(GetDlgItem(hwndTab[CurrentPage], txtPort),
662 (LOWORD(wParam) == rbTCP) ? SW_SHOW : SW_HIDE);
663 }
664 return TRUE;
665
666 }
667 break;
668 }
669 return FALSE;
670 }
671
672 INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
673 {
674 switch(uMsg)
675 {
676 case WM_CTLCOLORDLG:
677 if (!hbrBg)
678 hbrBg= CreateSolidBrush(RGB(255,255,255));
679 return (INT_PTR)hbrBg;
680 break;
681 case WM_CLOSE:
682 if(MessageBox(hDlg, TEXT("Close the program?"), TEXT("Close"),
683 MB_ICONQUESTION | MB_YESNO) == IDYES)
684 {
685 notCanceled= FALSE;
686 DestroyWindow(hDlg);
687 } return TRUE;
688
689 case WM_DESTROY:
690 DestroyWindow(hDlg);
691 PostQuitMessage(0);
692 return TRUE;
693 case WM_INITDIALOG:
694 {
695 static int Dialogs[] = {Page_0, Page_1, Page_2, Page_3, Page_4, Page_5};
696 int i;
697 RECT rc;
698 GetWindowRect(hDlg, &rc);
699
700 for (i= 0; i <= LASTPAGE; ++i)
701 {
702 hwndTab[i]= CreateDialog(hInstance, MAKEINTRESOURCE(Dialogs[i]), hDlg, DialogDSNProc);
703 SetWindowPos(hwndTab[i], 0, 120, 5, (rc.right-rc.left)-120, (rc.bottom-rc.top), SWP_NOZORDER | SWP_NOACTIVATE);
704 ShowWindow(hwndTab[i], (i == 0) ? SW_SHOW : SW_HIDE);
705 }
706 i= 0;
707 while (DsnMap[i].Key)
708 {
709 if (DsnMap[i].MaxLength)
710 MA_WIN_SET_MAXLEN(DsnMap[i].Page, DsnMap[i].Item, DsnMap[i].MaxLength);
711 ++i;
712 }
713
714 return TRUE;
715 }
716 }
717 return FALSE;
718 }
719
720
721 BOOL APIENTRY DllMain( HMODULE hModule,
722 DWORD ul_reason_for_call,
723 LPVOID lpReserved
724 )
725 {
726 hInstance= hModule;
727 return TRUE;
728 }
729
730
731 void CenterWindow(HWND hwndWindow)
732 {
733 RECT rectWindow;
734
735 int nWidth, nHeight, nScreenWidth, nScreenHeight;
736 GetWindowRect(hwndWindow, &rectWindow);
737
738 nWidth = rectWindow.right - rectWindow.left;
739 nHeight = rectWindow.bottom - rectWindow.top;
740
741 nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
742 nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
743
744 MoveWindow(hwndWindow, (nScreenWidth - nWidth) / 2, (nScreenHeight - nHeight) / 2,
745 nWidth, nHeight, TRUE);
746
747 }
748
749
750 BOOL DSNDialog(HWND hwndParent,
751 WORD fRequest,
752 LPCSTR lpszDriver,
753 LPCSTR lpszAttributes,
754 MADB_Dsn *Dsn)
755 {
756 MSG msg;
757 BOOL ret;
758 char *DsnName= NULL;
759 my_bool DsnExists= FALSE;
760 char Delimiter= ';';
761
762 if (Dsn->isPrompt < 0 || Dsn->isPrompt > MAODBC_PROMPT_REQUIRED)
763 {
764 Dsn->isPrompt= MAODBC_CONFIG;
765 }
766
767 if (lpszAttributes)
768 {
769 Delimiter= '\0';
770 DsnName= strchr((char *)lpszAttributes, '=');
771 }
772
773 if (DsnName)
774 {
775 ++DsnName;
776 /* In case of prompting we are supposed to show dialog even DSN name is incorrect */
777 if (!Dsn->isPrompt && !SQLValidDSN(DsnName))
778 {
779 if (hwndParent)
780 {
781 MessageBox(hwndParent, "Validation of data source name failed", "Error", MB_ICONERROR | MB_OK);
782 }
783 return FALSE;
784 }
785 }
786
787 if (!DsnName && Dsn && Dsn->DSNName)
788 {
789 DsnName= Dsn->DSNName;
790 }
791 else if (DsnName && Dsn)
792 {
793 MADB_RESET(Dsn->DSNName, DsnName);
794 }
795
796 /* Even if DsnName invalid(in case of prompt) - we should not have problem */
797 DsnExists= MADB_DSN_Exists(DsnName);
798
799 SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &Environment);
800 SQLSetEnvAttr(Environment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
801
802 switch (fRequest)
803 {
804 case ODBC_ADD_DSN:
805 if (DsnExists)
806 {
807 if (hwndParent)
808 {
809 if (MessageBox(hwndParent, "Data source name already exists, do you want to replace it?",
810 "Question", MB_ICONQUESTION | MB_YESNO) != IDYES)
811 {
812 return FALSE;
813 }
814 }
815 }
816
817 MADB_DSN_SetDefaults(Dsn);
818 MADB_ParseConnString(Dsn, (char *)lpszAttributes, SQL_NTS, Delimiter);
819
820 /* Need to set driver after connstring parsing, and before saving */
821 if (lpszDriver)
822 {
823 Dsn->Driver= _strdup(lpszDriver);
824 }
825
826 if (SQL_SUCCEEDED(TestDSN(Dsn, NULL)))
827 {
828 return MADB_SaveDSN(Dsn);
829 }
830 else if (hwndParent == NULL)
831 {
832 return FALSE;
833 }
834
835 break;
836
837 case ODBC_CONFIG_DSN:
838
839 /* i.e. not a prompt */
840 if (Dsn->isPrompt == MAODBC_CONFIG && Dsn->SaveFile == NULL)
841 {
842 if (!DsnExists)
843 {
844 if (hwndParent != NULL)
845 {
846 MessageBox(0, "Data source name not found", "Error", MB_ICONERROR | MB_OK);
847 }
848 return FALSE;
849 }
850 else if (!MADB_ReadConnString(Dsn, (char *)lpszAttributes, SQL_NTS, Delimiter))
851 {
852 SQLPostInstallerError(ODBC_ERROR_INVALID_DSN, Dsn->ErrorMsg);
853 return FALSE;
854 }
855
856 if (hwndParent == NULL)
857 {
858 if (SQL_SUCCEEDED(TestDSN(Dsn, NULL)))
859 {
860 return MADB_SaveDSN(Dsn);
861 }
862 else if (hwndParent == NULL)
863 {
864 return FALSE;
865 }
866 }
867 }
868 }
869
870 InitCommonControls();
871
872 EffectiveDisabledPages= DisabledPages[Dsn->isPrompt];
873 EffectiveDisabledControls= DisabledControls[Dsn->isPrompt];
874
875 if (fRequest == ODBC_ADD_DSN && Dsn->isPrompt == MAODBC_CONFIG && Dsn->DSNName != NULL)
876 {
877 EffectiveDisabledControls= PromptDisabledControls;
878 }
879
880 notCanceled= TRUE;
881 hwndMain= CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc, 0);
882 SetWindowLongPtr(hwndMain, DWLP_USER, (LONG_PTR)Dsn);
883
884 /* Setting first not disabled page */
885 CurrentPage= -1;
886 SetPage(hwndMain, 1);
887
888 SetDialogFields();
889 CenterWindow(hwndMain);
890 ShowWindow(hwndMain, SW_SHOW);
891
892 while((ret = GetMessage(&msg, 0, 0, 0)) != 0) {
893 if(ret == -1)
894 break;
895
896 if(!IsDialogMessage(hwndTab[CurrentPage], &msg)) {
897 TranslateMessage(&msg);
898 DispatchMessage(&msg);
899 }
900 }
901
902 SQLFreeHandle(SQL_HANDLE_ENV, Environment);
903
904 if (notCanceled && fRequest == ODBC_CONFIG_DSN && DsnName != NULL && strcmp(DsnName, Dsn->DSNName) != 0)
905 {
906 SQLRemoveDSNFromIni(DsnName);
907 }
908
909 return notCanceled;
910 }
911
912
913 BOOL INSTAPI ConfigDSN(
914 HWND hwndParent,
915 WORD fRequest,
916 LPCSTR lpszDriver,
917 LPCSTR lpszAttributes)
918 {
919 MADB_Dsn Dsn;
920 if (!hwndParent && fRequest != ODBC_REMOVE_DSN)
921 {
922 /*
923 SQLPostInstallerError(ODBC_ERROR_INVALID_HWND, "Invalid Window Handle (NULL)");
924 return FALSE; */
925 }
926
927 switch (fRequest) {
928 case ODBC_ADD_DSN:
929 case ODBC_CONFIG_DSN:
930 memset(&Dsn, 0, sizeof(MADB_Dsn));
931 return DSNDialog(hwndParent, fRequest, lpszDriver, lpszAttributes, &Dsn);
932 case ODBC_REMOVE_DSN:
933 {
934 char *Val= strchr((char *)lpszAttributes, '=');
935 if (Val)
936 {
937 ++Val;
938 return SQLRemoveDSNFromIni(Val);
939 }
940 }
941 default:
942 return FALSE;
943 }
944 }
945
946 BOOL __stdcall DSNPrompt(HWND hwnd, MADB_Dsn *Dsn)
947 {
948 return DSNDialog(hwnd, ODBC_CONFIG_DSN, NULL, NULL, Dsn);
949 }
0 // Microsoft Visual C++ generated resource script.
1 //
2 #include "resource.h"
3
4 #define APSTUDIO_READONLY_SYMBOLS
5 /////////////////////////////////////////////////////////////////////////////
6 //
7 // Generated from the TEXTINCLUDE 2 resource.
8 //
9 #include "WinResrc.h"
10
11 #ifndef IDC_STATIC
12 # define IDC_STATIC (-1)
13 #endif
14
15 /////////////////////////////////////////////////////////////////////////////
16 #undef APSTUDIO_READONLY_SYMBOLS
17
18 /////////////////////////////////////////////////////////////////////////////
19 // German (Germany) resources
20
21 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
22 LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
23
24 #ifdef APSTUDIO_INVOKED
25 /////////////////////////////////////////////////////////////////////////////
26 //
27 // TEXTINCLUDE
28 //
29
30 1 TEXTINCLUDE
31 BEGIN
32 "resource.h\0"
33 END
34
35 2 TEXTINCLUDE
36 BEGIN
37 "#include ""afxres.h""\r\n"
38 "\0"
39 END
40
41 3 TEXTINCLUDE
42 BEGIN
43 "\r\n"
44 "\0"
45 END
46
47 #endif // APSTUDIO_INVOKED
48
49
50 /////////////////////////////////////////////////////////////////////////////
51 //
52 // Dialog
53 //
54
55 IDD_DIALOG1 DIALOGEX 0, 0, 385, 173
56 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
57 CAPTION "Create a new Data Source to MariaDB"
58 FONT 8, "MS Shell Dlg", 400, 0, 0x1
59 BEGIN
60 CONTROL 106,IDC_STATIC,"Static",SS_BITMAP,0,0,80,170
61 END
62
63 Page_0 DIALOGEX 0, 0, 299, 182
64 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU | WS_TABSTOP
65 FONT 8, "MS Shell Dlg", 400, 0, 0x1
66 BEGIN
67 LTEXT "Welcome to the MariaDB ODBC Data Source Wizard!",IDC_STATIC,7,7,287,25,0,WS_EX_TRANSPARENT
68 LTEXT "This wizard will help you to create an ODBC data source that you can use to connect to a MariaDB server.",IDC_STATIC,7,33,287,21,0,WS_EX_TRANSPARENT
69 LTEXT "What name do you want to use to refer to your data source ?",IDC_STATIC,7,60,287,12,0,WS_EX_TRANSPARENT
70 LTEXT "Name:",IDC_STATIC,44,78,22,8,0,WS_EX_TRANSPARENT
71 EDITTEXT txtDsnName,73,77,169,14,ES_AUTOHSCROLL | WS_GROUP
72 LTEXT "How do you want to describe the data source ?",IDC_STATIC,7,101,287,12,0,WS_EX_TRANSPARENT
73 LTEXT "Description:",IDC_STATIC,27,117,39,8,0,WS_EX_TRANSPARENT
74 EDITTEXT txtDSNDescription,73,116,169,14,ES_AUTOHSCROLL
75 PUSHBUTTON "< Previous",PB_PREV,50,149,50,14,WS_DISABLED
76 PUSHBUTTON "Next >",PB_NEXT,104,149,50,14
77 PUSHBUTTON "Cancel",IDCANCEL,178,149,50,14
78 PUSHBUTTON "Help",IDCANCEL4,236,149,50,14
79 EDITTEXT txtDriver,233,7,53,15,ES_AUTOHSCROLL | NOT WS_VISIBLE
80 END
81
82 Tab_Cursor DIALOGEX 0, 0, 256, 172
83 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
84 FONT 8, "MS Shell Dlg", 400, 0, 0x1
85 BEGIN
86 CONTROL "Don't cache results of forward only cursors",IDC_CHECK3,
87 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,40,153,10
88 CONTROL "Force use of forward only cursors",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,55,124,10
89 CONTROL "Prefetch rows",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,70,61,10
90 CONTROL "Pad Char to fulllength with SPACE",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,113,124,10
91 CONTROL "Return SQL_NULL_DATA for zero date",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,129,139,10
92 END
93
94 Tab_Connection DIALOGEX 0, 0, 256, 172
95 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
96 FONT 8, "MS Shell Dlg", 400, 0, 0x1
97 BEGIN
98 CONTROL "Allow big result sets",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,78,79,10,WS_EX_TRANSPARENT
99 END
100
101 Page_1 DIALOGEX 0, 0, 299, 182
102 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
103 FONT 8, "MS Shell Dlg", 400, 0, 0x1
104 BEGIN
105 LTEXT "How do you want to connect to MariaDB",IDC_STATIC,9,7,130,10,0,WS_EX_TRANSPARENT
106 LTEXT "Server Name:",lblServerName,86,21,49,11,0,WS_EX_TRANSPARENT | WS_EX_RIGHT
107 LTEXT "Please specify a user name and password to connect to MariaDB",IDC_STATIC,9,54,207,8,0,WS_EX_TRANSPARENT
108 LTEXT "Please specify a user name and password to connect to MariaDB",IDC_STATIC,9,105,207,8,0,WS_EX_TRANSPARENT
109 LTEXT "User name:",IDC_STATIC,26,70,38,8,0,WS_EX_TRANSPARENT | WS_EX_RIGHT
110 LTEXT "Password:",IDC_STATIC,30,88,34,8,0,WS_EX_TRANSPARENT | WS_EX_RIGHT
111 LTEXT "Database:",IDC_STATIC,20,121,34,8,0,WS_EX_TRANSPARENT | WS_EX_RIGHT
112 CONTROL "TCP/IP",rbTCP,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,21,38,10,WS_EX_TRANSPARENT
113 CONTROL "Named Pipe",rbPipe,"Button",BS_AUTORADIOBUTTON,7,33,53,10,WS_EX_TRANSPARENT
114 EDITTEXT txtServerName,139,18,141,14,ES_AUTOHSCROLL
115 EDITTEXT txtPort,140,34,40,14,ES_AUTOHSCROLL
116 LTEXT "Port:",lblPort,86,35,49,11,0,WS_EX_TRANSPARENT | WS_EX_RIGHT
117 EDITTEXT txtUserName,71,68,141,14,ES_AUTOHSCROLL
118 EDITTEXT txtPassword,71,86,142,14,ES_PASSWORD | ES_AUTOHSCROLL
119 PUSHBUTTON "&Test DSN",pbTestDSN,223,86,50,14
120 COMBOBOX cbDatabase,71,119,93,80,CBS_DROPDOWN | CBS_AUTOHSCROLL | CBS_SORT | WS_VSCROLL | WS_TABSTOP
121 PUSHBUTTON "< Previous",PB_PREV,50,149,50,14
122 PUSHBUTTON "Next >",PB_NEXT,104,149,50,14
123 PUSHBUTTON "Cancel",IDCANCEL,178,149,50,14
124 PUSHBUTTON "Help",IDCANCEL4,236,149,50,14
125 END
126
127 Page_2 DIALOGEX 0, 0, 299, 182
128 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
129 FONT 8, "MS Shell Dlg", 400, 0, 0x1
130 BEGIN
131 LTEXT "Do you want tio send initial statement(s) after establishing connection to MariaDB?",IDC_STATIC,7,7,264,8,0,WS_EX_TRANSPARENT
132 EDITTEXT txtInitCmd,74,30,197,39,ES_MULTILINE | ES_AUTOHSCROLL | WS_VSCROLL
133 LTEXT "Statement(s):",IDC_STATIC,20,32,46,8,0,WS_EX_TRANSPARENT
134 RTEXT "Connection timeout in sec:",IDC_STATIC,17,77,86,8,0,WS_EX_TRANSPARENT
135 EDITTEXT txtConnectionTimeOut,111,75,40,14,ES_AUTOHSCROLL
136 CONTROL "Enable automatic &reconnect",ckReconnect,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,94,107,10,WS_EX_TRANSPARENT
137 CONTROL "Don't prompt when connecting",ckConnectPrompt,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,110,113,10,WS_EX_TRANSPARENT
138 CONTROL "Use compression",ckCompressed,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,94,107,10,WS_EX_TRANSPARENT
139 CONTROL "Read odbc section from my.cnf",ckUseMycnf,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,163,110,198,10,WS_EX_TRANSPARENT
140 PUSHBUTTON "Cancel",IDCANCEL,178,149,50,14
141 PUSHBUTTON "Next >",PB_NEXT,104,149,50,14
142 PUSHBUTTON "< Previous",PB_PREV,50,149,50,14,WS_DISABLED
143 PUSHBUTTON "Help",IDCANCEL4,236,149,50,14
144 COMBOBOX cbCharset,113,127,160,80,CBS_DROPDOWN | CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
145 RTEXT "Connection Character Set:",IDC_STATIC,7,130,96,8,0,WS_EX_TRANSPARENT
146 END
147
148 Page_3 DIALOGEX 0, 0, 299, 182
149 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
150 FONT 8, "MS Shell Dlg", 400, 0, 0x1
151 BEGIN
152 GROUPBOX "Miscellanous Options",IDC_STATIC,7,7,277,124,0,WS_EX_TRANSPARENT
153 CONTROL "Ignore schema in column specification",ckIgnoreSchema,
154 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,25,136,10,WS_EX_TRANSPARENT
155 CONTROL "Allow multiple statements",ckMultiStmt,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,39,97,10,WS_EX_TRANSPARENT
156 LTEXT "Plugins Directory",IDC_STATIC,15,53,56,8,0,WS_EX_TRANSPARENT
157 EDITTEXT txtPluginDir,72,53,110,10,ES_AUTOHSCROLL
158 PUSHBUTTON "Browse",pbPlugindirBrowse,183,51,30,14
159 // CONTROL "Disable catalog support",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,39,91,10,WS_EX_TRANSPARENT
160 // CONTROL "Ignore space after function names",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,53,127,10,WS_EX_TRANSPARENT
161 PUSHBUTTON "Cancel",IDCANCEL,178,149,50,14
162 PUSHBUTTON "Next >",PB_NEXT,104,149,50,14
163 PUSHBUTTON "< Previous",PB_PREV,50,149,50,14,WS_DISABLED
164 PUSHBUTTON "Help",IDCANCEL4,236,149,50,14
165 END
166
167 Page_4 DIALOGEX 0, 0, 299, 182
168 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
169 FONT 8, "MS Shell Dlg", 400, 0, 0x1
170 BEGIN
171 GROUPBOX "SSL Settings",IDC_STATIC,7,7,277,124,0,WS_EX_TRANSPARENT
172
173 LTEXT "Key",IDC_STATIC,15,20,56,8,0,WS_EX_TRANSPARENT
174 EDITTEXT txtSslKey,84,20,110,10,ES_AUTOHSCROLL
175 PUSHBUTTON "Browse",pbKeyBrowse,195,18,30,14
176
177 LTEXT "Certificate",IDC_STATIC,15,34,56,8,0,WS_EX_TRANSPARENT
178 EDITTEXT txtSslCert,84,34,110,10,ES_AUTOHSCROLL
179 PUSHBUTTON "Browse",pbCertBrowse,195,32,30,14
180
181 LTEXT "Certificate Authority",IDC_STATIC,15,48,68,8,0,WS_EX_TRANSPARENT
182 EDITTEXT txtSslCertAuth,84,48,110,10,ES_AUTOHSCROLL
183 PUSHBUTTON "Browse",pbCaCertBrowse,195,46,30,14
184
185 LTEXT "CA Path",IDC_STATIC,15,62,56,8,0,WS_EX_TRANSPARENT
186 EDITTEXT txtSslCaPath,84,62,110,10,ES_AUTOHSCROLL
187 PUSHBUTTON "Browse",pbCaPathBrowse,195,60,30,14
188
189 LTEXT "Cipher",IDC_STATIC,15,76,56,8,0,WS_EX_TRANSPARENT
190 EDITTEXT txtSslCipher,84,76,110,10,ES_AUTOHSCROLL
191
192 CONTROL "Verify Certificate",cbSslVerify,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,90,68,10,WS_EX_TRANSPARENT
193
194 CONTROL "Force TLS Use",cbForceTls,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,84,90,97,10,WS_EX_TRANSPARENT
195
196 LTEXT "Allowed TLS versions(Not checking any means that all are allowed)",IDC_STATIC,15,104,264,8,0,WS_EX_TRANSPARENT
197 CONTROL "v.1.1",cbTls11,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,115,30,10,WS_EX_TRANSPARENT
198 CONTROL "v.1.2",cbTls12,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,115,30,10,WS_EX_TRANSPARENT
199 CONTROL "v.1.3",cbTls13,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,75,115,30,10,WS_EX_TRANSPARENT
200
201 PUSHBUTTON "Cancel",IDCANCEL,178,149,50,14
202 PUSHBUTTON "Next >",PB_NEXT,104,149,50,14
203 PUSHBUTTON "< Previous",PB_PREV,50,149,50,14,WS_DISABLED
204 PUSHBUTTON "Help",IDCANCEL4,236,149,50,14
205 END
206
207 Page_5 DIALOGEX 0, 0, 299, 182
208 STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
209 FONT 8, "MS Shell Dlg", 400, 0, 0x1
210 BEGIN
211 PUSHBUTTON "Cancel",IDCANCEL,178,149,50,14
212 PUSHBUTTON "Next >",PB_NEXT,104,149,50,14
213 PUSHBUTTON "< Previous",PB_PREV,50,149,50,14,WS_DISABLED
214 PUSHBUTTON "Help",IDCANCEL4,236,149,50,14
215 GROUPBOX "Cursor/Results",IDC_STATIC,7,7,277,132,0,WS_EX_TRANSPARENT
216 CONTROL "Enable dynamic cursors",ckEnableDynamicCursor,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,19,91,10,WS_EX_TRANSPARENT
217 CONTROL "Disable driver provided cursor support",ckDisableDriverCursor,
218 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,33,138,10,WS_EX_TRANSPARENT
219 CONTROL "Debug",ckDebug,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,197,19,37,10,WS_EX_TRANSPARENT
220 CONTROL "Return matched rows instead of affected rows",ckReturnMatchedRows,
221 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,48,165,10,WS_EX_TRANSPARENT
222 CONTROL "Enable SQL_AUTO_IS_NULL",ckEnableSQLAutoIsNull,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,63,105,10,WS_EX_TRANSPARENT
223 CONTROL "Allow spaces after function names",ckIgnoreSpace,
224 "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,78,124,10,WS_EX_TRANSPARENT
225 CONTROL "Return SQL_NULL_DATA for zero date",ckNullDate,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,93,139,10,WS_EX_TRANSPARENT
226 // CONTROL "Don't cache results of forward only cursors",ckDontCacheForwardCursor,
227 // "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,108,153,10,WS_EX_TRANSPARENT
228 // CONTROL "Force use of forward only cursors",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,123,124,10,WS_EX_TRANSPARENT
229 // CONTROL "Prefetch rows",ckPrefetchRows,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,197,33,61,10,WS_EX_TRANSPARENT
230 END
231
232
233 /////////////////////////////////////////////////////////////////////////////
234 //
235 // DESIGNINFO
236 //
237
238 #ifdef APSTUDIO_INVOKED
239 GUIDELINES DESIGNINFO
240 BEGIN
241 IDD_DIALOG1, DIALOG
242 BEGIN
243 LEFTMARGIN, 3
244 BOTTOMMARGIN, 172
245 END
246
247 Page_0, DIALOG
248 BEGIN
249 LEFTMARGIN, 7
250 RIGHTMARGIN, 294
251 TOPMARGIN, 7
252 BOTTOMMARGIN, 173
253 END
254
255 Tab_Cursor, DIALOG
256 BEGIN
257 LEFTMARGIN, 7
258 RIGHTMARGIN, 249
259 TOPMARGIN, 7
260 BOTTOMMARGIN, 163
261 END
262
263 Tab_Metadata, DIALOG
264 BEGIN
265 LEFTMARGIN, 7
266 RIGHTMARGIN, 249
267 TOPMARGIN, 7
268 BOTTOMMARGIN, 163
269 END
270
271 Tab_Connection, DIALOG
272 BEGIN
273 LEFTMARGIN, 7
274 RIGHTMARGIN, 249
275 TOPMARGIN, 7
276 BOTTOMMARGIN, 163
277 END
278
279 Page_1, DIALOG
280 BEGIN
281 LEFTMARGIN, 7
282 RIGHTMARGIN, 294
283 TOPMARGIN, 7
284 BOTTOMMARGIN, 173
285 END
286
287 Page_2, DIALOG
288 BEGIN
289 LEFTMARGIN, 7
290 RIGHTMARGIN, 294
291 TOPMARGIN, 7
292 BOTTOMMARGIN, 173
293 END
294
295 Page_3, DIALOG
296 BEGIN
297 LEFTMARGIN, 7
298 RIGHTMARGIN, 294
299 TOPMARGIN, 7
300 BOTTOMMARGIN, 173
301 END
302
303 Page_4, DIALOG
304 BEGIN
305 LEFTMARGIN, 7
306 RIGHTMARGIN, 294
307 TOPMARGIN, 7
308 BOTTOMMARGIN, 173
309 END
310
311 Page_5, DIALOG
312 BEGIN
313 LEFTMARGIN, 7
314 RIGHTMARGIN, 294
315 TOPMARGIN, 7
316 BOTTOMMARGIN, 173
317 END
318 END
319 #endif // APSTUDIO_INVOKED
320
321
322 /////////////////////////////////////////////////////////////////////////////
323 //
324 // Bitmap
325 //
326
327 IDB_BITMAP1 BITMAP "odbc_logo_left.bmp"
328 #endif // German (Germany) resources
329 /////////////////////////////////////////////////////////////////////////////
330
331
332
333 #ifndef APSTUDIO_INVOKED
334 /////////////////////////////////////////////////////////////////////////////
335 //
336 // Generated from the TEXTINCLUDE 3 resource.
337 //
338
339
340 /////////////////////////////////////////////////////////////////////////////
341 #endif // not APSTUDIO_INVOKED
342
343
Binary diff not shown
Binary diff not shown
0 /************************************************************************************
1 Copyright (C) 2013 SkySQL AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 #include <windows.h>
20 #include <stdio.h>
21 #include <odbcinst.h>
22
23 typedef BOOL (*DSNDialog)(HWND hwndParent,
24 WORD fRequest,
25 LPCSTR lpszDriver,
26 LPCSTR lpszAttributes);
27
28 int main()
29 {
30 HMODULE hmod= NULL;
31 BOOL ret;
32 DSNDialog DsnFunc= NULL;
33 HWND hWnd;
34 DWORD dwProcID= GetCurrentProcessId();
35
36 hWnd= GetConsoleWindow();
37 if (hWnd == NULL)
38 {
39 hWnd= GetTopWindow(GetDesktopWindow());
40 while (hWnd)
41 {
42 DWORD dwWndProcID = 0;
43 GetWindowThreadProcessId(hWnd, &dwWndProcID);
44 if (dwWndProcID == dwProcID)
45 break;
46 hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
47 }
48 }
49
50 if ((hmod= LoadLibrary("maodbcs.dll")))
51 {
52 if (DsnFunc= (DSNDialog)GetProcAddress(hmod, "ConfigDSN"))
53 {
54 ret= DsnFunc(NULL, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=2\0\0");
55 printf("%s 1 Null hWnd and not enough info\n", ret ? "not ok" : "ok");
56
57 printf("# The dialog is supposed to show up now - please complete info for connection\n");
58 ret= DsnFunc(hWnd, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=2\0\0");
59
60 if (ret != FALSE)
61 {
62 printf("ok 2 hWnd and not enough info\n");
63 ret= DsnFunc(NULL, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=2\0\0");
64 printf("%s 3 Null hWnd trying to add existing dsn \n", ret ? "not ok" : "ok");
65 ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
66 printf("%s 4 Null hWnd trying to config with insufficient data \n", ret ? "not ok" : "ok");
67 printf("# The dialog asking if you want to overwrite existing DSN is supposed to show up. Please say 'No'. Otherwise please cancel config dialog\n");
68 ret= DsnFunc(hWnd, ODBC_ADD_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
69 printf("%s 5 Replace Prompt \n", ret ? "not ok" : "ok");
70 ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=inexistent_dsn\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
71 printf("%s 6 Null hWnd trying to config inexisting DSN\n", ret ? "not ok" : "ok");
72 ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=inexistent_dsn\0UID=garbage\0PWD=DoubleGarbage\0OPTIONS=2\0\0");
73 printf("%s 7 hWnd trying to config inexisting DSN\n", ret ? "not ok" : "ok");
74 ret= DsnFunc(NULL, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0OPTIONS=0\0\0");
75 printf("%s 8 Null hWnd config with sufficient data \n", ret ? "ok" : "not ok");
76 printf("# Please make sure that in dialog Named pipe is selected, and all options are un-checked\n");
77 ret= DsnFunc(hWnd, ODBC_CONFIG_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0NamedPipe=1\0\0");
78 printf("%s 9 hWnd config with sufficient data \n", ret ? "ok" : "not ok");
79 }
80 else
81 {
82 printf("not ok 2 hWnd and not enough info\n");
83 printf("skip 3\n");
84 printf("skip 4\n");
85 printf("skip 5\n");
86 printf("skip 6\n");
87 printf("skip 7\n");
88 printf("skip 8\n");
89 printf("skip 9\n");
90 }
91
92 ret= DsnFunc(hWnd, ODBC_REMOVE_DSN, getenv("TEST_DRIVER"), "DSN=dsn_test\0\0");
93 printf("%s 10 removing dsn\n", ret ? "ok" : "not ok");
94 }
95 FreeLibrary(hmod);
96 }
97
98 return 1;
99 }
0 /************************************************************************************
1 Copyright (C) 2017,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 /* Code allowing to deploy MariaDB bulk operation functionality.
20 * i.e. adapting ODBC param arrays to MariaDB arrays */
21
22 #include <ma_odbc.h>
23
24 #define MAODBC_DATTIME_AS_PTR_ARR 1
25
26 static BOOL CanUseStructArrForDatetime(MADB_Stmt *Stmt)
27 {
28 #ifdef MAODBC_DATTIME_AS_PTR_ARR
29 return FALSE;
30 #endif
31 return TRUE;
32 }
33 char MADB_MapIndicatorValue(SQLLEN OdbcInd)
34 {
35 switch (OdbcInd)
36 {
37 case SQL_NTS: return STMT_INDICATOR_NTS;
38 case SQL_COLUMN_IGNORE: return STMT_INDICATOR_IGNORE;
39 case SQL_NULL_DATA: return STMT_INDICATOR_NULL;
40 case SQL_PARAM_IGNORE: return STMT_INDICATOR_IGNORE_ROW;
41 /*STMT_INDICATOR_DEFAULT*/
42 }
43 return '\0';
44 }
45
46
47 BOOL MADB_AppBufferCanBeUsed(SQLSMALLINT CType, SQLSMALLINT SqlType)
48 {
49 switch (CType)
50 {
51 case CHAR_BINARY_TYPES:
52 /*if (SqlType != SQL_BIT)
53 {
54 break;
55 }*/
56 case WCHAR_TYPES:
57 case SQL_C_NUMERIC:
58 case DATETIME_TYPES:
59
60 return FALSE;
61 }
62 return TRUE;
63 }
64
65
66 void MADB_CleanBulkOperData(MADB_Stmt *Stmt, unsigned int ParamOffset)
67 {
68 if (MADB_DOING_BULK_OPER(Stmt))
69 {
70 MADB_DescRecord *CRec;
71 void *DataPtr= NULL;
72 MYSQL_BIND *MaBind= NULL;
73 int i;
74
75 for (i= ParamOffset; i < MADB_STMT_PARAM_COUNT(Stmt); ++i)
76 {
77 if ((CRec= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ)) != NULL)
78 {
79 MaBind= &Stmt->params[i - ParamOffset];
80 DataPtr= GetBindOffset(Stmt->Apd, CRec, CRec->DataPtr, 0, CRec->OctetLength);
81
82 if (MaBind->buffer != DataPtr)
83 {
84 switch (CRec->ConciseType)
85 {
86 case DATETIME_TYPES:
87 if (CanUseStructArrForDatetime(Stmt) == FALSE)
88 {
89 MADB_FREE(MaBind->buffer);
90 break;
91 }
92 /* Otherwise falling through and do the same as for others */
93 case SQL_C_WCHAR:
94 case SQL_C_NUMERIC:
95 {
96 unsigned int i;
97 for (i= 0; i < Stmt->Bulk.ArraySize; ++i)
98 {
99 MADB_FREE(((char**)MaBind->buffer)[i]);
100 }
101 }
102 /* falling through */
103 default:
104 MADB_FREE(MaBind->buffer);
105 }
106 }
107
108 MADB_FREE(MaBind->length);
109
110 MADB_FREE(MaBind->u.indicator);
111 }
112 }
113 Stmt->Bulk.ArraySize= 0;
114 Stmt->Bulk.HasRowsToSkip= 0;
115 }
116 }
117
118
119 SQLRETURN MADB_InitIndicatorArray(MADB_Stmt *Stmt, MYSQL_BIND *MaBind, char InitValue)
120 {
121 MaBind->u.indicator= MADB_ALLOC(Stmt->Bulk.ArraySize);
122
123 if (MaBind->u.indicator == NULL)
124 {
125 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
126 }
127 memset(MaBind->u.indicator, InitValue, Stmt->Bulk.ArraySize);
128
129 return SQL_SUCCESS;
130 }
131
132
133 SQLRETURN MADB_SetBulkOperLengthArr(MADB_Stmt *Stmt, MADB_DescRecord *CRec, SQLLEN *OctetLengthPtr, SQLLEN *IndicatorPtr,
134 void *DataPtr, MYSQL_BIND *MaBind, BOOL VariableLengthMadbType)
135 {
136 /* Leaving it so far here commented, but it comlicates things w/out much gains */
137 /*if (sizeof(SQLLEN) == sizeof(long) && MADB_AppBufferCanBeUsed())
138 {
139 if (OctetLengthPtr)
140 {
141 MaBind->length= OctetLengthPtr;
142 }
143 }
144 else
145 {*/
146 unsigned int row;
147
148 if (VariableLengthMadbType)
149 {
150 MaBind->length= MADB_REALLOC(MaBind->length, Stmt->Bulk.ArraySize*sizeof(long));
151 if (MaBind->length == NULL)
152 {
153 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
154 }
155 }
156
157 for (row= 0; row < Stmt->Apd->Header.ArraySize; ++row, DataPtr= (char*)DataPtr + CRec->OctetLength)
158 {
159 if (Stmt->Apd->Header.ArrayStatusPtr != NULL && Stmt->Apd->Header.ArrayStatusPtr[row] == SQL_PARAM_IGNORE)
160 {
161 Stmt->Bulk.HasRowsToSkip= 1;
162 continue;
163 }
164
165 if ((OctetLengthPtr != NULL && OctetLengthPtr[row] == SQL_NULL_DATA)
166 || (IndicatorPtr != NULL && IndicatorPtr[row] != SQL_NULL_DATA))
167 {
168 RETURN_ERROR_OR_CONTINUE(MADB_SetIndicatorValue(Stmt, MaBind, row, SQL_NULL_DATA));
169 continue;
170 }
171 if ((OctetLengthPtr != NULL && OctetLengthPtr[row] == SQL_COLUMN_IGNORE)
172 || (IndicatorPtr != NULL && IndicatorPtr[row] != SQL_COLUMN_IGNORE))
173 {
174 RETURN_ERROR_OR_CONTINUE(MADB_SetIndicatorValue(Stmt, MaBind, row, SQL_COLUMN_IGNORE));
175 continue;
176 }
177
178 if (VariableLengthMadbType)
179 {
180 MaBind->length[row]= (unsigned long)MADB_CalculateLength(Stmt, OctetLengthPtr != NULL ? &OctetLengthPtr[row] : NULL, CRec, DataPtr);
181 }
182 }
183
184 return SQL_SUCCESS;
185 }
186 /* {{{ MADB_InitBulkOperBuffers */
187 /* Allocating data and length arrays, if needed, and initing them in certain cases.
188 DataPtr should be ensured to be not NULL */
189 SQLRETURN MADB_InitBulkOperBuffers(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void *DataPtr, SQLLEN *OctetLengthPtr,
190 SQLLEN *IndicatorPtr, SQLSMALLINT SqlType, MYSQL_BIND *MaBind)
191 {
192 BOOL VariableLengthMadbType= TRUE;
193
194 MaBind->buffer_length= 0;
195 MaBind->buffer_type= MADB_GetMaDBTypeAndLength(CRec->ConciseType, &MaBind->is_unsigned, &MaBind->buffer_length);
196
197 /* For fixed length types MADB_GetMaDBTypeAndLength has set buffer_length */
198 if (MaBind->buffer_length != 0)
199 {
200 VariableLengthMadbType= FALSE;
201 }
202 switch (CRec->ConciseType)
203 {
204 case CHAR_BINARY_TYPES:
205 if (SqlType == SQL_BIT)
206 {
207 CRec->InternalBuffer= MADB_CALLOC(Stmt->Bulk.ArraySize);
208 MaBind->buffer_length= 1;
209 break;
210 }
211 case DATETIME_TYPES:
212 if (CanUseStructArrForDatetime(Stmt) == TRUE)
213 {
214 CRec->InternalBuffer= MADB_ALLOC(Stmt->Bulk.ArraySize*sizeof(MYSQL_TIME));
215 MaBind->buffer_length= sizeof(MYSQL_TIME);
216 break;
217 }
218 /* Otherwise falling thru and allocating array of pointers */
219 case WCHAR_TYPES:
220 case SQL_C_NUMERIC:
221 CRec->InternalBuffer= MADB_CALLOC(Stmt->Bulk.ArraySize*sizeof(char*));
222 MaBind->buffer_length= sizeof(char*);
223 break;
224 default:
225 MaBind->buffer= DataPtr;
226 if (MaBind->buffer_length == 0)
227 {
228 MaBind->buffer_length= sizeof(char*);
229 }
230 }
231
232 if (MaBind->buffer != DataPtr)
233 {
234 MaBind->buffer= CRec->InternalBuffer;
235 if (MaBind->buffer == NULL)
236 {
237 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
238 }
239 CRec->InternalBuffer= NULL; /* Need to reset this pointer, so the memory won't be freed (accidentally) */
240 }
241
242 return MADB_SetBulkOperLengthArr(Stmt, CRec, OctetLengthPtr, IndicatorPtr, DataPtr, MaBind, VariableLengthMadbType);
243 }
244 /* }}} */
245
246 /* {{{ MADB_SetIndicatorValue */
247 SQLRETURN MADB_SetIndicatorValue(MADB_Stmt *Stmt, MYSQL_BIND *MaBind, unsigned int row, SQLLEN OdbcIndicator)
248 {
249 if (MaBind->u.indicator == NULL)
250 {
251 RETURN_ERROR_OR_CONTINUE(MADB_InitIndicatorArray(Stmt, MaBind, STMT_INDICATOR_NONE));
252 }
253
254 MaBind->u.indicator[row]= MADB_MapIndicatorValue(OdbcIndicator);
255 return SQL_SUCCESS;
256 }
257 /* }}} */
258
259 /* {{{ MADB_ExecuteBulk */
260 /* Assuming that bulk insert can't go with DAE(and that unlikely ever changes). And that it has been checked before this call,
261 and we can't have DAE here */
262 SQLRETURN MADB_ExecuteBulk(MADB_Stmt *Stmt, unsigned int ParamOffset)
263 {
264 unsigned int i, IndIdx= -1;
265 unsigned long Dummy;
266
267 for (i= ParamOffset; i < ParamOffset + MADB_STMT_PARAM_COUNT(Stmt); ++i)
268 {
269 MADB_DescRecord *CRec, *SqlRec;
270 SQLLEN *IndicatorPtr= NULL;
271 SQLLEN *OctetLengthPtr= NULL;
272 void *DataPtr= NULL;
273 MYSQL_BIND *MaBind= &Stmt->params[i - ParamOffset];
274 SQLULEN row, Start= Stmt->ArrayOffset;
275
276 if ((CRec= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ)) &&
277 (SqlRec= MADB_DescGetInternalRecord(Stmt->Ipd, i, MADB_DESC_READ)))
278 {
279 /* check if parameter was bound */
280 if (!CRec->inUse)
281 {
282 return MADB_SetError(&Stmt->Error, MADB_ERR_07002, NULL, 0);
283 }
284
285 if (MADB_ConversionSupported(CRec, SqlRec) == FALSE)
286 {
287 return MADB_SetError(&Stmt->Error, MADB_ERR_07006, NULL, 0);
288 }
289
290 MaBind->length= NULL;
291 IndicatorPtr= (SQLLEN *)GetBindOffset(Stmt->Apd, CRec, CRec->IndicatorPtr, 0, sizeof(SQLLEN));
292 OctetLengthPtr= (SQLLEN *)GetBindOffset(Stmt->Apd, CRec, CRec->OctetLengthPtr, 0, sizeof(SQLLEN));
293 DataPtr= GetBindOffset(Stmt->Apd, CRec, CRec->DataPtr, 0, CRec->OctetLength);
294
295 /* If these are the same pointers, setting indicator to NULL to simplify things a bit */
296 if (IndicatorPtr == OctetLengthPtr)
297 {
298 IndicatorPtr= NULL;
299 }
300 /* Well, specs kinda say, that both values and lenghts arrays should be set(in instruction to param array operations)
301 But there is no error/sqlstate for the case if any of those pointers is not set. Thus we assume that is possible */
302 if (DataPtr == NULL)
303 {
304 /* Special case - DataPtr is not set, we treat it as all values are NULL. Setting indicators and moving on next param */
305 RETURN_ERROR_OR_CONTINUE(MADB_InitIndicatorArray(Stmt, MaBind, MADB_MapIndicatorValue(SQL_NULL_DATA)));
306 continue;
307 }
308
309 /* Sets Stmt->Bulk.HasRowsToSkip if needed, since it traverses and checks status array anyway */
310 RETURN_ERROR_OR_CONTINUE(MADB_InitBulkOperBuffers(Stmt, CRec, DataPtr, OctetLengthPtr, IndicatorPtr, SqlRec->ConciseType, MaBind));
311
312 if (MaBind->u.indicator != NULL && IndIdx == (unsigned int)-1)
313 {
314 IndIdx= i - ParamOffset;
315 }
316
317 /* Doing it on last parameter - just to do do this once, and to use already allocated indicator array.
318 Little stupid optimization. But it's actually even a bit simpler this way */
319 if (i == ParamOffset + MADB_STMT_PARAM_COUNT(Stmt) - 1 && Stmt->Bulk.HasRowsToSkip)
320 {
321 if (IndIdx == (unsigned int)-1)
322 {
323 IndIdx= 0;
324 }
325
326 for (row= Start; row < Start + Stmt->Apd->Header.ArraySize; ++row)
327 {
328 if (Stmt->Apd->Header.ArrayStatusPtr[row] == SQL_PARAM_IGNORE)
329 {
330 MADB_SetIndicatorValue(Stmt, &Stmt->params[IndIdx], (unsigned int)row, SQL_PARAM_IGNORE);
331 }
332 }
333 }
334
335 if (MADB_AppBufferCanBeUsed(CRec->ConciseType, SqlRec->ConciseType))
336 {
337 /* Everything has been done for such column already */
338 continue;
339 }
340
341 /* We either have skipped rows or need to convert parameter values/convert array */
342 for (row= Start; row < Start + Stmt->Apd->Header.ArraySize; ++row, DataPtr= (char*)DataPtr + CRec->OctetLength)
343 {
344 void *Buffer= (char*)MaBind->buffer + row*MaBind->buffer_length;
345 void **BufferPtr= (void**)Buffer; /* For the case when Buffer points to the pointer already */
346
347 if (Stmt->Apd->Header.ArrayStatusPtr != NULL && Stmt->Apd->Header.ArrayStatusPtr[row] == SQL_PARAM_IGNORE)
348 {
349 continue;
350 }
351 if (MaBind->u.indicator && MaBind->u.indicator[row] > STMT_INDICATOR_NONE)
352 {
353 continue;
354 }
355
356 switch (CRec->ConciseType)
357 {
358 case SQL_C_CHAR:
359 if (SqlRec->ConciseType != SQL_BIT)
360 {
361 break;
362 }
363 case DATETIME_TYPES:
364 if (CanUseStructArrForDatetime(Stmt))
365 {
366 BufferPtr= &Buffer;
367 }
368 }
369
370 /* Need &Dummy here as a length ptr, since NULL is not good here.
371 It would make MADB_ConvertC2Sql to use MaBind->buffer_length by default */
372 if (!SQL_SUCCEEDED(MADB_ConvertC2Sql(Stmt, CRec, DataPtr, MaBind->length != NULL ? MaBind->length[row] : 0,
373 SqlRec, MaBind, BufferPtr, MaBind->length != NULL ? MaBind->length + row : &Dummy)))
374 {
375 /* Perhaps it's better to move to Clean function */
376 CRec->InternalBuffer= NULL;
377 return Stmt->Error.ReturnValue;
378 }
379 CRec->InternalBuffer= NULL;
380 }
381 }
382 }
383
384 return MADB_DoExecute(Stmt, FALSE);
385 }
386 /* }}} */
0 /************************************************************************************
1 Copyright (C) 2017,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 /* Code allowing to deploy MariaDB bulk operation functionality.
20 * i.e. adapting ODBC param arrays to MariaDB arrays */
21
22 #ifndef _ma_bulk_h
23 #define _ma_bulk_h
24
25 #define MADB_DOING_BULK_OPER(_stmt) ((_stmt)->Bulk.ArraySize > 1)
26
27 /* Couple defined to make "switch"s look at least shorter, if not nicer */
28 #define CHAR_BINARY_TYPES SQL_C_CHAR:\
29 case SQL_C_BINARY:\
30 case SQL_LONGVARBINARY:\
31 case SQL_VARBINARY:\
32 case SQL_VARCHAR:\
33 case SQL_LONGVARCHAR
34
35 #define WCHAR_TYPES SQL_C_WCHAR:\
36 case SQL_WVARCHAR:\
37 case SQL_WLONGVARCHAR
38
39 #define DATETIME_TYPES SQL_C_TIMESTAMP:\
40 case SQL_TYPE_TIMESTAMP:\
41 case SQL_C_TIME:\
42 case SQL_TYPE_TIME:\
43 case SQL_C_INTERVAL_HOUR_TO_MINUTE:\
44 case SQL_C_INTERVAL_HOUR_TO_SECOND:\
45 case SQL_C_DATE:\
46 case SQL_TYPE_DATE
47
48 char MADB_MapIndicatorValue(SQLLEN OdbcInd);
49 unsigned int MADB_UsedParamSets(MADB_Stmt *Stmt);
50 BOOL MADB_AppBufferCanBeUsed(SQLSMALLINT CType, SQLSMALLINT SqlType);
51 void MADB_CleanBulkOperData(MADB_Stmt *Stmt, unsigned int ParamOffset);
52 SQLRETURN MADB_InitBulkOperBuffers(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void *DataPtr, SQLLEN *OctetLengthPtr,
53 SQLLEN *IndicatorPtr, SQLSMALLINT SqlType, MYSQL_BIND *MaBind);
54 SQLRETURN MADB_SetIndicatorValue(MADB_Stmt *Stmt, MYSQL_BIND *MaBind, unsigned int row, SQLLEN OdbcIndicator);
55
56 SQLRETURN MADB_ExecuteBulk(MADB_Stmt *Stmt, unsigned int ParamOffset);
57
58 #endif
0 /************************************************************************************
1 Copyright (C) 2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 /* Common functions used in both connector and setup library.
20 * Moved to avoid redundant dependencies */
21
22 #include <ma_odbc.h>
23
24 static unsigned int ValidChar(const char *start, const char *end)
25 {
26 return 4;
27 }
28
29
30 static unsigned CharOctetLen(unsigned int utf32)
31 {
32 return 4;
33 }
34
35 MARIADB_CHARSET_INFO dummyUtf32le= {0, 1, "utf32le", "utf32_general_ci", "", 0, "UTF-32LE", 4, 4, CharOctetLen, ValidChar};
36
37 MARIADB_CHARSET_INFO* DmUnicodeCs= NULL;
38 Client_Charset utf8= {CP_UTF8, NULL};
39
40 /* {{{ ltrim */
41 char* ltrim(char *Str)
42 {
43 /* I am not sure using iswspace, and not isspace makes any sense here. But probably does not hurt either */
44 while (Str && iswspace(Str[0]))
45 ++Str;
46 return Str;
47 }
48 /* }}} */
49
50 /* {{{ trim */
51 char* trim(char *Str)
52 {
53 char *end;
54
55 Str= ltrim(Str);
56
57 end= Str + strlen(Str) - 1;
58 while (iswspace(*end))
59 *end--= 0;
60 return Str;
61 }
62 /* }}} */
63
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 struct st_madb_isolation MADB_IsolationLevel[] =
21 {
22 {SQL_TRANSACTION_REPEATABLE_READ, "REPEATABLE READ"},
23 {SQL_TRANSACTION_READ_COMMITTED, "READ COMMITTED"},
24 {SQL_TRANSACTION_READ_UNCOMMITTED, "READ UNCOMMITTED"},
25 {SQL_TRANSACTION_SERIALIZABLE, "SERIALIZABLE"},
26 {0, 0}
27 };
28
29 /* used by SQLGetFunctions */
30 SQLUSMALLINT MADB_supported_api[]=
31 {
32 SQL_API_SQLALLOCCONNECT,
33 SQL_API_SQLALLOCENV,
34 SQL_API_SQLALLOCHANDLE,
35 SQL_API_SQLALLOCSTMT,
36 SQL_API_SQLBINDCOL,
37 SQL_API_SQLBINDPARAM,
38 SQL_API_SQLCANCEL,
39 SQL_API_SQLCLOSECURSOR,
40 SQL_API_SQLCOLATTRIBUTE,
41 SQL_API_SQLCOLUMNS,
42 SQL_API_SQLCONNECT,
43 SQL_API_SQLCOPYDESC,
44 SQL_API_SQLDATASOURCES,
45 SQL_API_SQLDESCRIBECOL,
46 SQL_API_SQLDISCONNECT,
47 SQL_API_SQLENDTRAN,
48 SQL_API_SQLERROR,
49 SQL_API_SQLEXECDIRECT,
50 SQL_API_SQLEXECUTE,
51 SQL_API_SQLFETCH,
52 SQL_API_SQLFETCHSCROLL,
53 SQL_API_SQLFREECONNECT,
54 SQL_API_SQLFREEENV,
55 SQL_API_SQLFREEHANDLE,
56 SQL_API_SQLFREESTMT,
57 SQL_API_SQLGETCONNECTATTR,
58 SQL_API_SQLGETCONNECTOPTION,
59 SQL_API_SQLGETCURSORNAME,
60 SQL_API_SQLGETDATA,
61 SQL_API_SQLGETDESCFIELD,
62 SQL_API_SQLGETDESCREC,
63 SQL_API_SQLGETDIAGFIELD,
64 SQL_API_SQLGETDIAGREC,
65 SQL_API_SQLGETENVATTR,
66 SQL_API_SQLGETFUNCTIONS,
67 SQL_API_SQLGETINFO,
68 SQL_API_SQLGETSTMTATTR,
69 SQL_API_SQLGETSTMTOPTION,
70 SQL_API_SQLGETTYPEINFO,
71 SQL_API_SQLNUMRESULTCOLS,
72 SQL_API_SQLPARAMDATA,
73 SQL_API_SQLPREPARE,
74 SQL_API_SQLPUTDATA,
75 SQL_API_SQLROWCOUNT,
76 SQL_API_SQLSETCONNECTATTR,
77 SQL_API_SQLSETCONNECTOPTION,
78 SQL_API_SQLSETCURSORNAME,
79 SQL_API_SQLSETDESCFIELD,
80 SQL_API_SQLSETDESCREC,
81 SQL_API_SQLSETENVATTR,
82 SQL_API_SQLSETPARAM,
83 SQL_API_SQLSETSTMTATTR,
84 SQL_API_SQLSETSTMTOPTION,
85 SQL_API_SQLSPECIALCOLUMNS,
86 SQL_API_SQLSTATISTICS,
87 SQL_API_SQLTABLES,
88 SQL_API_SQLTRANSACT,
89 SQL_API_SQLBULKOPERATIONS,
90 SQL_API_SQLBINDPARAMETER,
91 SQL_API_SQLBROWSECONNECT,
92 SQL_API_SQLCOLATTRIBUTES,
93 SQL_API_SQLCOLUMNPRIVILEGES ,
94 SQL_API_SQLDESCRIBEPARAM,
95 SQL_API_SQLDRIVERCONNECT,
96 SQL_API_SQLDRIVERS,
97 SQL_API_SQLEXTENDEDFETCH,
98 SQL_API_SQLFOREIGNKEYS,
99 SQL_API_SQLMORERESULTS,
100 SQL_API_SQLNATIVESQL,
101 SQL_API_SQLNUMPARAMS,
102 SQL_API_SQLPARAMOPTIONS,
103 SQL_API_SQLPRIMARYKEYS,
104 SQL_API_SQLPROCEDURECOLUMNS,
105 SQL_API_SQLPROCEDURES,
106 SQL_API_SQLSETPOS,
107 SQL_API_SQLSETSCROLLOPTIONS,
108 SQL_API_SQLTABLES,
109 SQL_API_SQLTABLEPRIVILEGES
110
111 };
112
113
114 struct st_ma_connection_methods MADB_Dbc_Methods; /* declared at the end of file */
115
116
117 my_bool CheckConnection(MADB_Dbc *Dbc)
118 {
119 if (!Dbc->mariadb)
120 return FALSE;
121 if (mysql_get_socket(Dbc->mariadb) == MARIADB_INVALID_SOCKET)
122 {
123 /* Check if reconnect option was set */
124 if (DSN_OPTION(Dbc, MADB_OPT_FLAG_AUTO_RECONNECT))
125 {
126 if (!mysql_ping(Dbc->mariadb))
127 return TRUE;
128 }
129 return FALSE;
130 }
131 return TRUE;
132 }
133
134 /* {{{ MADB_DbcSetAttr */
135 SQLRETURN MADB_DbcSetAttr(MADB_Dbc *Dbc, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength, my_bool isWChar)
136 {
137 MADB_CLEAR_ERROR(&Dbc->Error);
138
139 if (!Dbc)
140 {
141 /* Todo: check */
142 if (Attribute != SQL_ATTR_TRACE ||
143 Attribute != SQL_ATTR_TRACEFILE)
144 return SQL_INVALID_HANDLE;
145 return SQL_SUCCESS;
146 }
147
148 switch(Attribute) {
149 case SQL_ATTR_ACCESS_MODE:
150 if ((SQLPOINTER)SQL_MODE_READ_WRITE != ValuePtr)
151 MADB_SetError(&Dbc->Error, MADB_ERR_01S02, NULL, 0);
152 Dbc->AccessMode= SQL_MODE_READ_WRITE;
153 break;
154 #if (ODBCVER >= 0x0351)
155 case SQL_ATTR_ANSI_APP:
156 if (ValuePtr != NULL)
157 {
158 Dbc->IsAnsi= 1;
159 Dbc->ConnOrSrcCharset= &SourceAnsiCs;
160 CopyClientCharset(&SourceAnsiCs, &Dbc->Charset);
161 }
162 else
163 {
164 Dbc->IsAnsi= 0;
165 }
166 break;
167 #endif
168 case SQL_ATTR_ASYNC_ENABLE:
169 if ((SQLPOINTER)SQL_ASYNC_ENABLE_OFF != ValuePtr)
170 MADB_SetError(&Dbc->Error, MADB_ERR_01S02, NULL, 0);
171 Dbc->AsyncEnable= SQL_ASYNC_ENABLE_OFF;
172 break;
173 case SQL_ATTR_AUTO_IPD:
174 /* read only */
175 MADB_SetError(&Dbc->Error, MADB_ERR_HY092, NULL, 0);
176 break;
177 case SQL_ATTR_AUTOCOMMIT:
178 {
179 SQLULEN ValidAttrs[]= {2, SQL_AUTOCOMMIT_ON, SQL_AUTOCOMMIT_OFF};
180 MADB_CHECK_ATTRIBUTE(Dbc, ValuePtr, ValidAttrs);
181 /* if a connection is open, try to apply setting to the connection */
182 if (Dbc->mariadb)
183 {
184 if (Dbc->EnlistInDtc) {
185 return MADB_SetError(&Dbc->Error, MADB_ERR_25000, NULL, 0);
186 }
187 if (mysql_autocommit(Dbc->mariadb, (my_bool)(size_t)ValuePtr))
188 {
189 return MADB_SetError(&Dbc->Error, MADB_ERR_HY001, mysql_error(Dbc->mariadb), mysql_errno(Dbc->mariadb));
190 }
191 }
192 Dbc->AutoCommit= (SQLUINTEGER)(SQLULEN)ValuePtr;
193 }
194 break;
195 case SQL_ATTR_CONNECTION_DEAD:
196 /* read only! */
197 return MADB_SetError(&Dbc->Error, MADB_ERR_HY092, NULL, 0);
198 case SQL_ATTR_CURRENT_CATALOG:
199 {
200 MADB_FREE(Dbc->CatalogName);
201 if (isWChar)
202 {
203 /* IsAnsi will be set before this, even if it is set before connection */
204 Dbc->CatalogName= MADB_ConvertFromWChar((SQLWCHAR *)ValuePtr, StringLength, NULL, Dbc->ConnOrSrcCharset, NULL);
205 }
206 else
207 Dbc->CatalogName= _strdup((char *)ValuePtr);
208
209 if (Dbc->mariadb &&
210 mysql_select_db(Dbc->mariadb, Dbc->CatalogName))
211 {
212 return MADB_SetError(&Dbc->Error, MADB_ERR_HY001, mysql_error(Dbc->mariadb), mysql_errno(Dbc->mariadb));
213 }
214 }
215 break;
216 case SQL_ATTR_LOGIN_TIMEOUT:
217 Dbc->LoginTimeout= (SQLUINTEGER)(SQLULEN)ValuePtr;
218 break;
219 case SQL_ATTR_METADATA_ID:
220 Dbc->MetadataId= (SQLUINTEGER)(SQLULEN)ValuePtr;
221 break;
222 case SQL_ATTR_ODBC_CURSORS:
223 {
224 SQLULEN ValidAttrs[]= {3, SQL_CUR_USE_IF_NEEDED, SQL_CUR_USE_ODBC, SQL_CUR_USE_DRIVER};
225 MADB_CHECK_ATTRIBUTE(Dbc, ValuePtr, ValidAttrs);
226 if ((SQLULEN)ValuePtr != SQL_CUR_USE_ODBC)
227 MADB_SetError(&Dbc->Error, MADB_ERR_01S02, NULL, 0);
228 Dbc->OdbcCursors= SQL_CUR_USE_ODBC;
229 }
230 break;
231 case SQL_ATTR_ENLIST_IN_DTC:
232 /* MS Distributed Transaction Coordinator not supported */
233 return MADB_SetError(&Dbc->Error, MADB_ERR_HYC00, NULL, 0);
234 case SQL_ATTR_PACKET_SIZE:
235 /* if connection was made, return HY001 */
236 if (Dbc->mariadb)
237 {
238 return MADB_SetError(&Dbc->Error, MADB_ERR_HY001, NULL, 0);
239 }
240 Dbc->PacketSize= (SQLUINTEGER)(SQLULEN)ValuePtr;
241 break;
242 case SQL_ATTR_QUIET_MODE:
243 Dbc->QuietMode= (HWND)ValuePtr;
244 break;
245 case SQL_ATTR_TRACE:
246 break;
247 case SQL_ATTR_TRACEFILE:
248 break;
249 case SQL_ATTR_TRANSLATE_LIB:
250 break;
251 case SQL_ATTR_TRANSLATE_OPTION:
252 break;
253 case SQL_ATTR_TXN_ISOLATION:
254 if (Dbc->mariadb)
255 {
256 my_bool ValidTx= FALSE;
257 unsigned int i;
258 for (i=0; i < 4; i++)
259 {
260 if (MADB_IsolationLevel[i].SqlIsolation == (SQLLEN)ValuePtr)
261 {
262 char StmtStr[128];
263 _snprintf(StmtStr, sizeof(StmtStr), "SET SESSION TRANSACTION ISOLATION LEVEL %s",
264 MADB_IsolationLevel[i].StrIsolation);
265 LOCK_MARIADB(Dbc);
266 if (mysql_query(Dbc->mariadb, StmtStr))
267 {
268 UNLOCK_MARIADB(Dbc);
269 return MADB_SetError(&Dbc->Error, MADB_ERR_HY001, mysql_error(Dbc->mariadb), mysql_errno(Dbc->mariadb));
270 }
271 UNLOCK_MARIADB(Dbc);
272 ValidTx= TRUE;
273 break;
274 }
275 }
276 if (!ValidTx)
277 {
278 return MADB_SetError(&Dbc->Error, MADB_ERR_HY024, NULL, 0);
279 }
280 }
281 Dbc->TxnIsolation= (SQLINTEGER)(SQLLEN)ValuePtr;
282 break;
283 default:
284 break;
285 }
286 return Dbc->Error.ReturnValue;
287 }
288 /* }}} */
289
290 /* {{{ MADB_DbcHetAttr */
291 SQLRETURN MADB_DbcGetAttr(MADB_Dbc *Dbc, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr, my_bool isWChar)
292 {
293 MADB_CLEAR_ERROR(&Dbc->Error);
294
295 if (!Dbc)
296 return SQL_INVALID_HANDLE;
297
298 if (!ValuePtr && Attribute != SQL_ATTR_CURRENT_CATALOG)
299 return SQL_SUCCESS;
300 if (Attribute == SQL_ATTR_CURRENT_CATALOG && !StringLengthPtr &&
301 (!ValuePtr || !BufferLength))
302 {
303 return MADB_SetError(&Dbc->Error, MADB_ERR_01004, NULL, 0);
304 }
305
306 switch(Attribute) {
307 case SQL_ATTR_ACCESS_MODE:
308 *(SQLUINTEGER *)ValuePtr= SQL_MODE_READ_WRITE;
309 break;
310 case SQL_ATTR_ASYNC_ENABLE:
311 *(SQLULEN *)ValuePtr= SQL_ASYNC_ENABLE_OFF;
312 break;
313 case SQL_ATTR_AUTO_IPD:
314 *(SQLUINTEGER *)ValuePtr= SQL_FALSE;
315 break;
316 case SQL_ATTR_AUTOCOMMIT:
317 *(SQLUINTEGER *)ValuePtr= Dbc->AutoCommit;
318 break;
319 case SQL_ATTR_CONNECTION_DEAD:
320 /* ping may fail if status isn't ready, so we need to check errors */
321 if (mysql_ping(Dbc->mariadb))
322 *(SQLUINTEGER *)ValuePtr= (mysql_errno(Dbc->mariadb) == CR_SERVER_GONE_ERROR ||
323 mysql_errno(Dbc->mariadb) == CR_SERVER_LOST) ? SQL_CD_TRUE : SQL_CD_FALSE;
324 else
325 *(SQLUINTEGER *)ValuePtr= SQL_CD_FALSE;
326 break;
327 case SQL_ATTR_CURRENT_CATALOG:
328 {
329 SQLSMALLINT StrLen;
330 SQLRETURN ret;
331
332 ret= MADB_Dbc_GetCurrentDB(Dbc, ValuePtr, BufferLength, &StrLen, isWChar);
333 /* if we weren't able to determine the current db, we will return the cached catalog name */
334 if (!SQL_SUCCEEDED(ret) && Dbc->CatalogName)
335 {
336 MADB_CLEAR_ERROR(&Dbc->Error);
337 StrLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : 0, ValuePtr, BufferLength,
338 Dbc->CatalogName, strlen(Dbc->CatalogName), &Dbc->Error);
339 ret= SQL_SUCCESS;
340 }
341 if (StringLengthPtr != NULL)
342 {
343 *StringLengthPtr= (SQLINTEGER)StrLen;
344 }
345 return ret;
346 }
347 case SQL_ATTR_LOGIN_TIMEOUT:
348 *(SQLUINTEGER *)ValuePtr= Dbc->LoginTimeout;
349 break;
350 case SQL_ATTR_CONNECTION_TIMEOUT:
351 *(SQLUINTEGER *)ValuePtr= 0;
352 break;
353 case SQL_ATTR_METADATA_ID:
354 *(SQLUINTEGER *)ValuePtr= Dbc->MetadataId;
355 case SQL_ATTR_ODBC_CURSORS:
356 *(SQLINTEGER *)ValuePtr= SQL_CUR_USE_ODBC;
357 break;
358 case SQL_ATTR_ENLIST_IN_DTC:
359 /* MS Distributed Transaction Coordinator not supported */
360 MADB_SetError(&Dbc->Error, MADB_ERR_HYC00, NULL, 0);
361 break;
362 case SQL_ATTR_PACKET_SIZE:
363 {
364 unsigned long packet_size= 0;
365 mysql_get_option(Dbc->mariadb, MYSQL_OPT_NET_BUFFER_LENGTH, &packet_size);
366 *(SQLINTEGER *)ValuePtr= (SQLINTEGER)packet_size;
367 }
368 break;
369 case SQL_ATTR_QUIET_MODE:
370 Dbc->QuietMode= (HWND)ValuePtr;
371 break;
372 case SQL_ATTR_TRACE:
373 break;
374 case SQL_ATTR_TRACEFILE:
375 break;
376 case SQL_ATTR_TRANSLATE_LIB:
377 break;
378 case SQL_ATTR_TRANSLATE_OPTION:
379 break;
380 case SQL_ATTR_TXN_ISOLATION:
381 /* TxnIsolation wasn't set before we retrieve it from open connection or
382 assume a default of REPETABLE_READ */
383 if (!Dbc->TxnIsolation)
384 {
385 *(SQLULEN *)ValuePtr= SQL_TRANSACTION_REPEATABLE_READ;
386 if (Dbc->mariadb)
387 {
388 MYSQL_RES *result;
389 MYSQL_ROW row;
390 const char *StmtString= "SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='TX_ISOLATION'";
391
392 LOCK_MARIADB(Dbc);
393 if (mysql_query(Dbc->mariadb, StmtString))
394 {
395 UNLOCK_MARIADB(Dbc);
396 MADB_SetNativeError(&Dbc->Error, SQL_HANDLE_DBC, Dbc->mariadb);
397 return Dbc->Error.ReturnValue;
398 }
399 result= mysql_store_result(Dbc->mariadb);
400 UNLOCK_MARIADB(Dbc);
401 if ((row = mysql_fetch_row(result)))
402 {
403 unsigned int i;
404 for (i=0; i < 4; i++)
405 if (!strcmp(row[0], MADB_IsolationLevel[i].StrIsolation))
406 {
407 *(SQLULEN *)ValuePtr= MADB_IsolationLevel[i].SqlIsolation;
408 break;
409 }
410 }
411 mysql_free_result(result);
412 }
413 }
414 else
415 *(SQLULEN *)ValuePtr= Dbc->TxnIsolation;
416 break;
417
418 default:
419 MADB_SetError(&Dbc->Error, MADB_ERR_HYC00, NULL, 0);
420 break;
421 }
422 return Dbc->Error.ReturnValue;
423 }
424 /* }}} */
425
426
427 /* {{{ MADB_DbcInit() */
428 MADB_Dbc *MADB_DbcInit(MADB_Env *Env)
429 {
430 MADB_Dbc *Connection= NULL;
431
432 MADB_CLEAR_ERROR(&Env->Error);
433
434 if (!(Connection = (MADB_Dbc *)MADB_CALLOC(sizeof(MADB_Dbc))))
435 goto cleanup;
436
437 Connection->AutoCommit= 4;
438 Connection->Environment= Env;
439 Connection->Methods= &MADB_Dbc_Methods;
440 //CopyClientCharset(&SourceAnsiCs, &Connection->Charset);
441 InitializeCriticalSection(&Connection->cs);
442 /* Not sure that critical section is really needed here - this init routine is called when
443 no one has the handle yet */
444 EnterCriticalSection(&Connection->Environment->cs);
445
446 /* Save connection in Environment list */
447 Connection->ListItem.data= (void *)Connection;
448 Connection->Environment->Dbcs= MADB_ListAdd(Connection->Environment->Dbcs, &Connection->ListItem);
449
450 LeaveCriticalSection(&Connection->Environment->cs);
451
452 MADB_PutErrorPrefix(NULL, &Connection->Error);
453
454 return Connection;
455 cleanup:
456 if (Connection)
457 free(Connection);
458 else
459 MADB_SetError(&Env->Error, MADB_ERR_HY001, NULL, 0);
460
461 return NULL;
462 }
463 /* }}} */
464
465 /* {{{ MADB_DbcFree() */
466 SQLRETURN MADB_DbcFree(MADB_Dbc *Connection)
467 {
468 MADB_Env *Env= NULL;
469
470 if (!Connection)
471 return SQL_ERROR;
472 MDBUG_C_PRINT(Connection, "%sMADB_DbcFree", "\t->");
473 MDBUG_C_DUMP(Connection, Connection, 0x);
474
475 Env= Connection->Environment;
476
477 /* TODO: If somebody uses connection it won't help if lock it here. At least it requires
478 more fingers movements
479 LOCK_MARIADB(Dbc);*/
480 if (Connection->mariadb)
481 {
482 mysql_close(Connection->mariadb);
483 Connection->mariadb= NULL;
484 }
485 /*UNLOCK_MARIADB(Dbc);*/
486
487 /* todo: delete all descriptors */
488
489 EnterCriticalSection(&Env->cs);
490 Connection->Environment->Dbcs= MADB_ListDelete(Connection->Environment->Dbcs, &Connection->ListItem);
491 LeaveCriticalSection(&Env->cs);
492
493 MADB_FREE(Connection->CatalogName);
494 CloseClientCharset(&Connection->Charset);
495 MADB_FREE(Connection->DataBase);
496 MADB_DSN_Free(Connection->Dsn);
497 DeleteCriticalSection(&Connection->cs);
498
499 free(Connection);
500 return SQL_SUCCESS;
501 }
502 /* }}} */
503
504 /* {{{ MADB_Dbc_GetCurrentDB */
505 SQLRETURN MADB_Dbc_GetCurrentDB(MADB_Dbc *Connection, SQLPOINTER CurrentDB, SQLINTEGER CurrentDBLength,
506 SQLSMALLINT *StringLengthPtr, my_bool isWChar)
507 {
508 MADB_Stmt *Stmt;
509 SQLRETURN ret;
510 SQLLEN Size;
511 char Buffer[65 * sizeof(SQLWCHAR)];
512
513 MADB_CLEAR_ERROR(&Connection->Error);
514 ret= MA_SQLAllocHandle(SQL_HANDLE_STMT, (SQLHANDLE) Connection, (SQLHANDLE*)&Stmt);
515 if (!SQL_SUCCEEDED(ret))
516 return ret;
517 if (!SQL_SUCCEEDED(Stmt->Methods->ExecDirect(Stmt, (char *)"SELECT IF(DATABASE() IS NOT NULL,DATABASE(),'null')", SQL_NTS)) ||
518 !SQL_SUCCEEDED(Stmt->Methods->Fetch(Stmt)))
519 {
520 MADB_CopyError(&Connection->Error, &Stmt->Error);
521 goto end;
522 }
523
524 ret= Stmt->Methods->GetData(Stmt, 1, SQL_CHAR, Buffer, 65, &Size, TRUE);
525
526 Size= (SQLSMALLINT)MADB_SetString(isWChar ? & Connection->Charset : 0,
527 (void *)CurrentDB, BUFFER_CHAR_LEN(CurrentDBLength, isWChar), Buffer,
528 SQL_NTS, &Connection->Error);
529 if (StringLengthPtr)
530 *StringLengthPtr= isWChar ? (SQLSMALLINT)Size * sizeof(SQLWCHAR) : (SQLSMALLINT)Size;
531
532 end:
533 MA_SQLFreeStmt(Stmt, SQL_DROP);
534 return Connection->Error.ReturnValue;
535 }
536 BOOL MADB_SqlMode(MADB_Dbc *Connection, enum enum_madb_sql_mode SqlMode)
537 {
538 switch (SqlMode)
539 {
540 case MADB_NO_BACKSLASH_ESCAPES:
541 return test(Connection->mariadb->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES);
542 case MADB_ANSI_QUOTES:
543 return test(Connection->mariadb->server_status & SERVER_STATUS_ANSI_QUOTES);
544 }
545 return FALSE;
546 }
547 /* }}} */
548
549 /* {{{ MADB_DbcEndTran */
550 SQLRETURN MADB_DbcEndTran(MADB_Dbc *Dbc, SQLSMALLINT CompletionType)
551 {
552 MADB_CLEAR_ERROR(&Dbc->Error);
553 if (!Dbc)
554 return SQL_INVALID_HANDLE;
555
556 LOCK_MARIADB(Dbc);
557 switch (CompletionType) {
558 case SQL_ROLLBACK:
559 if (Dbc->mariadb && mysql_rollback(Dbc->mariadb))
560 MADB_SetNativeError(&Dbc->Error, SQL_HANDLE_DBC, Dbc->mariadb);
561 break;
562 case SQL_COMMIT:
563 if (Dbc->mariadb && mysql_commit(Dbc->mariadb))
564 MADB_SetNativeError(&Dbc->Error, SQL_HANDLE_DBC, Dbc->mariadb);
565 break;
566 default:
567 MADB_SetError(&Dbc->Error, MADB_ERR_HY012, NULL, 0);
568 }
569 UNLOCK_MARIADB(Dbc);
570
571 return Dbc->Error.ReturnValue;
572 }
573 /* }}} */
574
575 /* {{{ MADB_Dbc_ConnectDB
576 Mind that this function is used for establishing connection from the setup lib
577 */
578 SQLRETURN MADB_DbcConnectDB(MADB_Dbc *Connection,
579 MADB_Dsn *Dsn)
580 {
581 char StmtStr[128];
582 unsigned ReportDataTruncation= 1;
583 unsigned int i;
584 unsigned long client_flags= 0L;
585 my_bool my_reconnect= 1;
586
587 if (!Connection || !Dsn)
588 return SQL_ERROR;
589
590 MADB_CLEAR_ERROR(&Connection->Error);
591
592 if (Connection->mariadb == NULL)
593 {
594 if (!(Connection->mariadb= mysql_init(NULL)))
595 {
596 MADB_SetError(&Connection->Error, MADB_ERR_HY001, NULL, 0);
597 goto end;
598 }
599 }
600
601 if( !MADB_IS_EMPTY(Dsn->ConnCPluginsDir))
602 {
603 mysql_optionsv(Connection->mariadb, MYSQL_PLUGIN_DIR, Dsn->ConnCPluginsDir);
604 }
605 else
606 {
607 MADB_SetDefaultPluginsDir(Connection);
608 }
609
610 if (Dsn->ReadMycnf != '\0')
611 {
612 mysql_optionsv(Connection->mariadb, MYSQL_READ_DEFAULT_GROUP, (void *)"odbc");
613 }
614 /* If a client character set was specified in DSN, we will always use it.
615 Otherwise for ANSI applications we will use the current character set,
616 for unicode connections we use utf8
617 */
618 {
619 const char* cs_name= NULL;
620
621 if (!MADB_IS_EMPTY(Dsn->CharacterSet))
622 {
623 cs_name= Dsn->CharacterSet;
624 }
625 else if (Connection->IsAnsi)
626 {
627 MARIADB_CHARSET_INFO *cs= mariadb_get_charset_by_name("auto");
628 cs_name= cs->csname;
629 }
630
631 if (InitClientCharset(&Connection->Charset, MADB_IS_EMPTY(cs_name) ? "utf8mb4" : cs_name))
632 {
633 /* Memory allocation error */
634 MADB_SetError(&Connection->Error, MADB_ERR_HY001, NULL, 0);
635 goto end;
636 }
637 if (iOdbc() && strcmp(Connection->Charset.cs_info->csname, "swe7") == 0)
638 {
639 MADB_SetError(&Connection->Error, MADB_ERR_HY001, "Charset SWE7 is not supported with iODBC", 0);
640 goto end;
641
642 }
643 if (!Connection->IsAnsi || iOdbc())
644 {
645 /* If application is not ansi, we should convert wchar into connection string */
646 Connection->ConnOrSrcCharset= &Connection->Charset;
647 }
648 }
649
650 /* todo: error handling */
651 mysql_optionsv(Connection->mariadb, MYSQL_SET_CHARSET_NAME, Connection->Charset.cs_info->csname);
652
653 if (Dsn->InitCommand && Dsn->InitCommand[0])
654 mysql_optionsv(Connection->mariadb, MYSQL_INIT_COMMAND, Dsn->InitCommand);
655
656 if (Dsn->ConnectionTimeout)
657 mysql_optionsv(Connection->mariadb, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&Dsn->ConnectionTimeout);
658
659 Connection->Options= Dsn->Options;
660
661 if (DSN_OPTION(Connection, MADB_OPT_FLAG_AUTO_RECONNECT))
662 mysql_optionsv(Connection->mariadb, MYSQL_OPT_RECONNECT, &my_reconnect);
663
664 if (Dsn->IsNamedPipe) /* DSN_OPTION(Connection, MADB_OPT_FLAG_NAMED_PIPE) */
665 mysql_optionsv(Connection->mariadb, MYSQL_OPT_NAMED_PIPE, (void *)Dsn->ServerName);
666
667 if (DSN_OPTION(Connection, MADB_OPT_FLAG_NO_SCHEMA))
668 client_flags|= CLIENT_NO_SCHEMA;
669 if (DSN_OPTION(Connection, MADB_OPT_FLAG_IGNORE_SPACE))
670 client_flags|= CLIENT_IGNORE_SPACE;
671
672 if (DSN_OPTION(Connection, MADB_OPT_FLAG_FOUND_ROWS))
673 client_flags|= CLIENT_FOUND_ROWS;
674 if (DSN_OPTION(Connection, MADB_OPT_FLAG_COMPRESSED_PROTO))
675 client_flags|= CLIENT_COMPRESS;
676 if (DSN_OPTION(Connection, MADB_OPT_FLAG_MULTI_STATEMENTS))
677 client_flags|= CLIENT_MULTI_STATEMENTS;
678
679 /* enable truncation reporting */
680 mysql_optionsv(Connection->mariadb, MYSQL_REPORT_DATA_TRUNCATION, &ReportDataTruncation);
681
682 if (Dsn->Socket)
683 {
684 int protocol= MYSQL_PROTOCOL_SOCKET;
685 mysql_optionsv(Connection->mariadb, MYSQL_OPT_PROTOCOL, (void*)&protocol);
686 }
687
688 {
689 /* I don't think it's possible to have empty strings or only spaces in the string here, but I prefer
690 to have this paranoid check to make sure we dont' them */
691 const char *SslKey= ltrim(Dsn->SslKey);
692 const char *SslCert= ltrim(Dsn->SslCert);
693 const char *SslCa= ltrim(Dsn->SslCa);
694 const char *SslCaPath= ltrim(Dsn->SslCaPath);
695 const char *SslCipher= ltrim(Dsn->SslCipher);
696
697 if (!MADB_IS_EMPTY(SslCa)
698 || !MADB_IS_EMPTY(SslCaPath)
699 || !MADB_IS_EMPTY(SslCipher)
700 || !MADB_IS_EMPTY(SslCert)
701 || !MADB_IS_EMPTY(SslKey))
702 {
703 char Enable= 1;
704 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_ENFORCE, &Enable);
705
706 if (!MADB_IS_EMPTY(SslKey))
707 {
708 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_KEY, SslKey);
709 }
710 if (!MADB_IS_EMPTY(SslCert))
711 {
712 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_CERT, SslCert);
713 }
714 if (!MADB_IS_EMPTY(SslCa))
715 {
716 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_CA, SslCa);
717 }
718 if (!MADB_IS_EMPTY(SslCaPath))
719 {
720 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_CAPATH, SslCaPath);
721 }
722 if (!MADB_IS_EMPTY(SslCipher))
723 {
724 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_CIPHER, SslCipher);
725 }
726
727 if (Dsn->TlsVersion > 0)
728 {
729 char TlsVersion[sizeof(TlsVersionName) + sizeof(TlsVersionBits) - 1], *Ptr= TlsVersion; /* All names + (n-1) comma */
730 unsigned int i, NeedComma= 0;
731
732 for (i= 0; i < sizeof(TlsVersionBits); ++i)
733 {
734 if (Dsn->TlsVersion & TlsVersionBits[i])
735 {
736 if (NeedComma != 0)
737 {
738 *Ptr++= ',';
739 }
740 else
741 {
742 NeedComma= 1;
743 }
744 strcpy(Ptr, TlsVersionName[i]);
745 Ptr += strlen(TlsVersionName[i]);
746 }
747 }
748 mysql_optionsv(Connection->mariadb, MARIADB_OPT_TLS_VERSION, (void *)TlsVersion);
749 }
750 }
751
752 if (Dsn->SslVerify)
753 {
754 const unsigned int verify= 0x01010101;
755 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char*)&verify);
756 }
757 else
758 {
759 const unsigned int verify= 0;
760 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char*)&verify);
761 }
762 }
763
764 if (Dsn->ForceTls != '\0')
765 {
766 const unsigned int ForceTls= 0x01010101;
767 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_ENFORCE, (const char*)&ForceTls);
768 }
769
770 if (!MADB_IS_EMPTY(Dsn->SslCrlPath))
771 {
772 mysql_optionsv(Connection->mariadb, MYSQL_OPT_SSL_CRLPATH, Dsn->SslCrlPath);
773 }
774
775 if (!mysql_real_connect(Connection->mariadb,
776 Dsn->Socket ? "localhost" : Dsn->ServerName, Dsn->UserName, Dsn->Password,
777 Dsn->Catalog && Dsn->Catalog[0] ? Dsn->Catalog : NULL, Dsn->Port, Dsn->Socket, client_flags))
778 {
779 goto err;
780 }
781
782 /* I guess it is better not to do that at all. Besides SQL_ATTR_PACKET_SIZE is actually not for max packet size */
783 if (Connection->PacketSize)
784 {
785 /*_snprintf(StmtStr, 128, "SET GLOBAL max_allowed_packet=%ld", Connection-> PacketSize);
786 if (mysql_query(Connection->mariadb, StmtStr))
787 goto err;*/
788 }
789
790 /* set default catalog */
791 if (Connection->CatalogName && Connection->CatalogName[0])
792 {
793 if (mysql_select_db(Connection->mariadb, Connection->CatalogName))
794 goto err;
795 }
796
797 /* Turn sql_auto_is_null behavior off.
798 For more details see: http://bugs.mysql.com/bug.php?id=47005 */
799 if (mysql_query(Connection->mariadb, "SET SESSION SQL_AUTO_IS_NULL=0"))
800 goto err;
801
802 /* set autocommit behavior */
803 if (mysql_autocommit(Connection->mariadb, (my_bool)Connection->AutoCommit))
804 goto err;
805
806 /* Set isolation level */
807 if (Connection->IsolationLevel)
808 for (i=0; i < 4; i++)
809 {
810 if (MADB_IsolationLevel[i].SqlIsolation == Connection->IsolationLevel)
811 {
812 _snprintf(StmtStr, 128, "SET SESSION TRANSACTION ISOLATION LEVEL %s",
813 MADB_IsolationLevel[i].StrIsolation);
814 if (mysql_query(Connection->mariadb, StmtStr))
815 goto err;
816 break;
817 }
818 }
819
820 MADB_SetCapabilities(Connection, mysql_get_server_version(Connection->mariadb));
821
822 goto end;
823
824 err:
825 MADB_SetNativeError(&Connection->Error, SQL_HANDLE_DBC, Connection->mariadb);
826
827 end:
828 if (Connection->Error.ReturnValue == SQL_ERROR && Connection->mariadb)
829 {
830 mysql_close(Connection->mariadb);
831 Connection->mariadb= NULL;
832 }
833
834 return Connection->Error.ReturnValue;
835 }
836 /* }}} */
837
838 /* {{{ MADB_DbcGetFunctions */
839 SQLRETURN MADB_DbcGetFunctions(MADB_Dbc *Dbc, SQLUSMALLINT FunctionId, SQLUSMALLINT *SupportedPtr)
840 {
841 unsigned int i, Elements= sizeof(MADB_supported_api) / sizeof(SQLUSMALLINT);
842
843 switch(FunctionId) {
844 case SQL_API_ODBC3_ALL_FUNCTIONS:
845 /* clear ptr */
846 memset(SupportedPtr, 0, sizeof(SQLUSMALLINT) * SQL_API_ODBC3_ALL_FUNCTIONS_SIZE);
847 for (i=0; i < Elements; ++i)
848 {
849 SQLUSMALLINT function= MADB_supported_api[i];
850 SupportedPtr[function >> 4]|= (1 << (function & 0x000F));
851 }
852 break;
853 case SQL_API_ALL_FUNCTIONS:
854 /* Set all to SQL_FALSE (0) */
855 memset(SupportedPtr, 0, sizeof(SQLUSMALLINT) * 100);
856 for (i=0; i < Elements; i++)
857 if (MADB_supported_api[i] < 100)
858 SupportedPtr[MADB_supported_api[i]]= SQL_TRUE;
859 break;
860 default:
861 *SupportedPtr= SQL_FALSE;
862 for (i=0; i < Elements; i++)
863 if (MADB_supported_api[i] == FunctionId)
864 {
865 *SupportedPtr= SQL_TRUE;
866 break;
867 }
868 break;
869 }
870 return SQL_SUCCESS;
871 }
872 /* }}} */
873
874 /* {{{ IsStringInfoType */
875 int IsStringInfoType(SQLSMALLINT InfoType)
876 {
877 switch (InfoType)
878 {
879 case SQL_ACCESSIBLE_PROCEDURES:
880 case SQL_ACCESSIBLE_TABLES:
881 case SQL_CATALOG_NAME:
882 case SQL_CATALOG_NAME_SEPARATOR:
883 case SQL_CATALOG_TERM:
884 case SQL_COLLATION_SEQ:
885 case SQL_COLUMN_ALIAS:
886 case SQL_DATA_SOURCE_NAME:
887 case SQL_DATABASE_NAME:
888 case SQL_DBMS_NAME:
889 case SQL_DBMS_VER:
890 case SQL_DESCRIBE_PARAMETER:
891 case SQL_DRIVER_NAME:
892 case SQL_DRIVER_ODBC_VER:
893 case SQL_DRIVER_VER:
894 case SQL_EXPRESSIONS_IN_ORDERBY:
895 case SQL_INTEGRITY:
896 case SQL_KEYWORDS:
897 case SQL_LIKE_ESCAPE_CLAUSE:
898 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
899 case SQL_MULT_RESULT_SETS:
900 case SQL_MULTIPLE_ACTIVE_TXN:
901 case SQL_NEED_LONG_DATA_LEN:
902 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
903 case SQL_PROCEDURE_TERM:
904 case SQL_PROCEDURES:
905 case SQL_ROW_UPDATES:
906 case SQL_SCHEMA_TERM:
907 case SQL_SEARCH_PATTERN_ESCAPE:
908 case SQL_SERVER_NAME:
909 case SQL_SPECIAL_CHARACTERS:
910 case SQL_TABLE_TERM:
911 case SQL_USER_NAME:
912 case SQL_XOPEN_CLI_YEAR:
913 case SQL_DATA_SOURCE_READ_ONLY:
914 case SQL_IDENTIFIER_QUOTE_CHAR:
915 return 1;
916 }
917
918 return 0;
919 }
920 /* }}} */
921
922 /* {{{ MADB_DbcGetInfo */
923 SQLRETURN MADB_DbcGetInfo(MADB_Dbc *Dbc, SQLUSMALLINT InfoType, SQLPOINTER InfoValuePtr,
924 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, my_bool isWChar)
925 {
926 SQLSMALLINT SLen= 0;
927 extern Client_Charset utf8;
928
929 if (!InfoValuePtr && !StringLengthPtr)
930 return SQL_SUCCESS;
931
932 /* Prety special case - on Windows DM passes NULL instead of InfoValuePtr and own pointer instead of StringLengthPtr.
933 The logic here is not quite clear - I would imagine that truncated status is more appropriate.
934 But UnixODBC does not do so, and we are making connector's behavior consistent */
935 if (InfoValuePtr != NULL && BufferLength == 0 && StringLengthPtr == NULL && IsStringInfoType(InfoType))
936 {
937 return SQL_SUCCESS;
938 }
939
940 MADB_CLEAR_ERROR(&Dbc->Error);
941 switch(InfoType) {
942 case SQL_ACCESSIBLE_PROCEDURES:
943 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
944 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), "N", SQL_NTS, &Dbc->Error);
945 break;
946 case SQL_ACCESSIBLE_TABLES:
947 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
948 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), "N", SQL_NTS, &Dbc->Error);
949 break;
950 case SQL_ACTIVE_ENVIRONMENTS:
951 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
952 break;
953 case SQL_AGGREGATE_FUNCTIONS:
954 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_AF_ALL | SQL_AF_AVG | SQL_AF_COUNT | SQL_AF_DISTINCT |
955 SQL_AF_MAX | SQL_AF_MIN | SQL_AF_SUM, StringLengthPtr);
956 break;
957 case SQL_ALTER_DOMAIN:
958 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
959 break;
960 case SQL_ALTER_TABLE:
961 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_AT_ADD_COLUMN | SQL_AT_DROP_COLUMN, StringLengthPtr);
962 break;
963 #ifdef SQL_ASYNC_DBC_FUNCTIONS
964 case SQL_ASYNC_DBC_FUNCTIONS:
965 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_ASYNC_DBC_NOT_CAPABLE, StringLengthPtr);
966 break;
967 #endif
968 #ifdef SQL_ASYNC_MODE
969 case SQL_ASYNC_MODE:
970 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_AM_NONE, StringLengthPtr);
971 break;
972 #endif
973 #ifdef SQL_ASYNC_NOTIFICATION
974 case SQL_ASYNC_NOTIFICATION:
975 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_ASYNC_NOTIFICATION_NOT_CAPABLE, StringLengthPtr);
976 break;
977 #endif
978 case SQL_BATCH_ROW_COUNT:
979 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_BRC_EXPLICIT, StringLengthPtr);
980 break;
981 case SQL_BATCH_SUPPORT:
982 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_BS_SELECT_EXPLICIT | SQL_BS_ROW_COUNT_EXPLICIT |
983 SQL_BS_SELECT_PROC | SQL_BS_ROW_COUNT_PROC,
984 StringLengthPtr);
985 break;
986 case SQL_BOOKMARK_PERSISTENCE:
987 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
988 break;
989 case SQL_CATALOG_LOCATION:
990 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_CL_START, StringLengthPtr);
991 break;
992 case SQL_CATALOG_NAME:
993 /* Todo: MyODBC Driver has a DSN configuration for diabling catalog usage:
994 but it's not implemented in MAODBC */
995 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
996 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), "Y", SQL_NTS, &Dbc->Error);
997 break;
998 case SQL_CATALOG_NAME_SEPARATOR:
999 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1000 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), ".", SQL_NTS, &Dbc->Error);
1001 break;
1002 case SQL_CATALOG_TERM:
1003 /* todo: See comment for SQL_CATALOG_NAME */
1004 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1005 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), "database", SQL_NTS, &Dbc->Error);
1006 break;
1007 case SQL_CATALOG_USAGE:
1008 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CU_DML_STATEMENTS |
1009 SQL_CU_INDEX_DEFINITION |
1010 SQL_CU_PROCEDURE_INVOCATION |
1011 SQL_CU_PRIVILEGE_DEFINITION |
1012 SQL_CU_TABLE_DEFINITION,
1013 StringLengthPtr);
1014 break;
1015 case SQL_COLLATION_SEQ:
1016 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1017 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1018 Dbc->mariadb->charset->name, SQL_NTS, &Dbc->Error);
1019 break;
1020 case SQL_COLUMN_ALIAS:
1021 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1022 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), "Y", SQL_NTS, &Dbc->Error);
1023 break;
1024 case SQL_CONCAT_NULL_BEHAVIOR:
1025 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_CB_NULL, StringLengthPtr);
1026 break;
1027 case SQL_CONVERT_BIGINT:
1028 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1029 break;
1030 case SQL_CONVERT_BINARY:
1031 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1032 break;
1033 case SQL_CONVERT_BIT:
1034 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1035 break;
1036 case SQL_CONVERT_CHAR:
1037 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1038 break;
1039 case SQL_CONVERT_WCHAR:
1040 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1041 break;
1042 #ifdef SQL_CONVERT_GUID
1043 case SQL_CONVERT_GUID:
1044 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1045 break;
1046 #endif
1047 case SQL_CONVERT_DATE:
1048 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1049 break;
1050 case SQL_CONVERT_DECIMAL:
1051 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1052 break;
1053 case SQL_CONVERT_DOUBLE:
1054 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1055 break;
1056 case SQL_CONVERT_FLOAT:
1057 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1058 break;
1059 case SQL_CONVERT_INTEGER:
1060 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1061 break;
1062 case SQL_CONVERT_INTERVAL_YEAR_MONTH:
1063 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1064 break;
1065 case SQL_CONVERT_INTERVAL_DAY_TIME:
1066 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1067 break;
1068 case SQL_CONVERT_LONGVARBINARY:
1069 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1070 break;
1071 case SQL_CONVERT_LONGVARCHAR:
1072 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1073 break;
1074 case SQL_CONVERT_WLONGVARCHAR:
1075 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1076 break;
1077 case SQL_CONVERT_NUMERIC:
1078 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1079 break;
1080 case SQL_CONVERT_REAL:
1081 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1082 break;
1083 case SQL_CONVERT_SMALLINT:
1084 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1085 break;
1086 case SQL_CONVERT_TIME:
1087 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1088 break;
1089 case SQL_CONVERT_TIMESTAMP:
1090 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1091 break;
1092 case SQL_CONVERT_TINYINT:
1093 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1094 break;
1095 case SQL_CONVERT_VARBINARY:
1096 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1097 break;
1098 case SQL_CONVERT_VARCHAR:
1099 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1100 break;
1101 case SQL_CONVERT_WVARCHAR:
1102 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, MADB_SUPPORTED_CONVERSIONS, StringLengthPtr);
1103 break;
1104 case SQL_CONVERT_FUNCTIONS:
1105 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1106 break;
1107 case SQL_CORRELATION_NAME:
1108 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_CN_DIFFERENT, StringLengthPtr);
1109 break;
1110 case SQL_CREATE_ASSERTION:
1111 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1112 break;
1113 case SQL_CREATE_CHARACTER_SET:
1114 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1115 break;
1116 case SQL_CREATE_COLLATION:
1117 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1118 break;
1119 case SQL_CREATE_DOMAIN:
1120 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1121 break;
1122 case SQL_CREATE_SCHEMA:
1123 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1124 break;
1125 case SQL_CREATE_TABLE:
1126 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CT_COLUMN_COLLATION | SQL_CT_COLUMN_DEFAULT |
1127 SQL_CT_COMMIT_DELETE | SQL_CT_CREATE_TABLE |
1128 SQL_CT_LOCAL_TEMPORARY,
1129 StringLengthPtr);
1130 break;
1131 case SQL_CREATE_TRANSLATION:
1132 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1133 break;
1134 case SQL_CREATE_VIEW:
1135 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CV_CASCADED | SQL_CV_CHECK_OPTION |
1136 SQL_CV_CREATE_VIEW, StringLengthPtr);
1137 break;
1138 case SQL_CURSOR_COMMIT_BEHAVIOR:
1139 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_CB_PRESERVE, StringLengthPtr);
1140 break;
1141 case SQL_CURSOR_ROLLBACK_BEHAVIOR:
1142 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_CB_PRESERVE, StringLengthPtr);
1143 break;
1144 case SQL_CURSOR_SENSITIVITY:
1145 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_UNSPECIFIED, StringLengthPtr);
1146 break;
1147 case SQL_DATA_SOURCE_NAME:
1148 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1149 Dbc->Dsn ? Dbc->Dsn->DSNName : "", SQL_NTS, &Dbc->Error);
1150 break;
1151 case SQL_DATABASE_NAME:
1152 return MADB_Dbc_GetCurrentDB(Dbc, InfoValuePtr, BufferLength, (SQLSMALLINT *)StringLengthPtr, isWChar);
1153 break;
1154 case SQL_DATETIME_LITERALS:
1155 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_DL_SQL92_DATE | SQL_DL_SQL92_TIME |
1156 SQL_DL_SQL92_TIMESTAMP, StringLengthPtr);
1157 break;
1158 case SQL_DBMS_NAME:
1159 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1160 Dbc->mariadb ? (char *)mysql_get_server_name(Dbc->mariadb) : "MariaDB",
1161 SQL_NTS, &Dbc->Error);
1162 break;
1163 case SQL_DBMS_VER:
1164 {
1165 char Version[13];
1166 unsigned long ServerVersion= 0L;
1167
1168 if (Dbc->mariadb)
1169 {
1170 ServerVersion= mysql_get_server_version(Dbc->mariadb);
1171 _snprintf(Version, sizeof(Version), "%02u.%02u.%06u", ServerVersion / 10000,
1172 (ServerVersion % 10000) / 100, ServerVersion % 100);
1173 }
1174 else
1175 Version[0]= 0;
1176 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &utf8 : 0, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1177 Version[0] ? Version : "", SQL_NTS, &Dbc->Error);
1178 }
1179 break;
1180 case SQL_DDL_INDEX:
1181 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX, StringLengthPtr);
1182 break;
1183 case SQL_DEFAULT_TXN_ISOLATION:
1184 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1185 break;
1186 case SQL_DESCRIBE_PARAMETER:
1187 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1188 "N", SQL_NTS, &Dbc->Error);
1189 break;
1190 #ifdef SQL_DRIVER_AWARE_POOLING_SUPPORTED
1191 case SQL_DRIVER_AWARE_POOLING_SUPPORTED:
1192 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_DRIVER_AWARE_POOLING_NOT_CAPABLE, StringLengthPtr);
1193 break;
1194 #endif
1195 /* Handled by driver manager */
1196 case SQL_DRIVER_HDBC:
1197 break;
1198 case SQL_DRIVER_HENV:
1199 break;
1200 case SQL_DRIVER_HLIB:
1201 break;
1202 case SQL_DRIVER_HSTMT:
1203 break;
1204 case SQL_DRIVER_NAME:
1205 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1206 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1207 MADB_DRIVER_NAME, SQL_NTS, &Dbc->Error);
1208 break;
1209 case SQL_DRIVER_ODBC_VER:
1210 {
1211 char *OdbcVersion = "03.51";
1212 /* DM requests this info before Dbc->Charset initialized. Thus checking if it is, and use utf8 by default
1213 The other way would be to use utf8 when Dbc initialized */
1214 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? (Dbc->Charset.cs_info ? &Dbc->Charset : &utf8 ): NULL,
1215 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1216 OdbcVersion, SQL_NTS, &Dbc->Error);
1217 }
1218 break;
1219 case SQL_DRIVER_VER:
1220 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1221 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1222 MARIADB_ODBC_VERSION, SQL_NTS, &Dbc->Error);
1223 break;
1224 /*******************************/
1225 case SQL_DROP_ASSERTION:
1226 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1227 break;
1228 case SQL_DROP_CHARACTER_SET:
1229 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1230 break;
1231 case SQL_DROP_COLLATION:
1232 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1233 break;
1234 case SQL_DROP_DOMAIN:
1235 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1236 break;
1237 case SQL_DROP_SCHEMA:
1238 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1239 break;
1240 case SQL_DROP_TABLE:
1241 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_DT_CASCADE | SQL_DT_DROP_TABLE |
1242 SQL_DT_RESTRICT, StringLengthPtr);
1243 break;
1244 case SQL_DROP_TRANSLATION:
1245 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1246 break;
1247 case SQL_DROP_VIEW:
1248 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_DV_CASCADE | SQL_DV_DROP_VIEW |
1249 SQL_DV_RESTRICT, StringLengthPtr);
1250 break;
1251 case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
1252 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CA1_ABSOLUTE |
1253 SQL_CA1_BULK_ADD |
1254 SQL_CA1_LOCK_NO_CHANGE |
1255 SQL_CA1_NEXT |
1256 SQL_CA1_POSITIONED_DELETE |
1257 SQL_CA1_POSITIONED_UPDATE |
1258 SQL_CA1_POS_DELETE |
1259 SQL_CA1_POS_POSITION |
1260 SQL_CA1_POS_REFRESH |
1261 SQL_CA1_POS_UPDATE |
1262 SQL_CA1_RELATIVE, StringLengthPtr);
1263 break;
1264 case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
1265 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CA2_CRC_EXACT |
1266 SQL_CA2_MAX_ROWS_DELETE |
1267 SQL_CA2_MAX_ROWS_INSERT |
1268 SQL_CA2_MAX_ROWS_SELECT |
1269 SQL_CA2_MAX_ROWS_UPDATE |
1270 SQL_CA2_SENSITIVITY_ADDITIONS |
1271 SQL_CA2_SENSITIVITY_DELETIONS |
1272 SQL_CA2_SENSITIVITY_UPDATES |
1273 SQL_CA2_SIMULATE_TRY_UNIQUE, StringLengthPtr);
1274 break;
1275 case SQL_EXPRESSIONS_IN_ORDERBY:
1276 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1277 "Y", SQL_NTS, &Dbc->Error);
1278 break;
1279 case SQL_FILE_USAGE:
1280 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_FILE_NOT_SUPPORTED, StringLengthPtr);
1281 break;
1282 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
1283 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CA1_ABSOLUTE |
1284 SQL_CA1_BULK_ADD |
1285 SQL_CA1_LOCK_NO_CHANGE |
1286 SQL_CA1_NEXT |
1287 SQL_CA1_POSITIONED_DELETE |
1288 SQL_CA1_POSITIONED_UPDATE |
1289 SQL_CA1_POS_DELETE |
1290 SQL_CA1_POS_POSITION |
1291 SQL_CA1_POS_REFRESH |
1292 SQL_CA1_POS_UPDATE |
1293 SQL_CA1_RELATIVE, StringLengthPtr);
1294 break;
1295 case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
1296 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CA2_CRC_EXACT |
1297 SQL_CA2_MAX_ROWS_DELETE |
1298 SQL_CA2_MAX_ROWS_INSERT |
1299 SQL_CA2_MAX_ROWS_SELECT |
1300 SQL_CA2_MAX_ROWS_UPDATE, StringLengthPtr);
1301 break;
1302 case SQL_GETDATA_EXTENSIONS:
1303 {
1304 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER |
1305 SQL_GD_BLOCK | SQL_GD_BOUND, StringLengthPtr);
1306 break;
1307 }
1308 case SQL_GROUP_BY:
1309 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_GB_NO_RELATION, StringLengthPtr);
1310 break;
1311 case SQL_IDENTIFIER_CASE:
1312 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_IC_MIXED, StringLengthPtr);
1313 break;
1314 case SQL_IDENTIFIER_QUOTE_CHAR:
1315 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1316 MADB_SqlMode(Dbc, MADB_ANSI_QUOTES) ? "\"" : "`", SQL_NTS, &Dbc->Error);
1317 break;
1318 case SQL_INDEX_KEYWORDS:
1319 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_IK_ALL, StringLengthPtr);
1320 break;
1321 case SQL_INFO_SCHEMA_VIEWS:
1322 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_ISV_CHARACTER_SETS | SQL_ISV_COLLATIONS |
1323 SQL_ISV_COLUMNS | SQL_ISV_COLUMN_PRIVILEGES |
1324 SQL_ISV_KEY_COLUMN_USAGE | SQL_ISV_REFERENTIAL_CONSTRAINTS |
1325 SQL_ISV_TABLES | SQL_ISV_TABLE_PRIVILEGES |
1326 SQL_ISV_TABLE_CONSTRAINTS | SQL_ISV_VIEWS, StringLengthPtr);
1327 break;
1328 case SQL_INSERT_STATEMENT:
1329 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_IS_INSERT_LITERALS | SQL_IS_INSERT_SEARCHED |
1330 SQL_IS_SELECT_INTO, StringLengthPtr);
1331 break;
1332 case SQL_INTEGRITY:
1333 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1334 "N", SQL_NTS, &Dbc->Error);
1335 break;
1336 case SQL_KEYSET_CURSOR_ATTRIBUTES1:
1337 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1338 break;
1339 case SQL_KEYSET_CURSOR_ATTRIBUTES2:
1340 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1341 break;
1342 case SQL_KEYWORDS:
1343 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1344 "ACCESSIBLE,ANALYZE,ASENSITIVE,BEFORE,BIGINT,BINARY,BLOB,CALL,"
1345 "CHANGE,CONDITION,DATABASE,DATABASES,DAY_HOUR,DAY_MICROSECOND,"
1346 "DAY_MINUTE,DAY_SECOND,DELAYED,DETERMINISTIC,DISTINCTROW,DIV,"
1347 "DUAL,EACH,ELSEIF,ENCLOSED,ESCAPED,EXIT,EXPLAIN,FLOAT4,FLOAT8,"
1348 "FORCE,FULLTEXT,HIGH_PRIORITY,HOUR_MICROSECOND,HOUR_MINUTE,"
1349 "HOUR_SECOND,IF,IGNORE,INFILE,INOUT,INT1,INT2,INT3,INT4,INT8,"
1350 "ITERATE,KEY,KEYS,KILL,LEAVE,LIMIT,LINEAR,LINES,LOAD,LOCALTIME,"
1351 "LOCALTIMESTAMP,LOCK,LONG,LONGBLOB,LONGTEXT,LOOP,LOW_PRIORITY,"
1352 "MEDIUMBLOB,MEDIUMINT,MEDIUMTEXT,MIDDLEINT,MINUTE_MICROSECOND,"
1353 "MINUTE_SECOND,MOD,MODIFIES,NO_WRITE_TO_BINLOG,OPTIMIZE,OPTIONALLY,"
1354 "OUT,OUTFILE,PURGE,RANGE,READS,READ_ONLY,READ_WRITE,REGEXP,RELEASE,"
1355 "RENAME,REPEAT,REPLACE,REQUIRE,RETURN,RLIKE,SCHEMAS,"
1356 "SECOND_MICROSECOND,SENSITIVE,SEPARATOR,SHOW,SPATIAL,SPECIFIC,"
1357 "SQLEXCEPTION,SQL_BIG_RESULT,SQL_CALC_FOUND_ROWS,SQL_SMALL_RESULT,"
1358 "SSL,STARTING,STRAIGHT_JOIN,TERMINATED,TINYBLOB,TINYINT,TINYTEXT,"
1359 "TRIGGER,UNDO,UNLOCK,UNSIGNED,USE,UTC_DATE,UTC_TIME,UTC_TIMESTAMP,"
1360 "VARBINARY,VARCHARACTER,WHILE,X509,XOR,YEAR_MONTH,ZEROFILL,GENERAL,"
1361 "IGNORE_SERVER_IDS,MASTER_HEARTBEAT_PERIOD,MAXVALUE,RESIGNAL,SIGNAL,"
1362 "SLOW", SQL_NTS, &Dbc->Error);
1363 break;
1364 case SQL_LIKE_ESCAPE_CLAUSE:
1365 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1366 "Y", SQL_NTS, &Dbc->Error);
1367 break;
1368 case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
1369 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1370 break;
1371 case SQL_MAX_BINARY_LITERAL_LEN:
1372 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1373 break;
1374 case SQL_MAX_CATALOG_NAME_LEN:
1375 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, NAME_CHAR_LEN * SYSTEM_MB_MAX_CHAR_LENGTH, StringLengthPtr);
1376 break;
1377 case SQL_MAX_CHAR_LITERAL_LEN:
1378 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1379 break;
1380 case SQL_MAX_COLUMN_NAME_LEN:
1381 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, NAME_CHAR_LEN * SYSTEM_MB_MAX_CHAR_LENGTH - 1, StringLengthPtr);
1382 break;
1383 case SQL_MAX_COLUMNS_IN_GROUP_BY:
1384 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1385 break;
1386 case SQL_MAX_COLUMNS_IN_INDEX:
1387 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 32, StringLengthPtr);
1388 break;
1389 case SQL_MAX_COLUMNS_IN_ORDER_BY:
1390 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1391 break;
1392 case SQL_MAX_COLUMNS_IN_SELECT:
1393 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1394 break;
1395 case SQL_MAX_COLUMNS_IN_TABLE:
1396 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1397 break;
1398 case SQL_MAX_CONCURRENT_ACTIVITIES:
1399 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1400 break;
1401 case SQL_MAX_CURSOR_NAME_LEN:
1402 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, MADB_MAX_CURSOR_NAME, StringLengthPtr);
1403 break;
1404 case SQL_MAX_DRIVER_CONNECTIONS:
1405 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1406 break;
1407 case SQL_MAX_IDENTIFIER_LEN:
1408 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, NAME_CHAR_LEN * SYSTEM_MB_MAX_CHAR_LENGTH, StringLengthPtr);
1409 break;
1410 case SQL_MAX_INDEX_SIZE:
1411 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 3072, StringLengthPtr);
1412 break;
1413 case SQL_MAX_PROCEDURE_NAME_LEN:
1414 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, NAME_CHAR_LEN * SYSTEM_MB_MAX_CHAR_LENGTH, StringLengthPtr);
1415 break;
1416 case SQL_MAX_ROW_SIZE:
1417 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1418 break;
1419 case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
1420 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1421 "Y", SQL_NTS, &Dbc->Error);
1422 break;
1423 case SQL_MAX_SCHEMA_NAME_LEN:
1424 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 0, StringLengthPtr);
1425 break;
1426 case SQL_MAX_STATEMENT_LEN:
1427 {
1428 size_t max_packet_size;
1429 mariadb_get_infov(Dbc->mariadb, MARIADB_MAX_ALLOWED_PACKET, &max_packet_size);
1430 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, (SQLUINTEGER)max_packet_size, StringLengthPtr);
1431 }
1432 break;
1433 case SQL_MAX_TABLE_NAME_LEN:
1434 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, NAME_CHAR_LEN * SYSTEM_MB_MAX_CHAR_LENGTH, StringLengthPtr);
1435 break;
1436 case SQL_MAX_TABLES_IN_SELECT:
1437 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, 63, StringLengthPtr);
1438 break;
1439 case SQL_MAX_USER_NAME_LEN:
1440 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, USERNAME_LENGTH, StringLengthPtr);
1441 break;
1442 case SQL_MULT_RESULT_SETS:
1443 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1444 "Y", SQL_NTS, &Dbc->Error);
1445 break;
1446 case SQL_MULTIPLE_ACTIVE_TXN:
1447 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1448 "Y", SQL_NTS, &Dbc->Error);
1449 break;
1450 case SQL_NEED_LONG_DATA_LEN:
1451 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1452 "N", SQL_NTS, &Dbc->Error);
1453 break;
1454 case SQL_NON_NULLABLE_COLUMNS:
1455 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_NNC_NON_NULL, StringLengthPtr);
1456 break;
1457 case SQL_NULL_COLLATION:
1458 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_NC_LOW, StringLengthPtr);
1459 break;
1460 case SQL_NUMERIC_FUNCTIONS:
1461 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_FN_NUM_ABS | SQL_FN_NUM_ACOS | SQL_FN_NUM_ASIN |
1462 SQL_FN_NUM_ATAN | SQL_FN_NUM_ATAN2 | SQL_FN_NUM_CEILING |
1463 SQL_FN_NUM_COS | SQL_FN_NUM_COT | SQL_FN_NUM_EXP |
1464 SQL_FN_NUM_FLOOR | SQL_FN_NUM_LOG | SQL_FN_NUM_MOD |
1465 SQL_FN_NUM_SIGN | SQL_FN_NUM_SIN | SQL_FN_NUM_SQRT |
1466 SQL_FN_NUM_TAN | SQL_FN_NUM_PI | SQL_FN_NUM_RAND |
1467 SQL_FN_NUM_DEGREES | SQL_FN_NUM_LOG10 | SQL_FN_NUM_POWER |
1468 SQL_FN_NUM_RADIANS | SQL_FN_NUM_ROUND | SQL_FN_NUM_TRUNCATE,
1469 StringLengthPtr);
1470 break;
1471 case SQL_ODBC_API_CONFORMANCE:
1472 MADB_SET_NUM_VAL(SQLSMALLINT, InfoValuePtr, SQL_OAC_LEVEL1, StringLengthPtr);
1473 break;
1474 case SQL_ODBC_INTERFACE_CONFORMANCE:
1475 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_OIC_CORE, StringLengthPtr);
1476 break;
1477 case SQL_ODBC_SQL_CONFORMANCE:
1478 MADB_SET_NUM_VAL(SQLSMALLINT, InfoValuePtr, SQL_OSC_CORE, StringLengthPtr);
1479 break;
1480 case SQL_ODBC_VER:
1481 break;
1482 case SQL_OUTER_JOINS:
1483 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL,
1484 (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar), "Y", SQL_NTS, &Dbc->Error);
1485 break;
1486 case SQL_OJ_CAPABILITIES:
1487 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_OJ_LEFT | SQL_OJ_RIGHT |
1488 SQL_OJ_NESTED | SQL_OJ_INNER, StringLengthPtr);
1489 break;
1490 case SQL_ORDER_BY_COLUMNS_IN_SELECT:
1491 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1492 "N", SQL_NTS, &Dbc->Error);
1493 break;
1494 case SQL_PARAM_ARRAY_ROW_COUNTS:
1495 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_PARC_NO_BATCH, StringLengthPtr);
1496 break;
1497 case SQL_PARAM_ARRAY_SELECTS:
1498 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_PAS_NO_BATCH, StringLengthPtr);
1499 break;
1500 case SQL_PROCEDURE_TERM:
1501 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1502 "stored procedure", SQL_NTS, &Dbc->Error);
1503 break;
1504 case SQL_PROCEDURES:
1505 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr, BUFFER_CHAR_LEN(BufferLength, isWChar),
1506 "Y", SQL_NTS, &Dbc->Error);
1507 break;
1508 case SQL_QUOTED_IDENTIFIER_CASE:
1509 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_IC_SENSITIVE, StringLengthPtr);
1510 break;
1511 case SQL_ROW_UPDATES:
1512 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1513 BUFFER_CHAR_LEN(BufferLength, isWChar),
1514 "N", SQL_NTS, &Dbc->Error);
1515 break;
1516 case SQL_SCHEMA_TERM:
1517 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1518 BUFFER_CHAR_LEN(BufferLength, isWChar),
1519 "", SQL_NTS, &Dbc->Error);
1520 break;
1521 case SQL_SCHEMA_USAGE:
1522 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1523 break;
1524 case SQL_SCROLL_OPTIONS:
1525 {
1526 SQLUINTEGER Options= SQL_SO_FORWARD_ONLY;
1527 if (!MA_ODBC_CURSOR_FORWARD_ONLY(Dbc))
1528 Options|= SQL_SO_STATIC;
1529 if (MA_ODBC_CURSOR_DYNAMIC(Dbc))
1530 Options|= SQL_SO_DYNAMIC;
1531 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, Options, StringLengthPtr);
1532 }
1533 break;
1534 case SQL_SEARCH_PATTERN_ESCAPE:
1535 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1536 BUFFER_CHAR_LEN(BufferLength, isWChar),
1537 "\\", SQL_NTS, &Dbc->Error);
1538 break;
1539 case SQL_SERVER_NAME:
1540 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1541 BUFFER_CHAR_LEN(BufferLength, isWChar),
1542 !(Dbc->mariadb) ? "" : Dbc->mariadb->host_info, SQL_NTS, &Dbc->Error);
1543 break;
1544 case SQL_SPECIAL_CHARACTERS:
1545 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1546 BUFFER_CHAR_LEN(BufferLength, isWChar),
1547 "\"\\/", SQL_NTS, &Dbc->Error);
1548 break;
1549 case SQL_SQL_CONFORMANCE:
1550 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SC_SQL92_INTERMEDIATE, StringLengthPtr);
1551 break;
1552 case SQL_SQL92_DATETIME_FUNCTIONS:
1553 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SDF_CURRENT_DATE | SQL_SDF_CURRENT_TIME |
1554 SQL_SDF_CURRENT_TIMESTAMP, StringLengthPtr);
1555 break;
1556 case SQL_SQL92_FOREIGN_KEY_DELETE_RULE:
1557 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1558 break;
1559 case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE:
1560 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1561 break;
1562 case SQL_SQL92_GRANT:
1563 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SG_DELETE_TABLE | SQL_SG_INSERT_COLUMN |
1564 SQL_SG_INSERT_TABLE | SQL_SG_REFERENCES_COLUMN |
1565 SQL_SG_REFERENCES_TABLE | SQL_SG_SELECT_TABLE |
1566 SQL_SG_UPDATE_COLUMN | SQL_SG_UPDATE_TABLE |
1567 SQL_SG_WITH_GRANT_OPTION, StringLengthPtr);
1568 break;
1569 case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS:
1570 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SNVF_BIT_LENGTH | SQL_SNVF_CHARACTER_LENGTH |
1571 SQL_SNVF_CHAR_LENGTH | SQL_SNVF_EXTRACT |
1572 SQL_SNVF_OCTET_LENGTH | SQL_SNVF_POSITION,
1573 StringLengthPtr);
1574 break;
1575 case SQL_SQL92_PREDICATES:
1576 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SP_BETWEEN | SQL_SP_COMPARISON |
1577 SQL_SP_EXISTS | SQL_SP_IN | SQL_SP_ISNOTNULL |
1578 SQL_SP_ISNULL | SQL_SP_LIKE | SQL_SP_QUANTIFIED_COMPARISON,
1579 StringLengthPtr);
1580 break;
1581 case SQL_SQL92_RELATIONAL_JOIN_OPERATORS:
1582 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SRJO_CROSS_JOIN | SQL_SRJO_INNER_JOIN |
1583 SQL_SRJO_LEFT_OUTER_JOIN | SQL_SRJO_RIGHT_OUTER_JOIN |
1584 SQL_SRJO_NATURAL_JOIN,
1585 StringLengthPtr);
1586 break;
1587 case SQL_SQL92_REVOKE:
1588 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SR_DELETE_TABLE | SQL_SR_INSERT_COLUMN |
1589 SQL_SR_INSERT_TABLE | SQL_SR_REFERENCES_COLUMN |
1590 SQL_SR_REFERENCES_TABLE | SQL_SR_SELECT_TABLE |
1591 SQL_SR_UPDATE_COLUMN | SQL_SR_UPDATE_TABLE,
1592 StringLengthPtr);
1593 break;
1594 case SQL_SQL92_ROW_VALUE_CONSTRUCTOR:
1595 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SRVC_DEFAULT | SQL_SRVC_NULL |
1596 SQL_SRVC_ROW_SUBQUERY | SQL_SRVC_VALUE_EXPRESSION,
1597 StringLengthPtr);
1598 break;
1599 case SQL_SQL92_STRING_FUNCTIONS:
1600 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SSF_CONVERT | SQL_SSF_LOWER |
1601 SQL_SSF_SUBSTRING | SQL_SSF_TRANSLATE |
1602 SQL_SSF_TRIM_BOTH | SQL_SSF_TRIM_LEADING |
1603 SQL_SSF_TRIM_TRAILING | SQL_SSF_UPPER,
1604 StringLengthPtr);
1605 break;
1606 case SQL_SQL92_VALUE_EXPRESSIONS:
1607 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SVE_CASE | SQL_SVE_CAST | SQL_SVE_COALESCE |
1608 SQL_SVE_NULLIF, StringLengthPtr);
1609 break;
1610 case SQL_STANDARD_CLI_CONFORMANCE:
1611 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SCC_ISO92_CLI, StringLengthPtr);
1612 break;
1613 case SQL_STATIC_CURSOR_ATTRIBUTES1:
1614 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CA1_ABSOLUTE | /* SQL_CA1_BOOKMARK | */
1615 SQL_CA1_NEXT | SQL_CA1_RELATIVE,
1616 StringLengthPtr);
1617 break;
1618 case SQL_STATIC_CURSOR_ATTRIBUTES2:
1619 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_CA2_MAX_ROWS_SELECT, StringLengthPtr);
1620 break;
1621 case SQL_STRING_FUNCTIONS:
1622 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_FN_STR_ASCII | SQL_FN_STR_BIT_LENGTH |
1623 SQL_FN_STR_CHAR | SQL_FN_STR_CHAR_LENGTH |
1624 SQL_FN_STR_CONCAT | SQL_FN_STR_INSERT |
1625 SQL_FN_STR_LCASE | SQL_FN_STR_LEFT |
1626 SQL_FN_STR_LENGTH | SQL_FN_STR_LOCATE |
1627 SQL_FN_STR_LOCATE_2 | SQL_FN_STR_LTRIM |
1628 SQL_FN_STR_OCTET_LENGTH | SQL_FN_STR_POSITION |
1629 SQL_FN_STR_REPEAT | SQL_FN_STR_REPLACE |
1630 SQL_FN_STR_RIGHT | SQL_FN_STR_RTRIM |
1631 SQL_FN_STR_SOUNDEX | SQL_FN_STR_SPACE |
1632 SQL_FN_STR_SUBSTRING | SQL_FN_STR_UCASE,
1633 StringLengthPtr);
1634 break;
1635 case SQL_SUBQUERIES:
1636 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_SQ_COMPARISON | SQL_SQ_CORRELATED_SUBQUERIES |
1637 SQL_SQ_EXISTS | SQL_SQ_IN | SQL_SQ_QUANTIFIED,
1638 StringLengthPtr);
1639 break;
1640 case SQL_SYSTEM_FUNCTIONS:
1641 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_FN_SYS_DBNAME | SQL_FN_SYS_IFNULL |
1642 SQL_FN_SYS_USERNAME, StringLengthPtr);
1643 break;
1644 case SQL_TABLE_TERM:
1645 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1646 BUFFER_CHAR_LEN(BufferLength, isWChar),
1647 "table", SQL_NTS, &Dbc->Error);
1648 break;
1649 case SQL_TIMEDATE_ADD_INTERVALS:
1650 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1651 break;
1652 case SQL_TIMEDATE_DIFF_INTERVALS:
1653 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, 0, StringLengthPtr);
1654 break;
1655 case SQL_TIMEDATE_FUNCTIONS:
1656 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_FN_TD_CURDATE | SQL_FN_TD_CURRENT_DATE |
1657 SQL_FN_TD_CURRENT_TIME | SQL_FN_TD_CURRENT_TIMESTAMP |
1658 SQL_FN_TD_CURTIME | SQL_FN_TD_DAYNAME |
1659 SQL_FN_TD_DAYOFMONTH | SQL_FN_TD_DAYOFWEEK |
1660 SQL_FN_TD_DAYOFYEAR | SQL_FN_TD_EXTRACT |
1661 SQL_FN_TD_HOUR | SQL_FN_TD_MINUTE |
1662 SQL_FN_TD_MONTH | SQL_FN_TD_MONTHNAME |
1663 SQL_FN_TD_NOW | SQL_FN_TD_QUARTER |
1664 SQL_FN_TD_SECOND | SQL_FN_TD_TIMESTAMPADD |
1665 SQL_FN_TD_TIMESTAMPDIFF | SQL_FN_TD_WEEK | SQL_FN_TD_YEAR,
1666 StringLengthPtr);
1667 break;
1668 case SQL_TXN_CAPABLE:
1669 MADB_SET_NUM_VAL(SQLUSMALLINT, InfoValuePtr, SQL_TC_DDL_COMMIT, StringLengthPtr);
1670 break;
1671 case SQL_TXN_ISOLATION_OPTION:
1672 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_TXN_READ_COMMITTED | SQL_TXN_READ_UNCOMMITTED |
1673 SQL_TXN_REPEATABLE_READ | SQL_TXN_SERIALIZABLE,
1674 StringLengthPtr);
1675 break;
1676 case SQL_UNION:
1677 MADB_SET_NUM_VAL(SQLUINTEGER, InfoValuePtr, SQL_U_UNION | SQL_U_UNION_ALL, StringLengthPtr);
1678 break;
1679 case SQL_USER_NAME:
1680 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1681 BUFFER_CHAR_LEN(BufferLength, isWChar),
1682 (Dbc->mariadb) ? Dbc->mariadb->user : "", SQL_NTS, &Dbc->Error);
1683 break;
1684 case SQL_XOPEN_CLI_YEAR:
1685 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1686 BUFFER_CHAR_LEN(BufferLength, isWChar),
1687 "1992", SQL_NTS, &Dbc->Error);
1688 break;
1689 case SQL_DATA_SOURCE_READ_ONLY:
1690 SLen= (SQLSMALLINT)MADB_SetString(isWChar ? &Dbc->Charset : NULL, (void *)InfoValuePtr,
1691 BUFFER_CHAR_LEN(BufferLength, isWChar),
1692 "N", SQL_NTS, &Dbc->Error);
1693 break;
1694 /* 2.0 types */
1695 case SQL_POS_OPERATIONS:
1696 MADB_SET_NUM_VAL(SQLINTEGER, InfoValuePtr, SQL_POS_POSITION | SQL_POS_REFRESH | SQL_POS_UPDATE | SQL_POS_DELETE | SQL_POS_ADD,
1697 StringLengthPtr);
1698 break;
1699 case SQL_STATIC_SENSITIVITY:
1700 MADB_SET_NUM_VAL(SQLINTEGER, InfoValuePtr, SQL_SS_DELETIONS | SQL_SS_UPDATES, StringLengthPtr);
1701 break;
1702 case SQL_LOCK_TYPES:
1703 MADB_SET_NUM_VAL(SQLINTEGER, InfoValuePtr, SQL_LCK_NO_CHANGE, StringLengthPtr);
1704 break;
1705 case SQL_SCROLL_CONCURRENCY:
1706 MADB_SET_NUM_VAL(SQLINTEGER, InfoValuePtr, SQL_SCCO_READ_ONLY | SQL_SCCO_OPT_VALUES, StringLengthPtr);
1707 break;
1708 default:
1709 MADB_SetError(&Dbc->Error, MADB_ERR_HY096, NULL, 0);
1710 return Dbc->Error.ReturnValue;
1711 }
1712 if (isWChar && SLen)
1713 {
1714 SLen*= sizeof(SQLWCHAR);
1715 }
1716 if (IsStringInfoType(InfoType) && StringLengthPtr)
1717 {
1718 *StringLengthPtr= SLen;
1719 }
1720
1721 return SQL_SUCCESS;
1722 }
1723 /* }}} */
1724
1725
1726 /* {{{ MADB_DriverSideMemalocate */
1727 char * MADB_DriverSideAllocate(size_t size)
1728 {
1729 return (char *)MADB_CALLOC(size);
1730 }
1731 /* }}} */
1732
1733
1734 /* {{{ MADB_DriverSideFree */
1735 void MADB_DriverSideFree(void *ptr)
1736 {
1737 MADB_FREE(ptr);
1738 }
1739 /* }}} */
1740
1741
1742 /* {{{ MADB_DriverConnect */
1743 SQLRETURN MADB_DriverConnect(MADB_Dbc *Dbc, SQLHWND WindowHandle, SQLCHAR *InConnectionString,
1744 SQLULEN StringLength1, SQLCHAR *OutConnectionString,
1745 SQLULEN BufferLength, SQLSMALLINT *StringLength2Ptr,
1746 SQLUSMALLINT DriverCompletion)
1747 {
1748 MADB_Dsn *Dsn;
1749 MADB_Drv *Drv= NULL;
1750 SQLRETURN ret= SQL_SUCCESS;
1751 MADB_Prompt DSNPrompt= { NULL, NULL };
1752 SQLULEN Length;
1753
1754 if (!Dbc)
1755 return SQL_INVALID_HANDLE;
1756
1757 MADB_CLEAR_ERROR(&Dbc->Error);
1758
1759 Dsn= MADB_DSN_Init();
1760
1761 if (!MADB_ReadConnString(Dsn, (char *)InConnectionString, StringLength1, ';'))
1762 {
1763 MADB_SetError(&Dbc->Error, MADB_ERR_HY000, "Error while parsing DSN", 0);
1764 goto error;
1765 }
1766
1767 /* if DSN prompt is off, adjusting DriverCompletion */
1768 if (Dsn->ConnectPrompt)
1769 DriverCompletion= SQL_DRIVER_NOPROMPT;
1770
1771 switch (DriverCompletion) {
1772 case SQL_DRIVER_COMPLETE_REQUIRED:
1773 case SQL_DRIVER_COMPLETE:
1774 case SQL_DRIVER_NOPROMPT:
1775
1776 if (SQL_SUCCEEDED(MADB_DbcConnectDB(Dbc, Dsn)))
1777 {
1778 goto end;
1779 }
1780 else if (DriverCompletion == SQL_DRIVER_NOPROMPT)
1781 {
1782 /* For SQL_DRIVER_COMPLETE(_REQUIRED) this is not the end - will show prompt for user */
1783 goto error;
1784 }
1785 /* If we got here, it means that we had unsuccessful connect attempt with SQL_DRIVER_COMPLETE(_REQUIRED) completion
1786 Have to clean that error */
1787 MADB_CLEAR_ERROR(&Dbc->Error);
1788 break;
1789
1790 case SQL_DRIVER_PROMPT:
1791 break;
1792 default:
1793 MADB_SetError(&Dbc->Error, MADB_ERR_HY110, NULL, 0);
1794 goto error;
1795 break;
1796 }
1797
1798 /* Without window handle we can't show a dialog */
1799 if (DriverCompletion != SQL_DRIVER_NOPROMPT && !WindowHandle)
1800 {
1801 MADB_SetError(&Dbc->Error, MADB_ERR_IM008, NULL, 0);
1802 goto error;
1803 }
1804
1805 if (DriverCompletion == SQL_DRIVER_COMPLETE_REQUIRED)
1806 Dsn->isPrompt= MAODBC_PROMPT_REQUIRED;
1807 else
1808 Dsn->isPrompt= MAODBC_PROMPT;
1809
1810 /* We need to obtain the driver name to load maodbcs.dll, if it's not stored inside DSN,
1811 error IM007 (dialog prohibited) will be returned */
1812 if (!Dsn->Driver)
1813 {
1814 MADB_SetError(&Dbc->Error, MADB_ERR_IM007, NULL, 0);
1815 goto error;
1816 }
1817
1818 if (!(Drv= MADB_DriverGet(Dsn->Driver)))
1819 {
1820 MADB_SetError(&Dbc->Error, MADB_ERR_IM003, NULL, 0);
1821 goto error;
1822 }
1823 if (!Drv->SetupLibrary)
1824 {
1825 MADB_SetError(&Dbc->Error, MADB_ERR_HY000, "Couldn't determine setup library", 0);
1826 goto error;
1827 }
1828
1829 if (!SQL_SUCCEEDED(DSNPrompt_Lookup(&DSNPrompt, Drv->SetupLibrary, Dbc)))
1830 {
1831 goto error;
1832 }
1833
1834 Dsn->allocator= MADB_DriverSideAllocate;
1835 Dsn->free= MADB_DriverSideFree;
1836
1837 if (DSNPrompt.Call((HWND)WindowHandle, Dsn) == FALSE)
1838 {
1839 /* If user cancels prompt, SQLDriverConnect should return SQL_NO_DATA */
1840 Dbc->Error.ReturnValue= SQL_NO_DATA;
1841 goto error;
1842 }
1843
1844 DSNPrompt_Free(&DSNPrompt);
1845
1846 ret= MADB_DbcConnectDB(Dbc, Dsn);
1847 if (!SQL_SUCCEEDED(ret))
1848 {
1849 goto error;
1850 }
1851
1852 end:
1853 Dbc->Dsn= Dsn;
1854 /* Dialog returns bitmap - syncing corresponding properties */
1855 MADB_DsnUpdateOptionsFields(Dsn);
1856 if (Dsn->isPrompt)
1857 {
1858 char *PreservePwd;
1859
1860 /* DM should do that on its own, but we still better also remove pwd from the string being saved in the file DSN */
1861 if (Dsn->SaveFile != NULL)
1862 {
1863 PreservePwd= Dsn->Password;
1864 Dsn->Password= NULL;
1865 }
1866 /* If prompt/complete(_required), and dialog was succusefully showed - we generate string from the result DSN */
1867 Length= MADB_DsnToString(Dsn, (char *)OutConnectionString, BufferLength);
1868
1869 if (Dsn->SaveFile != NULL)
1870 {
1871 Dsn->Password= PreservePwd;
1872 }
1873 }
1874 else
1875 {
1876 if (StringLength1 == SQL_NTS)
1877 {
1878 StringLength1= (SQLSMALLINT)strlen((const char*)InConnectionString);
1879 }
1880 if (OutConnectionString && BufferLength)
1881 {
1882 /* Otherwise we are supposed to simply copy incoming connection string */
1883 strncpy_s((char *)OutConnectionString, BufferLength, (const char*)InConnectionString, StringLength1);
1884 }
1885 Length= StringLength1;
1886 }
1887 if (StringLength2Ptr)
1888 *StringLength2Ptr= (SQLSMALLINT)Length;
1889
1890 if (OutConnectionString && BufferLength && Length > BufferLength)
1891 {
1892 MADB_SetError(&Dbc->Error, MADB_ERR_01004, NULL, 0);
1893 return Dbc->Error.ReturnValue;
1894 }
1895 return ret;
1896 error:
1897 DSNPrompt_Free(&DSNPrompt);
1898 MADB_DSN_Free(Dsn);
1899 MADB_DriverFree(Drv);
1900 return Dbc->Error.ReturnValue;
1901 }
1902 /* }}} */
1903
1904 struct st_ma_connection_methods MADB_Dbc_Methods =
1905 {
1906 MADB_DbcSetAttr,
1907 MADB_DbcGetAttr,
1908 MADB_DbcConnectDB,
1909 MADB_DbcEndTran,
1910 MADB_DbcGetFunctions,
1911 MADB_DbcGetInfo,
1912 MADB_DriverConnect
1913 };
0 /************************************************************************************
1 Copyright (C) 2013,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_connection_h_
19 #define _ma_connection_h_
20
21 #define MADB_CONN_OPT_NOT_SUPPORTED 0
22 #define MADB_CONN_OPT_BEFORE 1
23 #define MADB_CONN_OPT_AFTER 2
24 #define MADB_CONN_OPT_BOTH 3
25
26 /* sql_mode's identifiers */
27 enum enum_madb_sql_mode {MADB_NO_BACKSLASH_ESCAPES, MADB_ANSI_QUOTES };
28
29 struct st_ma_connection_methods;
30
31 struct st_madb_isolation {
32 long SqlIsolation;
33 char *StrIsolation;
34 };
35
36 struct st_ma_connection_methods
37 {
38 SQLRETURN (*SetAttr)(MADB_Dbc *Dbc, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength, my_bool isWChar);
39 SQLRETURN (*GetAttr)(MADB_Dbc *Dbc, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength, SQLINTEGER *StringLengthPtr, my_bool isWChar);
40 SQLRETURN (*ConnectDB)(MADB_Dbc *Connection, MADB_Dsn *Dsn);
41 SQLRETURN (*EndTran)(MADB_Dbc *Dbc, SQLSMALLINT CompletionType);
42 SQLRETURN (*GetFunctions)(MADB_Dbc *Dbc, SQLUSMALLINT FunctionId, SQLUSMALLINT *SupportedPtr);
43 SQLRETURN(*GetInfo)(MADB_Dbc *Dnc, SQLUSMALLINT InfoType, SQLPOINTER InfoValuePtr,
44 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, my_bool isWChar);
45 SQLRETURN (*DriverConnect)(MADB_Dbc *Dbc, SQLHWND WindowHandle, SQLCHAR *InConnectionString,
46 SQLULEN StringLength1, SQLCHAR *OutConnectionString,
47 SQLULEN BufferLength, SQLSMALLINT *StringLength2Ptr,
48 SQLUSMALLINT DriverCompletion);
49 };
50
51 my_bool CheckConnection(MADB_Dbc *Dbc);
52
53 SQLRETURN MADB_DbcFree(MADB_Dbc *Connection);
54 MADB_Dbc * MADB_DbcInit(MADB_Env *Env);
55 SQLRETURN MADB_Dbc_GetCurrentDB(MADB_Dbc *Connection, SQLPOINTER CurrentDB, SQLINTEGER CurrentDBLength,
56 SQLSMALLINT *StringLengthPtr, my_bool isWChar);
57 BOOL MADB_SqlMode(MADB_Dbc *Connection, enum enum_madb_sql_mode SqlMode);
58 /* Has platform versions */
59 void MADB_SetDefaultPluginsDir(MADB_Dbc *Dbc);
60
61 #define MADB_SUPPORTED_CONVERSIONS SQL_CVT_BIGINT | SQL_CVT_BIT | SQL_CVT_CHAR | SQL_CVT_DATE |\
62 SQL_CVT_DECIMAL | SQL_CVT_DOUBLE | SQL_CVT_FLOAT |\
63 SQL_CVT_INTEGER | SQL_CVT_LONGVARCHAR | SQL_CVT_NUMERIC |\
64 SQL_CVT_REAL | SQL_CVT_SMALLINT | SQL_CVT_TIME | SQL_CVT_TIMESTAMP |\
65 SQL_CVT_TINYINT | SQL_CVT_VARCHAR | SQL_CVT_WCHAR | \
66 SQL_CVT_WLONGVARCHAR | SQL_CVT_WVARCHAR
67 /**************** Helper macros ****************/
68 /* check if the connection is established */
69 #define MADB_Dbc_ACTIVE(a) \
70 ((a)->mariadb && mysql_get_socket((a)->mariadb) != MARIADB_INVALID_SOCKET)
71
72 #define MADB_Dbc_DSN(a) \
73 (a) && (a)->Dsn
74
75 #define MADB_Dbc_AUTOCOMMIT(a) \
76 ((a)->mariadb && ((a)->mariadb->server_status && SERVER_STATUS_AUTOCOMMIT))
77
78 #define MADB_Dbc_TRANSACTION(a) \
79 ((a)->mariadb && ((a)->mariadb->server_capabilities && CLIENT_TRANSACTIONS))
80
81 #define MADB_CONNECTED(DbConnHandler) (DbConnHandler->mariadb && mysql_get_socket(DbConnHandler->mariadb) != MARIADB_INVALID_SOCKET)
82 #endif /* _ma_connection_h */
0 /************************************************************************************
1 Copyright (C) 2013, 2015 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 #ifdef MAODBC_DEBUG
21 extern char LogFile[];
22
23 void ma_debug_print(my_bool ident, char *format, ...)
24 {
25 FILE *fp= fopen(LogFile, "a");
26 if (fp)
27 {
28 va_list va;
29 va_start(va, format);
30 if (ident)
31 fprintf(fp, "\t");
32 vfprintf(fp, format, va);
33 fprintf(fp, "\n");
34 va_end(va);
35 fclose(fp);
36 }
37 }
38
39 void ma_debug_printw(wchar_t *format, ...)
40 {
41 FILE *fp= fopen(LogFile, "a");
42 if (fp)
43 {
44 va_list va;
45 va_start(va, format);
46 fwprintf(fp, format, va);
47 fwprintf(fp, L"\n");
48 va_end(va);
49 fclose(fp);
50 }
51 }
52
53 void ma_debug_printv(char *format, va_list args)
54 {
55 FILE *fp= fopen(LogFile, "a");
56 if (fp)
57 {
58 vfprintf(fp, format, args);
59 fclose(fp);
60 }
61 }
62
63
64 void ma_debug_print_error(MADB_Error *err)
65 {
66 /*TODO: Make it without #ifdefs */
67 #ifdef _WIN32
68 SYSTEMTIME st;
69
70 GetSystemTime(&st);
71 ma_debug_print(1, "%d-%02d-%02d %02d:%02d:%02d [%s](%u)%s", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, err->SqlState, err->NativeError, err->SqlErrorMsg);
72 #else
73 time_t t = time(NULL);\
74 struct tm st = *gmtime(&t);\
75 ma_debug_print(1, "%d-%02d-%02d %02d:%02d:%02d [%s](%u)%s", st.tm_year + 1900, st.tm_mon + 1, st.tm_mday, st.tm_hour, st.tm_min, st.tm_sec, err->SqlState, err->NativeError, err->SqlErrorMsg);
76 #endif
77 }
78
79
80 void ma_print_value(SQLSMALLINT OdbcType, SQLPOINTER Value, SQLLEN octets)
81 {
82 if (Value == 0)
83 {
84 ma_debug_print(1, "NULL ptr");
85 }
86 if (octets <= 0)
87 {
88 octets= 1;
89 }
90 switch (OdbcType)
91 {
92 case SQL_C_BIT:
93 case SQL_C_TINYINT:
94 case SQL_C_STINYINT:
95 case SQL_C_UTINYINT:
96 ma_debug_print(1, "%d", 0 + *((char*)Value));
97 break;
98 case SQL_C_SHORT:
99 case SQL_C_SSHORT:
100 case SQL_C_USHORT:
101 ma_debug_print(1, "%d", 0 + *((short int*)Value));
102 break;
103 case SQL_C_LONG:
104 case SQL_C_SLONG:
105 case SQL_C_ULONG:
106 ma_debug_print(1, "%d", 0 + *((int*)Value));
107 break;
108 case SQL_C_UBIGINT:
109 case SQL_C_SBIGINT:
110 ma_debug_print(1, "%ll", 0 + *((long long*)Value));
111 break;
112 case SQL_C_DOUBLE:
113 ma_debug_print(1, "%f", 0.0 + *((SQLDOUBLE*)Value));
114 break;
115 case SQL_C_FLOAT:
116 ma_debug_print(1, "%f", 0.0 + *((SQLFLOAT*)Value));
117 break;
118 case SQL_C_NUMERIC:
119 ma_debug_print(1, "%s", "[numeric struct]");
120 break;
121 case SQL_C_TYPE_TIME:
122 case SQL_C_TIME:
123 ma_debug_print(1, "%02d:02d:02d", ((SQL_TIME_STRUCT*)Value)->hour, ((SQL_TIME_STRUCT*)Value)->minute, ((SQL_TIME_STRUCT*)Value)->second);
124 break;
125 case SQL_C_TYPE_DATE:
126 case SQL_C_DATE:
127 ma_debug_print(1, "%4d-02d-02d", ((SQL_DATE_STRUCT*)Value)->year, ((SQL_DATE_STRUCT*)Value)->month, ((SQL_DATE_STRUCT*)Value)->day);
128 break;
129 case SQL_C_TYPE_TIMESTAMP:
130 case SQL_C_TIMESTAMP:
131 ma_debug_print(1, "%4d-02d-02d %02d:02d:02d", ((SQL_TIMESTAMP_STRUCT*)Value)->year, ((SQL_TIMESTAMP_STRUCT*)Value)->month,
132 ((SQL_TIMESTAMP_STRUCT*)Value)->day, ((SQL_TIMESTAMP_STRUCT*)Value)->hour, ((SQL_TIMESTAMP_STRUCT*)Value)->minute, ((SQL_TIMESTAMP_STRUCT*)Value)->second);
133 break;
134 case SQL_C_CHAR:
135 ma_debug_print(1, "%*s%s", MIN(10, octets), (char*)Value, octets > 10 ? "..." : "");
136 break;
137 default:
138 ma_debug_print(1, "%*X%s", MIN(10, octets), (char*)Value, octets > 10 ? "..." : "");
139 break;
140 }
141 }
142
143 /* #ifdef __APPLE__
144 void TravisTrace(char *format, va_list args)
145 {
146 BOOL Travis= FALSE;
147 Travis= getenv("TRAVIS") != NULL;
148
149 if (Travis != FALSE)
150 {
151 printf("#");
152 vprintf(format, args);
153 }
154
155 }
156 #endif */
157 #endif
0 /************************************************************************************
1 Copyright (C) 2013, 2015 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_debug_h_
19 #define _ma_debug_h_
20
21 #ifndef MAODBC_DEBUG
22
23 void ma_debug_print(my_bool ident, char *format, ...);
24
25 #define MDBUG_C_IS_ON(C) (0)
26 #define MDBUG_C_ENTER(C,A) {}
27 #define MDBUG_C_RETURN(C,A,E) return (A)
28 #define MDBUG_C_PRINT(C, format, args) {}
29 #define MDBUG_C_VOID_RETURN(C) {}
30 #define MDBUG_C_DUMP(C,A,B) {}
31
32 #else
33
34 #define MA_DEBUG_FLAG 4
35
36 #ifndef WIN32
37 #include <time.h>
38 #endif
39
40 void ma_debug_print(my_bool ident, char *format, ...);
41 void ma_debug_print_error(MADB_Error *err);
42
43 /* Debug is on for connection */
44 #define MDBUG_C_IS_ON(C) ((C) && (((MADB_Dbc*)(C))->Options & MA_DEBUG_FLAG))
45
46 #ifdef WIN32
47 #define MDBUG_C_ENTER(C,A)\
48 if (MDBUG_C_IS_ON(C))\
49 {\
50 SYSTEMTIME st;\
51 GetSystemTime(&st);\
52 ma_debug_print(0, ">>> %d-%02d-%02d %02d:%02d:%02d --- %s (thread: %d) ---", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, A, ((MADB_Dbc*)(C))->mariadb ? ((MADB_Dbc*)(C))->mariadb->thread_id : 0);\
53 }
54 #else
55 #define MDBUG_C_ENTER(C,A)\
56 if ((C) && (((MADB_Dbc*)(C))->Options & MA_DEBUG_FLAG))\
57 {\
58 time_t t = time(NULL);\
59 struct tm st= *gmtime(&t);\
60 ma_debug_print(0, ">>> %d-%02d-%02d %02d:%02d:%02d --- %s (thread: %d) ---", st.tm_year + 1900, st.tm_mon + 1, st.tm_mday, st.tm_hour, st.tm_min, st.tm_sec, A, ((MADB_Dbc*)(C))->mariadb ? ((MADB_Dbc*)(C))->mariadb->thread_id : 0);\
61 }
62 #endif
63
64 #define MDBUG_C_RETURN(C,A,E)\
65 if (MDBUG_C_IS_ON(C))\
66 {\
67 SQLRETURN _ret= (A);\
68 if (_ret && (E)->ReturnValue)\
69 ma_debug_print_error(E); \
70 ma_debug_print(0, "<<< --- end of function, returning %d ---", _ret); \
71 return _ret;\
72 }\
73 return (A);
74
75 #define MDBUG_C_PRINT(C, format, ...)\
76 if (MDBUG_C_IS_ON(C))\
77 ma_debug_print(1, format, __VA_ARGS__);
78
79 #define MDBUG_C_VOID_RETURN(C)\
80 if (MDBUG_C_IS_ON(C))\
81 ma_debug_print(0, "<<< --- end of function ---");\
82 return;
83
84 #define MDBUG_C_DUMP(C,A,B)\
85 if (MDBUG_C_IS_ON(C))\
86 ma_debug_print(1, #A ":\t%" #B, A);
87
88 #endif /* MAODBC_DEBUG */
89
90 /* These macros will be used to force debug output
91 for functions without a DBC handle */
92 #ifndef MA_ODBC_DEBUG_ALL
93
94 #define MDBUG_ENTER(A) {}
95 #define MDBUG_RETURN(A) return (A)
96 #define MDBUG_PRINT(format, args) {}
97 #define MDBUG_VOID_RETURN() {}
98 #define MDBUG_DUMP(B,C) {}
99
100 #else
101
102 #define MDBUG_ENTER(A)\
103 ma_debug_print(0, ">>> --- %s ---", A);
104
105 #define MDBUG_RETURN(A)\
106 ma_debug_print(0, "<<< .. end of function ---");\
107 return (A);
108
109 #define MDBUG_PRINT(format, ...)\
110 ma_debug_print(1, format, __VA_ARGS__);
111
112 #define MDBUG_VOID_RETURN()\
113 ma_debug_print(0, "<<< --- end of function ---");\
114 return;
115
116 #define MDBUG_DUMP(A,B)\
117 ma_debug_print(1, #A ":\t%" #B, A);
118
119 #endif /* MA_ODBC_DEBUG_ALL */
120
121 #endif /* _ma_debug_h_ */
0 /************************************************************************************
1 Copyright (C) 2013, 2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 extern Client_Charset utf8;
21
22 /* To keep the source code smaller we use the following structure to check if a field
23 identifier is valid for a given descriptor type */
24 struct st_ma_desc_fldid MADB_DESC_FLDID[]=
25 {
26 {SQL_DESC_ALLOC_TYPE, {MADB_DESC_READ, MADB_DESC_READ, MADB_DESC_NONE, MADB_DESC_NONE}},
27 {SQL_DESC_ARRAY_SIZE, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_NONE}},
28 {SQL_DESC_ARRAY_STATUS_PTR, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW}},
29 {SQL_DESC_BIND_OFFSET_PTR, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_NONE}},
30 {SQL_DESC_BIND_TYPE, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_NONE}},
31 {SQL_DESC_COUNT, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_READ}},
32 {SQL_DESC_ROWS_PROCESSED_PTR, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_RW, MADB_DESC_RW}},
33 {SQL_DESC_AUTO_UNIQUE_VALUE, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
34 {SQL_DESC_BASE_COLUMN_NAME, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
35 {SQL_DESC_BASE_TABLE_NAME, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
36 {SQL_DESC_CASE_SENSITIVE, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
37 {SQL_DESC_CATALOG_NAME, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
38 {SQL_DESC_CONCISE_TYPE, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW}},
39 {SQL_DESC_DATA_PTR, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_NONE}},
40 {SQL_DESC_DATETIME_INTERVAL_CODE, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
41 {SQL_DESC_DATETIME_INTERVAL_PRECISION, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
42 {SQL_DESC_DISPLAY_SIZE, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE}},
43 {SQL_DESC_FIXED_PREC_SCALE, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_RW, MADB_DESC_RW}},
44 {SQL_DESC_INDICATOR_PTR, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_NONE}},
45 {SQL_DESC_LABEL, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE}},
46 {SQL_DESC_LENGTH, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
47 {SQL_DESC_LITERAL_PREFIX, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
48 {SQL_DESC_LITERAL_SUFFIX, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
49 {SQL_DESC_LOCAL_TYPE_NAME, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ, MADB_DESC_READ}},
50 {SQL_DESC_NAME, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_RW, MADB_DESC_READ}},
51 {SQL_DESC_NULLABLE, {MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ, MADB_DESC_READ}},
52 {SQL_DESC_NUM_PREC_RADIX, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
53 {SQL_DESC_OCTET_LENGTH, {MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
54 {SQL_DESC_OCTET_LENGTH_PTR,{MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_NONE, MADB_DESC_NONE}},
55 {SQL_DESC_PARAMETER_TYPE,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_RW, MADB_DESC_NONE}},
56 {SQL_DESC_PRECISION,{MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
57 #if (ODBCVER >= 0x0350)
58 {SQL_DESC_ROWVER,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ, MADB_DESC_READ}},
59 #endif
60 {SQL_DESC_SCALE,{MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
61 {SQL_DESC_SCHEMA_NAME,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
62 {SQL_DESC_SEARCHABLE,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
63 {SQL_DESC_TABLE_NAME,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
64 {SQL_DESC_TYPE,{MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_RW, MADB_DESC_READ}},
65 {SQL_DESC_TYPE_NAME ,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ, MADB_DESC_READ}},
66 {SQL_DESC_UNSIGNED ,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ, MADB_DESC_READ}},
67 {SQL_DESC_UPDATABLE ,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_READ}},
68 {SQL_DESC_UNNAMED ,{MADB_DESC_NONE, MADB_DESC_NONE, MADB_DESC_RW, MADB_DESC_READ}},
69 {0, {0, 0, 0, 0}}
70 };
71
72 /* {{{ MADB_DescInit */
73 MADB_Desc *MADB_DescInit(MADB_Dbc *Dbc,enum enum_madb_desc_type DescType, my_bool isExternal)
74 {
75 MADB_Desc *Desc;
76
77 if (!(Desc= (MADB_Desc *)MADB_CALLOC(sizeof(MADB_Desc))))
78 return NULL;
79
80 Desc->DescType= DescType;
81 MADB_PutErrorPrefix(Dbc, &Desc->Error);
82
83 if (MADB_InitDynamicArray(&Desc->Records, sizeof(MADB_DescRecord), 0, MADB_DESC_INIT_REC_NUM))
84 {
85 MADB_FREE(Desc);
86 return NULL;
87 }
88 if (isExternal)
89 {
90 if (MADB_InitDynamicArray(&Desc->Stmts, sizeof(MADB_Stmt**), 0, MADB_DESC_INIT_STMT_NUM))
91 {
92 MADB_DescFree(Desc, FALSE);
93 return NULL;
94 }
95 else
96 {
97 Desc->Dbc= Dbc;
98 /* MADB_DescInit call for explicit descriptor is in critical section */
99 Desc->ListItem.data= (void *)Desc;
100 Dbc->Descrs= MADB_ListAdd(Dbc->Descrs, &Desc->ListItem);
101 }
102 }
103 Desc->AppType= isExternal;
104 Desc->Header.ArraySize= 1;
105
106 return Desc;
107 }
108 /* }}} */
109
110 /* {{{ MADB_DescFree */
111 SQLRETURN MADB_DescFree(MADB_Desc *Desc, my_bool RecordsOnly)
112 {
113 MADB_DescRecord *Record;
114 unsigned int i;
115
116 if (!Desc)
117 return SQL_ERROR;
118
119 /* We need to free internal pointers first */
120 for (i=0; i < Desc->Records.elements; i++)
121 {
122 Record= ((MADB_DescRecord *)Desc->Records.buffer) + i;
123 MADB_FREE(Record->InternalBuffer);
124 MADB_FREE(Record->DefaultValue);
125
126 if (Desc->DescType == MADB_DESC_IRD)
127 {
128 MADB_FREE(Record->CatalogName);
129 MADB_FREE(Record->BaseCatalogName);
130 MADB_FREE(Record->BaseColumnName);
131 MADB_FREE(Record->BaseTableName);
132 MADB_FREE(Record->ColumnName);
133 MADB_FREE(Record->TableName);
134 MADB_FREE(Record->TypeName);
135 }
136 else if(Desc->DescType == MADB_DESC_IPD)
137 {
138 MADB_FREE(Record->TypeName);
139 }
140 }
141 MADB_DeleteDynamic(&Desc->Records);
142
143 Desc->Header.Count= 0;
144
145 for (i=0; i < Desc->Stmts.elements; i++)
146 {
147 MADB_Stmt **XStmt= ((MADB_Stmt **)Desc->Stmts.buffer) + i;
148 MADB_Stmt *Stmt= *XStmt;
149 switch(Desc->DescType) {
150 case MADB_DESC_ARD:
151 Stmt->Ard=Stmt->IArd;
152 break;
153 case MADB_DESC_APD:
154 Stmt->Apd= Stmt->IApd;
155 break;
156 }
157 }
158 MADB_DeleteDynamic(&Desc->Stmts);
159 if (Desc->AppType)
160 {
161 Desc->Dbc->Descrs= MADB_ListDelete(Desc->Dbc->Stmts, &Desc->ListItem);
162 }
163 if (!RecordsOnly)
164 MADB_FREE(Desc);
165 return SQL_SUCCESS;
166 }
167 /* }}} */
168
169 /* {{{ MADB_SetIrdRecord */
170 my_bool
171 MADB_SetIrdRecord(MADB_Stmt *Stmt, MADB_DescRecord *Record, MYSQL_FIELD *Field)
172 {
173 if (Record == NULL)
174 {
175 return 1;
176 }
177
178 MADB_RESET(Record->CatalogName, Field->db);
179 MADB_RESET(Record->TableName, Field->table);
180 MADB_RESET(Record->ColumnName, Field->name);
181 MADB_RESET(Record->BaseTableName, Field->org_table);
182 MADB_RESET(Record->BaseColumnName, Field->org_name);
183 Record->AutoUniqueValue= (Field->flags & AUTO_INCREMENT_FLAG) ? SQL_TRUE : SQL_FALSE;
184 Record->CaseSensitive= (Field->flags & BINARY_FLAG) ? SQL_TRUE : SQL_FALSE;
185 Record->Nullable= ( (Field->flags & NOT_NULL_FLAG) &&
186 !Record->AutoUniqueValue &&
187 Field->type != MYSQL_TYPE_TIMESTAMP) ? SQL_NO_NULLS : SQL_NULLABLE;
188 Record->Unsigned= (Field->flags & UNSIGNED_FLAG) ? SQL_TRUE : SQL_FALSE;
189 /* We assume it might be updatable if tablename exists */
190 Record->Updateable= (Field->table && Field->table[0]) ? SQL_ATTR_READWRITE_UNKNOWN : SQL_ATTR_READONLY;
191
192 /*
193 RADIX:
194 If the data type in the SQL_DESC_TYPE field is an approximate numeric data type, this SQLINTEGER field
195 contains a value of 2 because the SQL_DESC_PRECISION field contains the number of bits.
196 If the data type in the SQL_DESC_TYPE field is an exact numeric data type, this field contains a value of 10
197 because the SQL_DESC_PRECISION field contains the number of decimal digits.
198 This field is set to 0 for all non-numeric data types.
199 */
200 switch (Field->type) {
201 case MYSQL_TYPE_DECIMAL:
202 case MYSQL_TYPE_NEWDECIMAL:
203 Record->NumPrecRadix= 10;
204 Record->Precision= (SQLSMALLINT)Field->length - 2;
205 Record->Scale= Field->decimals;
206 break;
207 case MYSQL_TYPE_FLOAT:
208 Record->NumPrecRadix= 2;
209 Record->Precision= (SQLSMALLINT)Field->length - 2;
210 //Record->Scale= Field->decimals;
211 break;
212 case MYSQL_TYPE_DOUBLE:
213 case MYSQL_TYPE_TINY:
214 case MYSQL_TYPE_SHORT:
215 case MYSQL_TYPE_INT24:
216 case MYSQL_TYPE_LONG:
217 case MYSQL_TYPE_LONGLONG:
218 case MYSQL_TYPE_YEAR:
219 Record->NumPrecRadix= 10;
220 break;
221 case MYSQL_TYPE_TIMESTAMP:
222 case MYSQL_TYPE_TIME:
223 case MYSQL_TYPE_DATETIME:
224 Record->Scale= Field->decimals;
225 default:
226 Record->NumPrecRadix= 0;
227 break;
228 }
229
230 Record->ConciseType= MapMariadDbToOdbcType(Field);
231 /*
232 TYPE:
233 For the datetime and interval data types, this field returns the verbose data type: SQL_DATETIME or SQL_INTERVAL.
234 */
235 Record->Type= (Record->ConciseType == SQL_TYPE_DATE || Record->ConciseType == SQL_DATE ||
236 Record->ConciseType == SQL_TYPE_TIME || Record->ConciseType == SQL_TIME ||
237 Record->ConciseType == SQL_TYPE_TIMESTAMP || Record->ConciseType == SQL_TIMESTAMP) ?
238 SQL_DATETIME : Record->ConciseType;
239
240 switch(Record->ConciseType) {
241 case SQL_TYPE_DATE:
242 Record->DateTimeIntervalCode= SQL_CODE_DATE;
243 break;
244 case SQL_TYPE_TIME:
245 Record->DateTimeIntervalCode= SQL_CODE_TIME;
246 break;
247 case SQL_TYPE_TIMESTAMP:
248 Record->DateTimeIntervalCode= SQL_CODE_TIMESTAMP;
249 break;
250 }
251 /*
252 SEARCHABLE:
253 Columns of type SQL_LONGVARCHAR and SQL_LONGVARBINARY usually return SQL_PRED_CHAR.
254 */
255 Record->Searchable= (Record->ConciseType == SQL_LONGVARCHAR ||
256 Record->ConciseType == SQL_WLONGVARCHAR ||
257 Record->ConciseType == SQL_LONGVARBINARY) ? SQL_PRED_CHAR : SQL_SEARCHABLE;
258
259 Record->DisplaySize= MADB_GetDisplaySize(Field, mariadb_get_charset_by_nr(Field->charsetnr));
260 Record->OctetLength= MADB_GetOctetLength(Field, Stmt->Connection->mariadb->charset->char_maxlen);
261 Record->Length= MADB_GetDataSize(Record->ConciseType, Field->length, Record->Unsigned == SQL_TRUE,
262 Record->Precision, Record->Scale, mariadb_get_charset_by_nr(Field->charsetnr));
263
264 MADB_RESET(Record->TypeName, MADB_GetTypeName(Field));
265
266 switch(Field->type) {
267 case MYSQL_TYPE_BLOB:
268 case MYSQL_TYPE_LONG_BLOB:
269 case MYSQL_TYPE_MEDIUM_BLOB:
270 case MYSQL_TYPE_STRING:
271 case MYSQL_TYPE_TINY_BLOB:
272 case MYSQL_TYPE_VAR_STRING:
273 if (Field->flags & BINARY_FLAG)
274 {
275 Record->LiteralPrefix= "0x";
276 Record->LiteralSuffix= "";
277 break;
278 }
279 /* else default */
280 case MYSQL_TYPE_DATE:
281 case MYSQL_TYPE_DATETIME:
282 case MYSQL_TYPE_NEWDATE:
283 case MYSQL_TYPE_TIME:
284 case MYSQL_TYPE_TIMESTAMP:
285 case MYSQL_TYPE_YEAR:
286 Record->LiteralPrefix="'";
287 Record->LiteralSuffix= "'";
288 break;
289 default:
290 Record->LiteralPrefix= "";
291 Record->LiteralSuffix= "";
292 break;
293 }
294
295 return 0;
296 }
297 /* }}} */
298
299 /* {{{ MADB_DescSetIrdMetadata */
300 my_bool
301 MADB_DescSetIrdMetadata(MADB_Stmt *Stmt, MYSQL_FIELD *Fields, unsigned int NumFields)
302 {
303 SQLSMALLINT i;
304
305 /* Perhaps we should call routine that does SQL_CLOSE here */
306 Stmt->Ird->Header.Count= 0;
307
308 for (i= 0; i < (SQLSMALLINT)NumFields; i++)
309 {
310 if (MADB_SetIrdRecord(Stmt, MADB_DescGetInternalRecord(Stmt->Ird, i, MADB_DESC_WRITE), &Fields[i]))
311 {
312 return 1;
313 }
314 }
315 return 0;
316 }
317 /* }}} */
318
319 /* {{{ MADB_FixOctetLength */
320 void MADB_FixOctetLength(MADB_DescRecord *Record)
321 {
322 switch (Record->ConciseType) {
323 case SQL_BIT:
324 case SQL_TINYINT:
325 Record->OctetLength= 1;
326 break;
327 case SQL_SMALLINT:
328 Record->OctetLength= 2;
329 break;
330 case SQL_INTEGER:
331 case SQL_REAL:
332 Record->OctetLength= 4;
333 break;
334 case SQL_BIGINT:
335 case SQL_DOUBLE:
336 Record->OctetLength= 8;
337 break;
338 case SQL_TYPE_DATE:
339 Record->OctetLength= sizeof(SQL_DATE_STRUCT);
340 break;
341 case SQL_TYPE_TIME:
342 Record->OctetLength= sizeof(SQL_TIME_STRUCT);
343 break;
344 case SQL_TYPE_TIMESTAMP:
345 Record->OctetLength= sizeof(SQL_TIMESTAMP_STRUCT);
346 break;
347 default:
348 Record->OctetLength= MIN(MADB_INT_MAX32, Record->OctetLength);
349 }
350 }
351 /* }}} */
352
353 /* {{{ MADB_FixDisplayLength */
354 void MADB_FixDisplaySize(MADB_DescRecord *Record, const MARIADB_CHARSET_INFO *charset)
355 {
356 switch (Record->ConciseType) {
357 case SQL_BIT:
358 Record->DisplaySize= 1;
359 break;
360 case SQL_TINYINT:
361 Record->DisplaySize= 4 - test(Record->Unsigned == SQL_TRUE);
362 break;
363 case SQL_SMALLINT:
364 Record->DisplaySize= 6 - test(Record->Unsigned == SQL_TRUE);
365 break;
366 case SQL_INTEGER:
367 Record->DisplaySize= 11 - test(Record->Unsigned == SQL_TRUE);
368 break;
369 case SQL_REAL:
370 Record->DisplaySize= 14;
371 break;
372 case SQL_BIGINT:
373 Record->DisplaySize= 20;
374 break;
375 case SQL_FLOAT:
376 case SQL_DOUBLE:
377 Record->DisplaySize= 24;
378 break;
379 case SQL_DECIMAL:
380 case SQL_NUMERIC:
381 Record->DisplaySize= Record->Precision + 2;
382 break;
383 case SQL_TYPE_DATE:
384 Record->DisplaySize= SQL_DATE_LEN;
385 break;
386 case SQL_TYPE_TIME:
387 Record->DisplaySize= SQL_TIME_LEN + MADB_FRACTIONAL_PART(Record->Scale);
388 break;
389 case SQL_TYPE_TIMESTAMP:
390 Record->DisplaySize= SQL_TIMESTAMP_LEN + MADB_FRACTIONAL_PART(Record->Scale);
391 break;
392 case SQL_BINARY:
393 case SQL_VARBINARY:
394 case SQL_LONGVARBINARY:
395 Record->DisplaySize=Record->OctetLength*2; /* For display in hex */
396 break;
397 case SQL_GUID:
398 Record->DisplaySize= 36;
399 break;
400 default:
401 if (charset == NULL || charset->char_maxlen < 2/*i.e.0||1*/)
402 {
403 Record->DisplaySize=Record->OctetLength;
404 }
405 else
406 {
407 Record->DisplaySize=Record->OctetLength/charset->char_maxlen;
408 }
409 }
410 }
411 /* }}} */
412
413 /* {{{ MADB_FixDataSize - aka Column size */
414 void MADB_FixDataSize(MADB_DescRecord *Record, const MARIADB_CHARSET_INFO *charset)
415 {
416 Record->Length= MADB_GetDataSize(Record->ConciseType, Record->OctetLength, Record->Unsigned == TRUE, Record->Precision, Record->Scale, charset );
417 }
418 /* }}} */
419
420 /* {{{ MADB_FixIrdRecord */
421 my_bool
422 MADB_FixIrdRecord(MADB_Stmt *Stmt, MADB_DescRecord *Record)
423 {
424 if (Record == NULL)
425 {
426 return 1;
427 }
428
429 MADB_FixOctetLength(Record);
430 /*
431 RADIX:
432 If the data type in the SQL_DESC_TYPE field is an approximate numeric data type, this SQLINTEGER field
433 contains a value of 2 because the SQL_DESC_PRECISION field contains the number of bits.
434 If the data type in the SQL_DESC_TYPE field is an exact numeric data type, this field contains a value of 10
435 because the SQL_DESC_PRECISION field contains the number of decimal digits.
436 This field is set to 0 for all non-numeric data types.
437 */
438 switch (Record->ConciseType) {
439 case SQL_DECIMAL:
440 Record->NumPrecRadix= 10;
441 Record->Precision= (SQLSMALLINT)Record->OctetLength - 2;
442 /*Record->Scale= Fields[i].decimals;*/
443 break;
444 case SQL_REAL:
445 /* Float*/
446 Record->NumPrecRadix= 2;
447 Record->Precision= (SQLSMALLINT)Record->OctetLength - 2;
448 break;
449 case SQL_DOUBLE:
450 case SQL_TINYINT:
451 case SQL_SMALLINT:
452 case SQL_INTEGER:
453 case SQL_BIGINT:
454 Record->NumPrecRadix= 10;
455 break;
456 default:
457 Record->NumPrecRadix= 0;
458 break;
459 }
460 /*
461 TYPE:
462 For the datetime and interval data types, this field returns the verbose data type: SQL_DATETIME or SQL_INTERVAL.
463 */
464 Record->Type= (Record->ConciseType == SQL_TYPE_DATE || Record->ConciseType == SQL_DATE ||
465 Record->ConciseType == SQL_TYPE_TIME || Record->ConciseType == SQL_TIME ||
466 Record->ConciseType == SQL_TYPE_TIMESTAMP || Record->ConciseType == SQL_TIMESTAMP) ?
467 SQL_DATETIME : Record->ConciseType;
468
469 switch(Record->ConciseType) {
470 case SQL_TYPE_DATE:
471 Record->DateTimeIntervalCode= SQL_CODE_DATE;
472 break;
473 case SQL_TYPE_TIME:
474 Record->DateTimeIntervalCode= SQL_CODE_TIME;
475 break;
476 case SQL_TYPE_TIMESTAMP:
477 Record->DateTimeIntervalCode= SQL_CODE_TIMESTAMP;
478 break;
479 }
480 /*
481 SEARCHABLE:
482 Columns of type SQL_LONGVARCHAR and SQL_LONGVARBINARY usually return SQL_PRED_CHAR.
483 */
484 Record->Searchable= (Record->ConciseType == SQL_LONGVARCHAR ||
485 Record->ConciseType == SQL_WLONGVARCHAR ||
486 Record->ConciseType == SQL_LONGVARBINARY) ? SQL_PRED_CHAR : SQL_SEARCHABLE;
487
488 MADB_FixDisplaySize(Record, Stmt->Connection->mariadb->charset);
489 MADB_FixDataSize(Record, Stmt->Connection->mariadb->charset);
490
491 /*Record->TypeName= strdup(MADB_GetTypeName(Fields[i]));*/
492
493 switch(Record->ConciseType) {
494 case SQL_BINARY:
495 case SQL_VARBINARY:
496 case SQL_LONGVARBINARY:
497 Record->LiteralPrefix= "0x";
498 Record->LiteralSuffix= "";
499 break;
500 /* else default */
501 case SQL_TYPE_DATE:
502 case SQL_TYPE_TIME:
503 case SQL_TYPE_TIMESTAMP:
504 Record->LiteralPrefix="'";
505 Record->LiteralSuffix= "'";
506 break;
507 default:
508 Record->LiteralPrefix= "";
509 Record->LiteralSuffix= "";
510 break;
511 }
512
513 return 0;
514 }
515 /* }}} */
516
517 /* {{{ MADB_FixColumnDataTypes */
518 my_bool
519 MADB_FixColumnDataTypes(MADB_Stmt *Stmt, MADB_ShortTypeInfo *ColTypesArr)
520 {
521 SQLSMALLINT i;
522 MADB_DescRecord *Record= NULL;
523
524 if (ColTypesArr == NULL)
525 {
526 return 1;
527 }
528 for (i=0; i < Stmt->Ird->Header.Count; ++i)
529 {
530 if (ColTypesArr[i].SqlType != 0)
531 {
532 Record= MADB_DescGetInternalRecord(Stmt->Ird, i, MADB_DESC_READ);
533
534 if (Record == NULL)
535 {
536 return 1;
537 }
538 Record->ConciseType= ColTypesArr[i].SqlType;
539 Record->Nullable= ColTypesArr[i].Nullable;
540
541 Record->Unsigned= ColTypesArr[i].Unsigned != 0 ? SQL_TRUE : SQL_FALSE;
542
543 if (ColTypesArr[i].OctetLength > 0)
544 {
545 Record->OctetLength= ColTypesArr[i].OctetLength;
546 }
547 if (MADB_FixIrdRecord(Stmt, Record))
548 {
549 return 1;
550 }
551 }
552 }
553
554 /* If the stmt is re-executed, we should be able to fix columns again */
555 Stmt->ColsTypeFixArr= ColTypesArr;
556 return 0;
557 }
558 /* }}} */
559
560 void MADB_DescSetRecordDefaults(MADB_Desc *Desc, MADB_DescRecord *Record)
561 {
562 memset(Record, 0, sizeof(MADB_DescRecord));
563
564 switch (Desc->DescType) {
565 case MADB_DESC_APD:
566 Record->ConciseType= Record->Type= SQL_C_DEFAULT;
567 break;
568 case MADB_DESC_ARD:
569 Record->ConciseType= Record->Type= SQL_C_DEFAULT;
570 break;
571 case MADB_DESC_IPD:
572 Record->FixedPrecScale= SQL_FALSE;
573 Record->LocalTypeName= "";
574 Record->Nullable= SQL_NULLABLE;
575 Record->ParameterType= SQL_PARAM_INPUT;
576 MADB_RESET(Record->TypeName, "VARCHAR");
577 Record->Unsigned= SQL_FALSE;
578 Record->ColumnName= "";
579 break;
580 case MADB_DESC_IRD:
581 Record->Nullable= SQL_NULLABLE_UNKNOWN;
582 Record->FixedPrecScale= SQL_FALSE;
583 Record->CaseSensitive= SQL_TRUE;
584 Record->ConciseType= SQL_VARCHAR;
585 Record->AutoUniqueValue= SQL_FALSE;
586 Record->Type= SQL_VARCHAR;
587 MADB_RESET(Record->TypeName, "VARCHAR");
588 Record->Unsigned= SQL_FALSE;
589 break;
590 }
591 }
592 /* }}} */
593
594 /* {{{ MADB_DescGetInternalRecord */
595 MADB_DescRecord *MADB_DescGetInternalRecord(MADB_Desc *Desc, SQLSMALLINT RecordNumber, SQLSMALLINT Type)
596 {
597 MADB_DescRecord *DescRecord;
598
599 if (RecordNumber > (SQLINTEGER)Desc->Records.elements &&
600 Type == MADB_DESC_READ)
601 {
602 MADB_SetError(&Desc->Error, MADB_ERR_07009, NULL, 0);
603 return NULL;
604 }
605
606 while (RecordNumber >= (SQLINTEGER)Desc->Records.elements)
607 {
608 if (!(DescRecord= (MADB_DescRecord *)MADB_AllocDynamic(&Desc->Records)))
609 {
610 MADB_SetError(&Desc->Error, MADB_ERR_HY001, NULL, 0);
611 return NULL;
612 }
613
614 MADB_DescSetRecordDefaults(Desc, DescRecord);
615 }
616
617 if (RecordNumber + 1 > Desc->Header.Count)
618 Desc->Header.Count= (SQLSMALLINT)(RecordNumber + 1);
619
620 DescRecord= ((MADB_DescRecord *)Desc->Records.buffer) + RecordNumber;
621
622 return DescRecord;
623 }
624 /* }}} */
625
626 /* {{{ MADB_DescCheckFldId */
627 SQLRETURN MADB_DeskCheckFldId(MADB_Desc *Desc, SQLSMALLINT FieldIdentifier, SQLSMALLINT mode)
628 {
629 int i= 0;
630
631 while (MADB_DESC_FLDID[i].FieldIdentifier &&
632 MADB_DESC_FLDID[i].FieldIdentifier != FieldIdentifier)
633 ++i;
634
635 /* End of list = invalid FieldIdentifier */
636 if (!MADB_DESC_FLDID[i].FieldIdentifier ||
637 !(MADB_DESC_FLDID[i].Access[Desc->DescType] & mode)) {
638 MADB_SetError(&Desc->Error, MADB_ERR_HY091, NULL, 0);
639 return SQL_ERROR;
640 }
641 return SQL_SUCCESS;
642 }
643 /* }}} */
644
645 /* {{{ MADB_DescGetField */
646 SQLRETURN MADB_DescGetField(SQLHDESC DescriptorHandle,
647 SQLSMALLINT RecNumber,
648 SQLSMALLINT FieldIdentifier,
649 SQLPOINTER ValuePtr,
650 SQLINTEGER BufferLength,
651 SQLINTEGER *StringLengthPtr,
652 my_bool isWChar)
653 {
654 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
655 MADB_DescRecord *DescRecord= NULL;
656 SQLRETURN ret;
657 size_t Length;
658
659 /* Bookmark */
660 if (RecNumber < 1)
661 {
662 /* todo */
663
664 }
665
666 ret= MADB_DeskCheckFldId(Desc, FieldIdentifier, MADB_DESC_READ);
667 if (!SQL_SUCCEEDED(ret))
668 return ret;
669
670 MADB_CLEAR_ERROR(&Desc->Error);
671
672 if (RecNumber)
673 if (!(DescRecord= MADB_DescGetInternalRecord(Desc, RecNumber - 1, MADB_DESC_READ)))
674 return SQL_ERROR;
675
676 switch (FieldIdentifier) {
677 case SQL_DESC_ALLOC_TYPE:
678 *((SQLINTEGER *)ValuePtr)= Desc->Header.AllocType;
679 break;
680 case SQL_DESC_ARRAY_SIZE:
681 *((SQLULEN *)ValuePtr)= Desc->Header.ArraySize;
682 break;
683 case SQL_DESC_ARRAY_STATUS_PTR:
684 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)Desc->Header.ArrayStatusPtr;
685 break;
686 case SQL_DESC_BIND_OFFSET_PTR:
687 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)Desc->Header.BindOffsetPtr;
688 break;
689 case SQL_DESC_BIND_TYPE:
690 *((SQLULEN *)ValuePtr)= Desc->Header.BindType;
691 break;
692 case SQL_DESC_COUNT:
693 *(SQLSMALLINT *)ValuePtr= Desc->Header.Count;
694 break;
695 case SQL_DESC_ROWS_PROCESSED_PTR:
696 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)Desc->Header.RowsProcessedPtr;
697 break;
698 case SQL_DESC_AUTO_UNIQUE_VALUE:
699 *((SQLINTEGER *)ValuePtr)= DescRecord->AutoUniqueValue;
700 break;
701 case SQL_DESC_BASE_COLUMN_NAME:
702 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->BaseColumnName, SQL_NTS, &Desc->Error);
703 if (StringLengthPtr)
704 *StringLengthPtr= (SQLINTEGER)Length;
705 break;
706 case SQL_DESC_BASE_TABLE_NAME:
707 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->BaseTableName, SQL_NTS, &Desc->Error);
708 if (StringLengthPtr)
709 *StringLengthPtr= (SQLINTEGER)Length;
710 break;
711 case SQL_DESC_CASE_SENSITIVE:
712 *((SQLINTEGER *)ValuePtr)= DescRecord->CaseSensitive;
713 break;
714 case SQL_DESC_CATALOG_NAME:
715 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->BaseCatalogName, SQL_NTS, &Desc->Error);
716 if (StringLengthPtr)
717 *StringLengthPtr= (SQLINTEGER)Length;
718 break;
719 case SQL_DESC_CONCISE_TYPE:
720 *((SQLSMALLINT *)ValuePtr)= DescRecord->ConciseType;
721 break;
722 case SQL_DESC_DATA_PTR:
723 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)DescRecord->DataPtr;
724 break;
725 case SQL_DESC_DATETIME_INTERVAL_CODE:
726 *((SQLSMALLINT *)ValuePtr)= DescRecord->DateTimeIntervalCode;
727 break;
728 case SQL_DESC_DATETIME_INTERVAL_PRECISION:
729 *((SQLINTEGER *)ValuePtr)= DescRecord->DateTimeIntervalPrecision;
730 break;
731 case SQL_DESC_FIXED_PREC_SCALE:
732 *((SQLSMALLINT *)ValuePtr)= DescRecord->FixedPrecScale;
733 break;
734 case SQL_DESC_INDICATOR_PTR:
735 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)DescRecord->IndicatorPtr;
736 break;
737 case SQL_DESC_LENGTH:
738 *((SQLINTEGER *)ValuePtr)= DescRecord->DescLength;
739 break;
740 case SQL_DESC_LITERAL_PREFIX:
741 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)DescRecord->LiteralPrefix;
742 break;
743 case SQL_DESC_LITERAL_SUFFIX:
744 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)DescRecord->LiteralSuffix;
745 break;
746 case SQL_DESC_LOCAL_TYPE_NAME:
747 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->LocalTypeName, SQL_NTS, &Desc->Error);
748 if (StringLengthPtr)
749 *StringLengthPtr= (SQLINTEGER)Length;
750 break;
751 case SQL_DESC_NAME:
752 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->BaseColumnName, SQL_NTS, &Desc->Error);
753 if (StringLengthPtr)
754 *StringLengthPtr= (SQLINTEGER)Length;
755 DescRecord->Unnamed= SQL_NAMED;
756 break;
757 case SQL_DESC_NULLABLE:
758 *((SQLINTEGER *)ValuePtr)= DescRecord->Nullable;
759 break;
760 case SQL_DESC_NUM_PREC_RADIX:
761 *((SQLINTEGER *)ValuePtr)= DescRecord->NumPrecRadix;
762 break;
763 case SQL_DESC_OCTET_LENGTH:
764 *((SQLLEN *)ValuePtr)= DescRecord->OctetLength;
765 break;
766 case SQL_DESC_OCTET_LENGTH_PTR:
767 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)DescRecord->OctetLengthPtr;
768 break;
769 case SQL_DESC_PARAMETER_TYPE:
770 *((SQLSMALLINT *)ValuePtr)= DescRecord->ParameterType;
771 break;
772 case SQL_DESC_PRECISION:
773 *((SQLINTEGER *)ValuePtr)= DescRecord->Precision;
774 break;
775 #if (ODBCVER >= 0x0350)
776 case SQL_DESC_ROWVER:
777 *((SQLPOINTER *)ValuePtr)= (SQLPOINTER)(SQLULEN)DescRecord->RowVer;
778 break;
779 #endif
780 case SQL_DESC_SCALE:
781 *((SQLINTEGER *)ValuePtr)= DescRecord->Scale;
782 break;
783 case SQL_DESC_SCHEMA_NAME:
784 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->SchemaName, SQL_NTS, &Desc->Error);
785 if (StringLengthPtr)
786 *StringLengthPtr= (SQLINTEGER)Length;
787 break;
788 case SQL_DESC_SEARCHABLE:
789 *((SQLINTEGER *)ValuePtr)= DescRecord->Searchable;
790 break;
791 case SQL_DESC_TABLE_NAME:
792 Length= MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->TableName, SQL_NTS, &Desc->Error);
793 if (StringLengthPtr)
794 *StringLengthPtr= (SQLINTEGER)Length;
795 break;
796 case SQL_DESC_TYPE:
797 *((SQLINTEGER *)ValuePtr)= DescRecord->Type;
798 break;
799 case SQL_DESC_TYPE_NAME:
800 *StringLengthPtr= (SQLINTEGER)MADB_SetString(isWChar ? &utf8 : 0, ValuePtr, BufferLength, DescRecord->TypeName, SQL_NTS, &Desc->Error);
801 break;
802 case SQL_DESC_UNSIGNED:
803 *((SQLINTEGER *)ValuePtr)= DescRecord->Unsigned;
804 break;
805 case SQL_DESC_UPDATABLE:
806 *((SQLINTEGER *)ValuePtr)= DescRecord->Updateable;
807 break;
808 }
809 return ret;
810 }
811
812 /* {{{ MADB_DescSetField */
813 SQLRETURN MADB_DescSetField(SQLHDESC DescriptorHandle,
814 SQLSMALLINT RecNumber,
815 SQLSMALLINT FieldIdentifier,
816 SQLPOINTER ValuePtr,
817 SQLINTEGER BufferLength,
818 my_bool isWChar)
819 {
820 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
821 MADB_DescRecord *DescRecord= NULL;
822 SQLRETURN ret;
823 SQL_UNNAMED;
824 ret= MADB_DeskCheckFldId(Desc, FieldIdentifier, MADB_DESC_WRITE);
825
826 /* Application may set IPD's field SQL_DESC_UNNAMED to SQL_UNNAMED only */
827 if (FieldIdentifier == SQL_DESC_UNNAMED && (SQLSMALLINT)(SQLULEN)ValuePtr == SQL_NAMED)
828 {
829 MADB_SetError(&Desc->Error, MADB_ERR_HY092, NULL, 0);
830 ret= Desc->Error.ReturnValue;
831 }
832
833 if (!SQL_SUCCEEDED(ret))
834 return ret;
835
836 MADB_CLEAR_ERROR(&Desc->Error);
837 switch (FieldIdentifier) {
838 case SQL_DESC_ARRAY_SIZE:
839 Desc->Header.ArraySize= (SQLULEN)ValuePtr;
840 return SQL_SUCCESS;
841 case SQL_DESC_ARRAY_STATUS_PTR:
842 Desc->Header.ArrayStatusPtr= (SQLUSMALLINT *)ValuePtr;
843 return SQL_SUCCESS;
844 case SQL_DESC_BIND_OFFSET_PTR:
845 Desc->Header.BindOffsetPtr= (SQLULEN *)ValuePtr;
846 return SQL_SUCCESS;
847 case SQL_DESC_BIND_TYPE:
848 Desc->Header.BindType= (SQLINTEGER)(SQLLEN)ValuePtr;
849 return SQL_SUCCESS;
850 case SQL_DESC_COUNT:
851 Desc->Header.Count= (SQLSMALLINT)(SQLLEN)ValuePtr;
852 return SQL_SUCCESS;
853 case SQL_DESC_ROWS_PROCESSED_PTR:
854 Desc->Header.RowsProcessedPtr= (SQLULEN *)ValuePtr;
855 return SQL_SUCCESS;
856 }
857
858 if (RecNumber > 0)
859 {
860 if (!(DescRecord= MADB_DescGetInternalRecord(Desc, RecNumber - 1, MADB_DESC_WRITE)))
861 return SQL_ERROR;
862
863 switch (FieldIdentifier) {
864 case SQL_DESC_CONCISE_TYPE:
865 DescRecord->ConciseType= (SQLSMALLINT)(SQLLEN)ValuePtr;
866 DescRecord->Type= MADB_GetTypeFromConciseType(DescRecord->ConciseType);
867 if (DescRecord->Type == SQL_INTERVAL)
868 {
869 DescRecord->DateTimeIntervalCode= DescRecord->ConciseType - 100;
870 }
871 break;
872 case SQL_DESC_DATA_PTR:
873 DescRecord->DataPtr= ValuePtr;
874 break;
875 case SQL_DESC_DATETIME_INTERVAL_CODE:
876 DescRecord->DateTimeIntervalCode= (SQLSMALLINT)(SQLLEN)ValuePtr;
877 break;
878 case SQL_DESC_DATETIME_INTERVAL_PRECISION:
879 DescRecord->DateTimeIntervalPrecision= (SQLINTEGER)(SQLLEN)ValuePtr;
880 break;
881 case SQL_DESC_FIXED_PREC_SCALE:
882 DescRecord->FixedPrecScale= (SQLSMALLINT)(SQLLEN)ValuePtr;
883 break;
884 case SQL_DESC_INDICATOR_PTR:
885 DescRecord->IndicatorPtr= (SQLLEN *)ValuePtr;
886 break;
887 case SQL_DESC_LENGTH:
888 DescRecord->DescLength= (SQLINTEGER)(SQLLEN)ValuePtr;
889 break;
890 case SQL_DESC_NUM_PREC_RADIX:
891 DescRecord->NumPrecRadix= (SQLINTEGER)(SQLLEN)ValuePtr;
892 break;
893 case SQL_DESC_OCTET_LENGTH:
894 DescRecord->OctetLength= (SQLLEN)ValuePtr;
895 break;
896 case SQL_DESC_OCTET_LENGTH_PTR:
897 DescRecord->OctetLengthPtr= (SQLLEN *)ValuePtr;
898 break;
899 case SQL_DESC_PARAMETER_TYPE:
900 DescRecord->ParameterType= (SQLSMALLINT)(SQLLEN)ValuePtr;
901 break;
902 case SQL_DESC_PRECISION:
903 DescRecord->Precision= (SQLSMALLINT)(SQLLEN)ValuePtr;
904 break;
905 case SQL_DESC_SCALE:
906 DescRecord->Scale= (SQLSMALLINT)(SQLLEN)ValuePtr;
907 break;
908 case SQL_DESC_TYPE:
909 DescRecord->Type= (SQLSMALLINT)(SQLLEN)ValuePtr;
910 DescRecord->ConciseType= DescRecord->Type;
911 break;
912 }
913 /* bug41018 (ma_desc.c):
914 We need to unbind in case parameter doesn't set a buffer or header field */
915 switch (FieldIdentifier)
916 {
917 case SQL_DESC_DATA_PTR:
918 case SQL_DESC_OCTET_LENGTH_PTR:
919 case SQL_DESC_INDICATOR_PTR:
920 break;
921 default:
922 if (Desc->DescType== MADB_DESC_ARD && DescRecord && DescRecord->DataPtr)
923 DescRecord->DataPtr= NULL;
924 break;
925 }
926
927 /* inUse is only used to check if column/parameter was bound or not. Thus we do not set it for each field, but only for those,
928 that make column/parameter "bound" */
929 if (DescRecord && (DescRecord->DataPtr != NULL || DescRecord->OctetLengthPtr != NULL || DescRecord->IndicatorPtr != NULL))
930 DescRecord->inUse= 1;
931 }
932 return ret;
933 }
934 /* }}} */
935
936 /* {{{ MADB_DescCopyDesc */
937 SQLRETURN MADB_DescCopyDesc(MADB_Desc *SrcDesc, MADB_Desc *DestDesc)
938 {
939 if (!SrcDesc)
940 return SQL_INVALID_HANDLE;
941
942 if (DestDesc->DescType == MADB_DESC_IRD)
943 {
944 MADB_SetError(&DestDesc->Error, MADB_ERR_HY016, NULL, 0);
945 return SQL_ERROR;
946 }
947 if (SrcDesc->DescType == MADB_DESC_IRD && !SrcDesc->Header.Count)
948 {
949 MADB_SetError(&DestDesc->Error, MADB_ERR_HY007, NULL, 0);
950 return SQL_ERROR;
951 }
952 /* make sure there aren't old records */
953 MADB_DeleteDynamic(&DestDesc->Records);
954 if (MADB_InitDynamicArray(&DestDesc->Records, sizeof(MADB_DescRecord),
955 SrcDesc->Records.max_element, SrcDesc->Records.alloc_increment))
956 {
957 MADB_SetError(&DestDesc->Error, MADB_ERR_HY001, NULL, 0);
958 return SQL_ERROR;
959 }
960
961 memcpy(&DestDesc->Header, &SrcDesc->Header, sizeof(MADB_Header));
962
963 /* We don't copy AppType from Src to Dest. If we copy internal descriptor to the explicit/external, it stays explicit/external */
964
965 DestDesc->DescType= SrcDesc->DescType;
966 memcpy(&DestDesc->Error, &SrcDesc->Error, sizeof(MADB_Error));
967
968 /* Since we never allocate pointers we can just copy content */
969 memcpy(DestDesc->Records.buffer, SrcDesc->Records.buffer,
970 SrcDesc->Records.size_of_element * SrcDesc->Records.max_element);
971 DestDesc->Records.elements= SrcDesc->Records.elements;
972
973 /* internal buffer needs to be clearead or we will get it freed twice with all nice subsequences */
974 {
975 unsigned int i;
976
977 for (i= 0; i < DestDesc->Records.elements; ++i)
978 {
979 MADB_DescRecord *Rec= MADB_DescGetInternalRecord(DestDesc, i, MADB_DESC_READ);
980
981 if (Rec != NULL)
982 {
983 Rec->InternalBuffer= NULL;
984 }
985 }
986 }
987
988 return SQL_SUCCESS;
989 }
990 /* }}} */
991
992 SQLRETURN MADB_DescGetRec(MADB_Desc *Desc,
993 SQLSMALLINT RecNumber,
994 SQLCHAR *Name,
995 SQLSMALLINT BufferLength,
996 SQLSMALLINT *StringLengthPtr,
997 SQLSMALLINT *TypePtr,
998 SQLSMALLINT *SubTypePtr,
999 SQLLEN *LengthPtr,
1000 SQLSMALLINT *PrecisionPtr,
1001 SQLSMALLINT *ScalePtr,
1002 SQLSMALLINT *NullablePtr,
1003 BOOL isWChar)
1004 {
1005 MADB_DescRecord *Record;
1006 SQLLEN Length;
1007
1008 MADB_CLEAR_ERROR(&Desc->Error);
1009
1010 if (!(Record= MADB_DescGetInternalRecord(Desc, RecNumber, MADB_DESC_READ)))
1011 {
1012 MADB_SetError(&Desc->Error, MADB_ERR_07009, NULL, 0);
1013 return Desc->Error.ReturnValue;
1014 }
1015
1016 /* SQL_DESC_NAME */
1017 Length= MADB_SetString(isWChar ? &utf8 : 0, Name, BufferLength, Record->BaseColumnName, SQL_NTS, &Desc->Error);
1018 if (StringLengthPtr)
1019 *StringLengthPtr= (SQLSMALLINT)Length;
1020 Record->Unnamed= SQL_NAMED;
1021
1022 /* SQL_DESC_TYPE */
1023 *(SQLSMALLINT *)TypePtr= (SQLSMALLINT)Record->Type;
1024
1025 /* SQL_DESC_DATETIME_INTERVAL_CODE */
1026 *(SQLSMALLINT *)SubTypePtr= Record->DateTimeIntervalCode;
1027
1028 /* SQL_DESC_OCTET_LENGTH */
1029 *(SQLLEN *)LengthPtr= (SQLLEN)Record->OctetLength;
1030
1031 /* SQL_DESC_PRECISION */
1032 *(SQLSMALLINT *)PrecisionPtr= (SQLSMALLINT)Record->Precision;
1033
1034 /* SQL_DESC_SCALE */
1035 *(SQLSMALLINT *)ScalePtr= (SQLSMALLINT)Record->Scale;
1036
1037 /* SQL_DESC_NULLABLE */
1038 *(SQLSMALLINT *)NullablePtr= (SQLSMALLINT)Record->Nullable;
1039
1040 return SQL_SUCCESS;
1041 }
1042
0 /************************************************************************************
1 Copyright (C) 2013,2015 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_desc_h_
19 #define _ma_desc_h_
20
21 #define MADB_DESC_NONE 0
22 #define MADB_DESC_READ 1
23 #define MADB_DESC_WRITE 2
24 #define MADB_DESC_RW 3
25
26 #define MADB_DESC_INIT_REC_NUM 32
27 #define MADB_DESC_INIT_STMT_NUM 16
28
29 enum enum_madb_desc_type {MADB_DESC_APD= 0, MADB_DESC_ARD, MADB_DESC_IPD, MADB_DESC_IRD, MADB_DESC_UNKNOWN=254};
30
31 MADB_DescRecord *MADB_DescGetInternalRecord(MADB_Desc *Desc, SQLSMALLINT RecordNumber, SQLSMALLINT Type);
32
33 MADB_Desc *MADB_DescInit(MADB_Dbc *Dbc, enum enum_madb_desc_type DescType, my_bool isExternal);
34 SQLRETURN MADB_DescFree(MADB_Desc *Desc, my_bool RecordsOnly);
35 SQLRETURN MADB_DescGetField(SQLHDESC DescriptorHandle,
36 SQLSMALLINT RecNumber,
37 SQLSMALLINT FieldIdentifier,
38 SQLPOINTER ValuePtr,
39 SQLINTEGER BufferLength,
40 SQLINTEGER *StringLengthPtr,
41 my_bool isWChar);
42 SQLRETURN MADB_DescSetField(SQLHDESC DescriptorHandle,
43 SQLSMALLINT RecNumber,
44 SQLSMALLINT FieldIdentifier,
45 SQLPOINTER ValuePtr,
46 SQLINTEGER BufferLength,
47 my_bool isWChar);
48
49 my_bool MADB_DescSetIrdMetadata(MADB_Stmt *Stmt, MYSQL_FIELD *Fields, unsigned int NumFields);
50 SQLRETURN MADB_DescCopyDesc(MADB_Desc *SrcDesc, MADB_Desc *DestDesc);
51 SQLRETURN MADB_DescGetRec(MADB_Desc *Desc,
52 SQLSMALLINT RecNumber,
53 SQLCHAR *Name,
54 SQLSMALLINT BufferLength,
55 SQLSMALLINT *StringLengthPtr,
56 SQLSMALLINT *TypePtr,
57 SQLSMALLINT *SubTypePtr,
58 SQLLEN *LengthPtr,
59 SQLSMALLINT *PrecisionPtr,
60 SQLSMALLINT *ScalePtr,
61 SQLSMALLINT *NullablePtr,
62 BOOL isWChar);
63
64 my_bool MADB_FixColumnDataTypes(MADB_Stmt *Stmt, MADB_ShortTypeInfo *ColTypesArr);
65
66 #endif /* _ma_desc_h_ */
0 /************************************************************************************
1 Copyright (C) 2013,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 BOOL __stdcall DllMain ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
21 {
22 switch (fdwReason) {
23 case DLL_PROCESS_ATTACH:
24 mysql_library_init(0, NULL, NULL);
25 break;
26 case DLL_PROCESS_DETACH:
27 mysql_library_end();
28 break;
29 case DLL_THREAD_ATTACH:
30 mysql_thread_init();
31 break;
32 case DLL_THREAD_DETACH:
33 mysql_thread_end();
34 break;
35 }
36 return TRUE;
37 }
38
0 /************************************************************************************
1 Copyright (C) 2013 SkySQL AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 /* {{{ MADB_DriverInit */
21 MADB_Drv *MADB_DriverInit(void)
22 {
23 return (MADB_Drv* )MADB_CALLOC(sizeof(MADB_Drv));
24 }
25
26 void MADB_DriverFree(MADB_Drv *Drv)
27 {
28 if (Drv)
29 {
30 MADB_FREE(Drv->DriverName);
31 MADB_FREE(Drv->OdbcLibrary);
32 MADB_FREE(Drv->SetupLibrary);
33 MADB_FREE(Drv);
34 }
35 }
36
37 /* {{{ MADB_DriverGet */
38 MADB_Drv * MADB_DriverGet(char *DriverName)
39 {
40 MADB_Drv *Drv= NULL;
41 char Value[2048];
42
43 if (!DriverName ||
44 !SQLGetPrivateProfileString(DriverName, "Driver", "", Value, 2048, "ODBCINST.INI"))
45 return NULL;
46 Drv= MADB_DriverInit();
47 Drv->DriverName= _strdup(DriverName);
48 Drv->OdbcLibrary= _strdup(Value);
49 if (SQLGetPrivateProfileString(DriverName, "Setup", "", Value, 2048, "ODBCINST.INI"))
50 Drv->SetupLibrary= _strdup(Value);
51 return Drv;
52 }
0 /***********************************************************************
1 Copyright (c) 2013 Monty Program Ab;
2 Copyright (c) 2013 Georg Richter
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
6 met:
7
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must the following disclaimer in
12 the documentation and/or other materials provided with the
13 distribution.
14
15 THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
16 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
19 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 SUCH DAMAGE.
27 ************************************************************************/
28
29 #ifndef _ma_driver_h_
30 #define _ma_driver_h_
31
32 typedef struct {
33 char *DriverName;
34 char *OdbcLibrary;
35 char *SetupLibrary;
36 } MADB_Drv;
37
38 MADB_Drv * MADB_DriverGet(char *DriverName);
39 void MADB_DriverFree(MADB_Drv *Drv);
40 MADB_Drv *MADB_DriverInit(void);
41
42 #endif /* _ma_driver_h_ */
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20
21 #define DSNKEY_OPTIONS_INDEX 3
22 #define DSNKEY_OPTION_INDEX 4
23 #define DSNKEY_NAMEDPIPE_INDEX 5
24 #define DSNKEY_TCPIP_INDEX 6
25 #define DSNKEY_SERVER_INDEX 7
26 #define DSNKEY_UID_INDEX 8
27 #define DSNKEY_PWD_INDEX 9
28 #define DSNKEY_DATABASE_INDEX 10
29
30 MADB_DsnKey DsnKeys[]=
31 {
32 {"DSN", offsetof(MADB_Dsn, DSNName), DSN_TYPE_STRING, 0, 0}, /* 0 */
33 {"DESCRIPTION", offsetof(MADB_Dsn, Description), DSN_TYPE_STRING, 0, 0},
34 {"DRIVER", offsetof(MADB_Dsn, Driver), DSN_TYPE_STRING, 0, 0},
35 /* OPTIONS should go above all DSN_TYPE_OPTION. They are not saved in DSN separately, and then DSN is read, corresponding
36 properties are filled from OPTIONS. Also putting its alias here - it should not appear on Windows(unless somebody edits
37 registry manually), but on *nix we can expect everything. Array index used in some places to decide if the key is OPTIONS */
38 {"OPTIONS", offsetof(MADB_Dsn, Options), DSN_TYPE_INT, 0, 0}, /* DSNKEY_OPTIONS_INDEX */
39 {"OPTION", DSNKEY_OPTIONS_INDEX, DSN_TYPE_INT, 0, 1}, /* DSNKEY_OPTION_INDEX */
40
41 {"NamedPipe", offsetof(MADB_Dsn, IsNamedPipe), DSN_TYPE_OPTION, MADB_OPT_FLAG_NAMED_PIPE, 0}, /* MADB_DSNKEY_NAMEDPIPE_INDEX */
42 {"TCPIP", offsetof(MADB_Dsn, IsTcpIp), DSN_TYPE_BOOL, 0, 0}, /* DSNKEY_TCPIP_INDEX */
43 {"SERVER", offsetof(MADB_Dsn, ServerName), DSN_TYPE_STRING, 0, 0}, /* DSNKEY_SERVER_INDEX */
44 {"UID", offsetof(MADB_Dsn, UserName), DSN_TYPE_STRING, 0, 0}, /* DSNKEY_UID_INDEX */
45 {"PWD", offsetof(MADB_Dsn, Password), DSN_TYPE_STRING, 0, 0}, /* DSNKEY_PWD_INDEX */
46 {"DATABASE", offsetof(MADB_Dsn, Catalog), DSN_TYPE_COMBO, 0, 0}, /* 10 DSNKEY_DATABASE_INDEX */
47 {"PORT", offsetof(MADB_Dsn, Port), DSN_TYPE_INT, 0, 0},
48 {"INITSTMT", offsetof(MADB_Dsn, InitCommand), DSN_TYPE_STRING, 0, 0},
49 {"CONN_TIMEOUT", offsetof(MADB_Dsn, ConnectionTimeout), DSN_TYPE_INT, 0, 0},
50 {"AUTO_RECONNECT", offsetof(MADB_Dsn, Reconnect), DSN_TYPE_OPTION, MADB_OPT_FLAG_AUTO_RECONNECT,0},
51 {"NO_PROMPT", offsetof(MADB_Dsn, ConnectPrompt), DSN_TYPE_OPTION, MADB_OPT_FLAG_NO_PROMPT,0},
52 {"CHARSET", offsetof(MADB_Dsn, CharacterSet), DSN_TYPE_COMBO, 0, 0},
53 {"TRACE", offsetof(MADB_Dsn, TraceFile), DSN_TYPE_STRING, 0, 0},
54 {"PLUGIN_DIR", offsetof(MADB_Dsn, ConnCPluginsDir), DSN_TYPE_STRING, 0, 0},
55 /* SSL */
56 {"SSLKEY", offsetof(MADB_Dsn, SslKey), DSN_TYPE_STRING, 0, 0},
57 {"SSLCERT", offsetof(MADB_Dsn, SslCert), DSN_TYPE_STRING, 0, 0}, /* 20 */
58 {"SSLCA", offsetof(MADB_Dsn, SslCa), DSN_TYPE_STRING, 0, 0},
59 {"SSLCAPATH", offsetof(MADB_Dsn, SslCaPath), DSN_TYPE_STRING, 0, 0},
60 {"SSLCIPHER", offsetof(MADB_Dsn, SslCipher), DSN_TYPE_STRING, 0, 0},
61 {"SSLVERIFY", offsetof(MADB_Dsn, SslVerify), DSN_TYPE_BOOL, 0, 0},
62 {"SSLFP", offsetof(MADB_Dsn, SslFp), DSN_TYPE_STRING, 0, 0},
63 {"SSLFPLIST", offsetof(MADB_Dsn, SslFpList), DSN_TYPE_STRING, 0, 0},
64 {"SSLCRL", offsetof(MADB_Dsn, SslCrl), DSN_TYPE_STRING, 0, 0},
65 {"SSLCRLPATH", offsetof(MADB_Dsn, SslCrlPath), DSN_TYPE_STRING, 0, 0},
66 {"SOCKET", offsetof(MADB_Dsn, Socket), DSN_TYPE_STRING, 0, 0},
67 {"SAVEFILE", offsetof(MADB_Dsn, SaveFile), DSN_TYPE_STRING, 0, 0}, /* 30 */
68 {"USE_MYCNF", offsetof(MADB_Dsn, ReadMycnf), DSN_TYPE_OPTION, MADB_OPT_FLAG_USE_CNF, 0},
69 {"TLSVERSION", offsetof(MADB_Dsn, TlsVersion), DSN_TYPE_CBOXGROUP, 0, 0},
70 {"FORCETLS", offsetof(MADB_Dsn, ForceTls), DSN_TYPE_BOOL, 0, 0},
71 /* Aliases. Here offset is index of aliased key */
72 {"SERVERNAME", DSNKEY_SERVER_INDEX, DSN_TYPE_STRING, 0, 1},
73 {"USER", DSNKEY_UID_INDEX, DSN_TYPE_STRING, 0, 1},
74 {"PASSWORD", DSNKEY_PWD_INDEX, DSN_TYPE_STRING, 0, 1},
75 {"DB", DSNKEY_DATABASE_INDEX, DSN_TYPE_COMBO, 0, 1},
76
77 /* Terminating Null */
78 {NULL, 0, DSN_TYPE_BOOL,0,0}
79 };
80
81 /* TODO: Shouln't 2nd be DSNKEY_OPTIONS_INDEX? But I seemed to remember it was removed for a reason... */
82 #define IS_OPTIONS_BITMAP(key_index) (key_index == DSNKEY_OPTIONS_INDEX || key_index == DSNKEY_OPTIONS_INDEX)
83
84 typedef struct
85 {
86 unsigned int Key;
87 unsigned int Dependent;
88 BOOL Same; /* Should dependent be switched same way, or in reverse */
89 } MADB_DsnKeyDep;
90
91 /* Define pairs of keys that are switches, i.e. setting one should reset the other.
92 Transitive dependencies have to be defined as direct dependencies here as well */
93 const MADB_DsnKeyDep DsnKeysSwitch[]=
94 {
95 {DSNKEY_NAMEDPIPE_INDEX, DSNKEY_TCPIP_INDEX, 0},
96 {DSNKEY_TCPIP_INDEX, DSNKEY_NAMEDPIPE_INDEX, 0}
97 };
98
99 const char TlsVersionName[][8]= {"TLSv1.1", "TLSv1.2", "TLSv1.3"};
100 const char TlsVersionBits[]= {MADB_TLSV11, MADB_TLSV12, MADB_TLSV13};
101
102 /* {{{ MADB_DSN_SetDefaults() */
103 void MADB_DSN_SetDefaults(MADB_Dsn *Dsn)
104 {
105 Dsn->IsTcpIp= 1;
106 }
107 /* }}} */
108
109 /* {{{ MADB_Dsn_Init() */
110 MADB_Dsn *MADB_DSN_Init()
111 {
112 MADB_Dsn *Dsn;
113
114 if ((Dsn= (MADB_Dsn *)MADB_CALLOC(sizeof(MADB_Dsn))))
115 {
116 Dsn->FreeMe= TRUE;
117 Dsn->Keys= (MADB_DsnKey *)&DsnKeys;
118 }
119 return Dsn;
120 }
121 /* }}} */
122
123 /* {{{ MADB_Dsn_Free */
124 void MADB_DSN_Free(MADB_Dsn *Dsn)
125 {
126 if (!Dsn)
127 return;
128
129 MADB_FREE(Dsn->DSNName);
130 MADB_FREE(Dsn->Driver);
131 MADB_FREE(Dsn->Description);
132 MADB_FREE(Dsn->ServerName);
133 MADB_FREE(Dsn->UserName);
134 MADB_FREE(Dsn->Password);
135 MADB_FREE(Dsn->Catalog);
136 MADB_FREE(Dsn->CharacterSet);
137 MADB_FREE(Dsn->InitCommand);
138 MADB_FREE(Dsn->TraceFile);
139 MADB_FREE(Dsn->Socket);
140 MADB_FREE(Dsn->ConnCPluginsDir);
141 MADB_FREE(Dsn->SslKey);
142 MADB_FREE(Dsn->SslCert);
143 MADB_FREE(Dsn->SslCa);
144 MADB_FREE(Dsn->SslCaPath);
145 MADB_FREE(Dsn->SslCipher);
146 MADB_FREE(Dsn->SslCrl);
147 MADB_FREE(Dsn->SslCrlPath);
148 MADB_FREE(Dsn->SslFp);
149 MADB_FREE(Dsn->SslFpList);
150 MADB_FREE(Dsn->SaveFile);
151
152 if (Dsn->FreeMe)
153 MADB_FREE(Dsn);
154 }
155 /* }}} */
156
157
158 void MADB_SetOptionValue(MADB_Dsn *Dsn, MADB_DsnKey *DsnKey, my_bool value)
159 {
160 *GET_FIELD_PTR(Dsn, DsnKey, my_bool)= value;
161 if (value)
162 {
163 Dsn->Options |= DsnKey->FlagValue;
164 }
165 else
166 {
167 Dsn->Options &= ~DsnKey->FlagValue;
168 }
169 }
170
171
172 my_bool MADB_DsnStoreValue(MADB_Dsn *Dsn, unsigned int DsnKeyIdx, char *Value, my_bool OverWrite);
173
174 /* {{{ MADB_DsnSwitchDependents */
175 /* If TCPIP selected, we have to reset NAMEDPIPE */
176 BOOL MADB_DsnSwitchDependents(MADB_Dsn *Dsn, unsigned int Changed)
177 {
178 int i;
179
180 for (i= 0; i < sizeof(DsnKeysSwitch)/sizeof(MADB_DsnKeyDep); ++i)
181 {
182 if (DsnKeysSwitch[i].Key == Changed)
183 {
184 my_bool KeySet;
185
186 switch (DsnKeys[Changed].Type)
187 {
188 case DSN_TYPE_STRING:
189 case DSN_TYPE_COMBO:
190 {
191 char *str= *GET_FIELD_PTR(Dsn, &DsnKeys[Changed], char*);
192 KeySet= str && *str;
193 }
194 break;
195 case DSN_TYPE_OPTION:
196 case DSN_TYPE_BOOL:
197 case DSN_TYPE_CBOXGROUP:
198 {
199 KeySet= *GET_FIELD_PTR(Dsn, &DsnKeys[Changed], my_bool);
200 }
201 break;
202 case DSN_TYPE_INT:
203 {
204 KeySet= *GET_FIELD_PTR(Dsn, &DsnKeys[Changed], int) != 0;
205 }
206 }
207
208 /* No problem to deal with aliases here as well, but let's keep things simple */
209 if (DsnKeys[DsnKeysSwitch[i].Dependent].IsAlias != 0)
210 {
211 return FALSE;
212 }
213
214 switch(DsnKeys[DsnKeysSwitch[i].Dependent].Type)
215 {
216 case DSN_TYPE_BOOL:
217 *GET_FIELD_PTR(Dsn, &DsnKeys[DsnKeysSwitch[i].Dependent], my_bool)= DsnKeysSwitch[i].Same == KeySet ? 1 : 0;
218 break;
219 case DSN_TYPE_OPTION:
220 MADB_SetOptionValue(Dsn, &DsnKeys[DsnKeysSwitch[i].Dependent], DsnKeysSwitch[i].Same == KeySet ? 1 : 0);
221 break;
222 default:
223 return FALSE; /* Only boolean fields are supported as dependent atm */
224 }
225 }
226 }
227
228 return TRUE;
229 }
230 /* }}} */
231
232
233 /* {{{ MADB_DsnStoreValue */
234 my_bool MADB_DsnStoreValue(MADB_Dsn *Dsn, unsigned int DsnKeyIdx, char *Value, my_bool OverWrite)
235 {
236 MADB_DsnKey *DsnKey= &DsnKeys[DsnKeyIdx];
237 if (!Dsn || DsnKey->IsAlias)
238 return FALSE;
239
240 switch(DsnKey->Type) {
241 case DSN_TYPE_STRING:
242 case DSN_TYPE_COMBO:
243 {
244 char **p= GET_FIELD_PTR(Dsn, DsnKey, char*);
245
246 if (*p && OverWrite == FALSE)
247 break;
248 /* For the case of making copy of currently stored values */
249 MADB_RESET(*p, Value);
250 }
251 break;
252 case DSN_TYPE_BOOL:
253 /* If value is not set or we may overwrite it */
254 if (!(*GET_FIELD_PTR(Dsn, DsnKey, my_bool) && OverWrite == FALSE))
255 {
256 *GET_FIELD_PTR(Dsn, DsnKey, my_bool)= atoi(Value);
257 }
258 break;
259 case DSN_TYPE_CBOXGROUP:
260 /* If value is not set or we may overwrite it */
261 if (! (*GET_FIELD_PTR(Dsn, DsnKey, char) && OverWrite == FALSE))
262 {
263 char IntValue= atoi(Value);
264
265 /* Atm we have only one DSN_TYPE_CBOXGROUP!!!, and following works only for it. If sometime another such field is added,
266 we will need another data structure array, that will bind DSN field with string values and bits for this field.
267 So far we use hardcoded arrays for the singe such field we have atm */
268 if (IntValue == '\0')
269 {
270 unsigned int i;
271
272 IntValue= 0;
273 for (i= 0; i < sizeof(TlsVersionBits); ++i)
274 {
275 if (strcasestr(Value, TlsVersionName[i]) != NULL)
276 {
277 IntValue|= TlsVersionBits[i];
278 }
279 }
280 }
281 *GET_FIELD_PTR(Dsn, DsnKey, char)= IntValue;
282 }
283 break;
284 case DSN_TYPE_INT:
285 if (*GET_FIELD_PTR(Dsn, DsnKey, int) && OverWrite == FALSE)
286 break;
287 *GET_FIELD_PTR(Dsn, DsnKey, int)= strtoul(Value, NULL, 10);
288 break;
289 case DSN_TYPE_OPTION:
290 if (*GET_FIELD_PTR(Dsn, DsnKey, my_bool) && OverWrite == FALSE)
291 break;
292 MADB_SetOptionValue(Dsn, DsnKey, strtoul(Value, NULL, 10) != 0 ? 1 : 0);
293
294 break;
295 }
296 return MADB_DsnSwitchDependents(Dsn, DsnKeyIdx);
297 }
298 /* }}} */
299
300 /* {{{ MADB_DsnUpdateOptionsFields */
301 void MADB_DsnUpdateOptionsFields(MADB_Dsn *Dsn)
302 {
303 int i= 0;
304
305 while (DsnKeys[i].DsnKey != NULL)
306 {
307 if (DsnKeys[i].IsAlias == 0)
308 {
309 if (DsnKeys[i].Type == DSN_TYPE_OPTION)
310 {
311 *GET_FIELD_PTR(Dsn, &DsnKeys[i], my_bool)= (my_bool)(DSN_OPTION(Dsn, DsnKeys[i].FlagValue) ? 1 : 0);
312 MADB_DsnSwitchDependents(Dsn, i);
313 }
314 }
315 ++i;
316 }
317 }
318 /* }}} */
319
320 /* {{{ MADB_ReadDSN */
321 my_bool MADB_ReadDSN(MADB_Dsn *Dsn, const char *KeyValue, my_bool OverWrite)
322 {
323 char *Value;
324 /* if no key/value pair was specified, we will try to read Dsn->DSNName */
325 if (!KeyValue)
326 {
327 Value= Dsn->DSNName;
328 }
329 else
330 {
331 if ((Value= strchr(KeyValue, '=')) != NULL)
332 {
333 ++Value;
334 MADB_RESET(Dsn->DSNName, Value);
335 }
336 }
337
338 if (Value)
339 {
340 int i= 1;
341 char KeyVal[1024];
342
343 while (DsnKeys[i].DsnKey)
344 {
345 unsigned int KeyIdx= DsnKeys[i].IsAlias ? DsnKeys[i].DsnOffset : i;
346
347 if (SQLGetPrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, "", KeyVal, 1024, "ODBC.INI") > 0)
348 {
349 if (!MADB_DsnStoreValue(Dsn, KeyIdx, KeyVal, OverWrite))
350 return FALSE;
351 }
352 else if (DsnKeys[i].Type == DSN_TYPE_OPTION)
353 {
354 *GET_FIELD_PTR(Dsn, &DsnKeys[KeyIdx], my_bool)= (my_bool)(DSN_OPTION(Dsn, DsnKeys[KeyIdx].FlagValue) ? 1 : 0);
355 }
356 ++i;
357 }
358 return TRUE;
359 }
360 return FALSE;
361 }
362 /* }}} */
363
364 my_bool MADB_DSN_Exists(const char *DsnName)
365 {
366 my_bool ret;
367 char buffer[1024];
368 char *p= "";
369
370 if (!DsnName)
371 return FALSE;
372
373 ret= (SQLGetPrivateProfileString(DsnName, NULL, p, buffer, 1024, "ODBC.INI") > 0);
374 return ret;
375 }
376
377 /* {{{ MADB_SaveDSN */
378 my_bool MADB_SaveDSN(MADB_Dsn *Dsn)
379 {
380 int i= 1;
381 char Value[32];
382 my_bool ret;
383 DWORD ErrNum;
384
385 if (!SQLValidDSN(Dsn->DSNName))
386 {
387 strcpy_s(Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, "Invalid Data Source Name");
388 return FALSE;
389 }
390
391 if (!SQLRemoveDSNFromIni(Dsn->DSNName))
392 {
393 SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
394 return FALSE;
395 }
396 if (!SQLWriteDSNToIni(Dsn->DSNName, Dsn->Driver))
397 {
398 SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
399 return FALSE;
400 }
401
402 while(DsnKeys[i].DsnKey)
403 {
404 /* Skipping aliases - options are saved by primary name only */
405 if (!DsnKeys[i].IsAlias)
406 {
407 ret= TRUE;
408 /* We do not save DSN_TYPE_OPTION - they are saved as OPTIONS bits */
409 switch (DsnKeys[i].Type) {
410 case DSN_TYPE_BOOL:
411 ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey,
412 *GET_FIELD_PTR(Dsn, &DsnKeys[i], my_bool) ? "1" : "0", "ODBC.INI");
413 break;
414 case DSN_TYPE_INT:
415 {
416 _snprintf(Value ,32, "%d", *(int *)((char *)Dsn + DsnKeys[i].DsnOffset));
417 ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, Value, "ODBC.INI");
418 }
419 break;
420 case DSN_TYPE_CBOXGROUP:
421 {
422 _snprintf(Value, 32, "%hu", (short)*GET_FIELD_PTR(Dsn, &DsnKeys[i], char));
423 ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, Value, "ODBC.INI");
424 }
425 break;
426 case DSN_TYPE_STRING:
427 case DSN_TYPE_COMBO:
428 {
429 char *Val= *GET_FIELD_PTR(Dsn, &DsnKeys[i], char*);
430 if (Val && Val[0])
431 ret= SQLWritePrivateProfileString(Dsn->DSNName, DsnKeys[i].DsnKey, Val, "ODBC.INI");
432 }
433 default:
434 /* To avoid warning with some compilers */
435 break;
436 } /* switch */
437
438 if (!ret)
439 {
440 SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
441 return FALSE;
442 }
443 }
444 i++;
445 }
446 /* Save Options */
447 _snprintf(Value ,32, "%d", Dsn->Options);
448 if (!(ret= SQLWritePrivateProfileString(Dsn->DSNName, "OPTIONS", Value, "ODBC.INI")))
449 {
450 SQLInstallerError(1,&ErrNum, Dsn->ErrorMsg, SQL_MAX_MESSAGE_LENGTH, NULL);
451 return FALSE;
452 }
453 return TRUE;
454 }
455 /* }}} */
456
457
458 size_t ConnStringLength(const char * String, char Delimiter)
459 {
460 size_t result= strlen(String);
461 const char *p= String + result + 1;
462
463 if (Delimiter != '\0')
464 {
465 return result;
466 }
467 /* else - we have string with null terminated key=value pairs with additional NULL after last pair */
468 while (*p)
469 {
470 p+= strlen(p) + 1;
471 }
472
473 return p - String /* Length without ending NULL */;
474 }
475
476 /* {{{ MADB_ParseConnString */
477 my_bool MADB_ParseConnString(MADB_Dsn *Dsn, const char *String, size_t Length, char Delimiter)
478 {
479 char *Buffer, *Key, *Value;
480 my_bool ret;
481
482 if (!String)
483 return FALSE;
484
485 if (Length == SQL_NTS)
486 {
487 Length= ConnStringLength(String, Delimiter);
488 }
489
490 Buffer= MADB_ALLOC(Length + 1);
491 Buffer= memcpy(Buffer, String, Length + 1);
492 Key= Buffer;
493
494 while (Key && Key < ((char *)Buffer + Length))
495 {
496 int i= 0;
497 if (!(Value= strchr(Key, '=')))
498 {
499 ret= FALSE;
500 break;
501 }
502
503 *Value= 0;
504 ++Value;
505 Key= trim(Key);
506
507 while (DsnKeys[i].DsnKey)
508 {
509 if (_stricmp(DsnKeys[i].DsnKey, Key) == 0)
510 {
511 char *p;
512 my_bool special= FALSE;
513
514 if (DsnKeys[i].IsAlias)
515 {
516 i= DsnKeys[i].DsnOffset; /* For aliases DsnOffset is index of aliased "main" key */
517 }
518
519 Value= trim(Value);
520
521 if (Value[0] == '{')
522 {
523 ++Value;
524 if ((p = strchr(Value, '}')))
525 {
526 *p= 0;
527 special= TRUE;
528 }
529 }
530 else if ((p= strchr(Value, Delimiter)))
531 {
532 *p= 0;
533 }
534 Value= trim(Value);
535
536 /* Overwriting here - if an option repeated more than once in the string, its last entrance will determine the value */
537 if (!MADB_DsnStoreValue(Dsn, i, Value, TRUE))
538 return FALSE;
539 if (IS_OPTIONS_BITMAP(i))
540 {
541 MADB_DsnUpdateOptionsFields(Dsn);
542 }
543
544 if (p)
545 {
546 *p= (special) ? ' ' : Delimiter;
547 }
548 break;
549 }
550 ++i;
551 }
552 if ((Key= strchr(Value, Delimiter)))
553 {
554 ++Key;
555 }
556 }
557 MADB_FREE(Buffer);
558 return TRUE;
559 }
560 /* }}} */
561
562 /* {{{ MADB_ReadConnString */
563 /* Like ParseConnString, but expands DSN if needed, preserving connection string values precedence.
564 Or in other words - it is combination of ReadDsn and ParseConnString */
565 BOOL MADB_ReadConnString(MADB_Dsn *Dsn, const char *String, size_t Length, char Delimiter)
566 {
567 /* Basically at this point we need DSN name only */
568 if (!MADB_ParseConnString(Dsn, String, Length, Delimiter))
569 {
570 return FALSE;
571 }
572
573 /* "If the connection string contains the DRIVER keyword, the driver cannot retrieve information about the data source
574 from the system information." https://msdn.microsoft.com/en-us/library/ms715433%28v=vs.85%29.aspx */
575 if (Dsn->DSNName && MADB_IS_EMPTY(Dsn->Driver))
576 {
577 MADB_ReadDSN(Dsn, NULL, FALSE);
578 /* This redundancy is needed to be able to reset options set in the DSN, e.g. if DSN has Reconnect option selected, and
579 connection string has AUTO_RECONNECT=0. Connection string should have precedence */
580 MADB_ParseConnString(Dsn, String, Length, Delimiter);
581 }
582 return TRUE;
583 }
584 /* }}} */
585
586 /* {{{ MADB_DsnToString */
587 SQLULEN MADB_DsnToString(MADB_Dsn *Dsn, char *OutString, SQLULEN OutLength)
588 {
589 int i= 0;
590 SQLULEN TotalLength= 0;
591 char *p= OutString;
592 char *Value= NULL;
593 char TmpStr[1024];
594 char IntVal[12];
595 int CpyLength;
596
597 if (OutLength && OutString)
598 OutString[0]= '\0';
599
600 while (DsnKeys[i].DsnKey)
601 {
602 Value= NULL;
603
604 if (!DsnKeys[i].IsAlias)
605 {
606 switch (DsnKeys[i].Type) {
607 case DSN_TYPE_STRING:
608 case DSN_TYPE_COMBO:
609 Value= *GET_FIELD_PTR(Dsn, &DsnKeys[i], char*);
610 if (MADB_IS_EMPTY(Value))
611 {
612 ++i;
613 continue;
614 }
615 break;
616 case DSN_TYPE_INT:
617 if (*GET_FIELD_PTR(Dsn, &DsnKeys[i], int))
618 {
619 _snprintf(IntVal, sizeof(IntVal), "%d", *GET_FIELD_PTR(Dsn, &DsnKeys[i], int));
620 Value= IntVal;
621 }
622 break;
623 case DSN_TYPE_BOOL:
624 if (*GET_FIELD_PTR(Dsn, &DsnKeys[i], my_bool))
625 {
626 Value= "1";
627 }
628 default:
629 /* To avoid warning with some compilers */
630 break;
631 case DSN_TYPE_CBOXGROUP:
632 if (*GET_FIELD_PTR(Dsn, &DsnKeys[i], char))
633 {
634 _snprintf(IntVal, sizeof(IntVal), "%hu", (short)*GET_FIELD_PTR(Dsn, &DsnKeys[i], char));
635 Value= IntVal;
636 }
637 break;
638 }
639 }
640
641 if (Value)
642 {
643 my_bool isSpecial= (strchr(Value, ' ') || strchr(Value, ';') || strchr(Value, '@'));
644 CpyLength= _snprintf(TmpStr + TotalLength, 1024 - TotalLength, "%s%s=%s%s%s", (TotalLength) ? ";" : "",
645 DsnKeys[i].DsnKey, isSpecial ? "{" : "", Value, isSpecial ? "}" : "");
646 TotalLength+= CpyLength;
647 }
648 ++i;
649 }
650
651 if (OutLength && OutString)
652 {
653 strncpy_s(OutString, OutLength, TmpStr, TotalLength);
654 }
655 return TotalLength;
656 }
657 /* }}} */
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_dsn_h_
19 #define _ma_dsn_h_
20
21 #include <odbcinst.h>
22
23 /* MySQL ODBC compatibility options */
24 #define MADB_OPT_FLAG_FIELD_LENGTH 1
25 #define MADB_OPT_FLAG_FOUND_ROWS 2
26 #define MADB_OPT_FLAG_DEBUG 4
27 #define MADB_OPT_FLAG_BIG_PACKETS 8
28 #define MADB_OPT_FLAG_NO_PROMPT 16
29 #define MADB_OPT_FLAG_DYNAMIC_CURSOR 32
30 #define MADB_OPT_FLAG_NO_SCHEMA 64
31 #define MADB_OPT_FLAG_NO_DEFAULT_CURSOR 128
32 #define MADB_OPT_FLAG_NO_LOCALE 256
33 #define MADB_OPT_FLAG_PAD_SPACE 512
34 #define MADB_OPT_FLAG_FULL_COLUMN_NAMES 1024 /*10*/
35 #define MADB_OPT_FLAG_COMPRESSED_PROTO 2048
36 #define MADB_OPT_FLAG_IGNORE_SPACE 4096
37 #define MADB_OPT_FLAG_NAMED_PIPE 8192
38 #define MADB_OPT_FLAG_NO_BIGINT 16384
39 #define MADB_OPT_FLAG_NO_CATALOG 32768
40 #define MADB_OPT_FLAG_USE_CNF 65536
41 #define MADB_OPT_FLAG_SAFE 131072
42 #define MADB_OPT_FLAG_NO_TRANSACTIONS 262144
43 #define MADB_OPT_FLAG_LOG_QUERY 524288
44 #define MADB_OPT_FLAG_NO_CACHE 1048576 /*20*/
45 #define MADB_OPT_FLAG_FORWARD_CURSOR 2097152
46 #define MADB_OPT_FLAG_AUTO_RECONNECT 4194304
47 #define MADB_OPT_FLAG_AUTO_IS_NULL 8388608
48 #define MADB_OPT_FLAG_ZERO_DATE_TO_MIN 16777216
49 #define MADB_OPT_FLAG_MIN_DATE_TO_ZERO 33554432
50 #define MADB_OPT_FLAG_MULTI_STATEMENTS 67108864
51 #define MADB_OPT_FLAG_COLUMN_SIZE_S32 134217728
52 #define MADN_OPT_FLAG_NO_BINARY_RESULT 268435456
53 #define MADN_OPT_FLAG_BIGINT_BIND_STR 536870912
54 #define MADN_OPT_FLAG_NO_INFORMATION_SCHEMA 1073741824 /*30*/
55
56 enum enum_dsn_item_type {
57 DSN_TYPE_STRING,
58 DSN_TYPE_INT,
59 DSN_TYPE_BOOL,
60 DSN_TYPE_COMBO, /* Mainly the same as string, but the field in the dialog is combobox */
61 DSN_TYPE_OPTION, /* Connection string option has correspondent OPTIONS bit */
62 DSN_TYPE_CBOXGROUP /* Group of checkboxes each of them represent a bit in the field's value
63 Bitmap size is 1 byte */
64 };
65
66 typedef struct
67 {
68 unsigned int Page;
69 unsigned long Item;
70 unsigned long value;
71 } MADB_OptionsMap;
72
73 typedef struct
74 {
75 char *DsnKey;
76 unsigned int DsnOffset;
77 enum enum_dsn_item_type Type;
78 unsigned long FlagValue;
79 my_bool IsAlias;
80 } MADB_DsnKey;
81
82 /* Definitions to tell setup library via isPrompt field what should it do */
83 #define MAODBC_CONFIG 0
84 #define MAODBC_PROMPT 1
85 #define MAODBC_PROMPT_REQUIRED 2
86
87 /* TLS version bits */
88 #define MADB_TLSV11 1
89 #define MADB_TLSV12 2
90 #define MADB_TLSV13 4
91
92 extern const char TlsVersionName[3][8];
93 extern const char TlsVersionBits[3];
94
95 typedef struct st_madb_dsn
96 {
97 /*** General ***/
98 char *DSNName;
99 char *Driver;
100 char *Description;
101 /*** Connection parameters ***/
102 char *ServerName;
103 my_bool IsNamedPipe;
104 my_bool IsTcpIp;
105 char *UserName;
106 char *Password;
107 char *Catalog;
108 unsigned int Port;
109 /* Options */
110 unsigned int Options;
111 char *CharacterSet;
112 char *InitCommand;
113 char *TraceFile;
114 unsigned int ConnectionTimeout;
115 my_bool Reconnect;
116 my_bool MultiStatements;
117 /* TRUE means "no prompt" */
118 my_bool ConnectPrompt;
119 char *Socket;
120 char *ConnCPluginsDir;
121 /* SSL Settings */
122 char *SslKey;
123 char *SslCert;
124 char *SslCa;
125 char *SslCaPath;
126 char *SslCipher;
127 char *SslCrl;
128 char *SslCrlPath;
129 char *SslFp;
130 char *SslFpList;
131 my_bool SslVerify;
132 char TlsVersion;
133 my_bool ForceTls;
134 char *SaveFile;
135 my_bool ReadMycnf;
136 /* --- Internal --- */
137 int isPrompt;
138 MADB_DsnKey *Keys;
139 char ErrorMsg[SQL_MAX_MESSAGE_LENGTH];
140 my_bool FreeMe;
141 /* Callbacke required for prompt to keep all memory de/allocation operations
142 on same side of libraries */
143 char * (*allocator)(size_t);
144 void (*free)(void*);
145 } MADB_Dsn;
146
147 /* this structure is used to store and retrieve DSN Information */
148 extern MADB_DsnKey DsnKeys[];
149
150 #define GET_FIELD_PTR(DSN, DSNKEY, TYPE) ((TYPE *)((char*)(DSN) + (DSNKEY)->DsnOffset))
151
152
153 /*** Function prototypes ***/
154 MADB_Dsn * MADB_DSN_Init (void);
155 void MADB_DSN_SetDefaults(MADB_Dsn *Dsn);
156 void MADB_DSN_Free (MADB_Dsn *Dsn);
157 my_bool MADB_ReadDSN (MADB_Dsn *Dsn, const char *KeyValue, my_bool OverWrite);
158 my_bool MADB_SaveDSN (MADB_Dsn *Dsn);
159 my_bool MADB_DSN_Exists (const char *DsnName);
160 my_bool MADB_ParseConnString(MADB_Dsn *Dsn, const char *String, size_t Length, char Delimiter);
161 BOOL MADB_ReadConnString (MADB_Dsn *Dsn, const char *String, size_t Length, char Delimiter);
162 SQLULEN MADB_DsnToString (MADB_Dsn *Dsn, char *OutString, SQLULEN OutLength);
163 void MADB_DsnUpdateOptionsFields (MADB_Dsn *Dsn);
164 BOOL MADB_DSN_PossibleConnect (MADB_Dsn *Dsn);
165
166 /*** Helper macros ***/
167 #define DSN_OPTION(a,b)\
168 ((a)->Options & b)
169
170 #define MA_ODBC_CURSOR_DYNAMIC(a)\
171 DSN_OPTION((a), MADB_OPT_FLAG_DYNAMIC_CURSOR)
172
173 #define MA_ODBC_CURSOR_FORWARD_ONLY(a)\
174 DSN_OPTION((a), MADB_OPT_FLAG_FORWARD_CURSOR)
175
176 #define MADB_DSN_SET_STR(dsn, item, value, len)\
177 if((value) && (len) != 0)\
178 {\
179 if ((len) == SQL_NTS)\
180 (len)=(SQLSMALLINT)strlen((value));\
181 MADB_FREE((dsn)->item);\
182 (dsn)->item= (char *)calloc(len + 1, sizeof(char));\
183 memcpy((dsn)->item, (value),(len));\
184 }
185
186 #endif /* _ma_dsn_h_ */
0 /************************************************************************************
1 Copyright (C) 2013,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 extern Client_Charset utf8;
21 extern MARIADB_CHARSET_INFO* DmUnicodeCs;
22 extern MARIADB_CHARSET_INFO dummyUtf32le;
23 Client_Charset SourceAnsiCs= {0, 0}; /* Basically it should be initialized with 0 anyway */
24
25 MARIADB_CHARSET_INFO * mysql_find_charset_name(const char *name);
26
27 #ifdef _WIN32
28 # pragma comment(lib, "ws2_32.lib")
29 #endif
30
31
32 static my_bool little_endian()
33 {
34 int x= 1;
35 char *c= (char*)&x;
36
37 return *c;
38 }
39
40
41 /* {{{ MADB_EnvFree */
42 SQLRETURN MADB_EnvFree(MADB_Env *Env)
43 {
44 if (!Env)
45 return SQL_ERROR;
46 DeleteCriticalSection(&Env->cs);
47 free(Env);
48
49 #ifdef _WIN32
50 WSACleanup();
51 #endif
52
53 return SQL_SUCCESS;
54 }
55 /* }}} */
56
57 const char* GetDefaultLogDir();
58 int GetSourceAnsiCs(Client_Charset *cc);
59
60 /* {{{ MADB_EnvInit */
61 MADB_Env *MADB_EnvInit()
62 {
63 MADB_Env *Env= NULL;
64
65 #ifdef _WIN32
66 /* Since we can't determine if WSAStartup has been called, we need
67 to call it again
68 */
69 WORD VersionRequested;
70 int err;
71 WSADATA WsaData;
72 /* if possible use latest supported version (2.2) */
73 const unsigned int MajorVersion=2,
74 MinorVersion=2;
75 VersionRequested= MAKEWORD(MajorVersion, MinorVersion);
76 /* Load WinSock library */
77 if ((err= WSAStartup(VersionRequested, &WsaData)))
78 {
79 /* todo: optional debug output */
80 return Env;
81 }
82 /* make sure 2.2 or higher is supported */
83 if ((LOBYTE(WsaData.wVersion) * 10 + HIBYTE(WsaData.wVersion)) < 22)
84 {
85 /* todo: optional debug output */
86 goto cleanup;
87 }
88 #endif
89 mysql_library_init(0, NULL, NULL);
90 if (!(Env= (MADB_Env *)MADB_CALLOC(sizeof(MADB_Env))))
91 {
92 /* todo: optional debug output */
93 goto cleanup;
94 }
95
96 MADB_PutErrorPrefix(NULL, &Env->Error);
97
98 InitializeCriticalSection(&Env->cs);
99 Env->OdbcVersion= SQL_OV_ODBC3;
100
101 /* This is probably is better todo with thread_once */
102 if (DmUnicodeCs == NULL)
103 {
104 if (sizeof(SQLWCHAR) == 2)
105 {
106 DmUnicodeCs= mariadb_get_charset_by_name(little_endian() ? "utf16le" : "utf16");
107 }
108 else
109 {
110 DmUnicodeCs= little_endian() ? &dummyUtf32le : mariadb_get_charset_by_name("utf32");
111 }
112 }
113 utf8.cs_info= mariadb_get_charset_by_name("utf8mb4");
114 GetDefaultLogDir();
115 GetSourceAnsiCs(&SourceAnsiCs);
116
117 cleanup:
118 #ifdef _WIN32
119 if (!Env)
120 WSACleanup();
121 #endif
122
123 return Env;
124 }
125 /* }}} */
126
127 /* {{{ MADB_EnvSetAttr */
128 SQLRETURN MADB_EnvSetAttr(MADB_Env* Env, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength)
129 {
130 MADB_CLEAR_ERROR(&Env->Error);
131 switch (Attribute) {
132 case SQL_ATTR_ODBC_VERSION:
133 if (Env->Dbcs)
134 {
135 MADB_SetError(&Env->Error, MADB_ERR_HYC00, NULL, 0);
136 return Env->Error.ReturnValue;
137 }
138 Env->OdbcVersion= (SQLINTEGER)(SQLLEN)ValuePtr;
139 break;
140 case SQL_ATTR_OUTPUT_NTS:
141 if ((SQLINTEGER)(SQLLEN)ValuePtr != SQL_TRUE)
142 MADB_SetError(&Env->Error, MADB_ERR_S1C00, NULL, 0);
143 break;
144 default:
145 MADB_SetError(&Env->Error, MADB_ERR_HYC00, NULL, 0);
146 break;
147 }
148 // LeaveCriticalSection(&Env->cs);
149 return Env->Error.ReturnValue;
150 }
151 /* }}} */
152
153 /* {{{ MADB_EnvGetAttr */
154 SQLRETURN MADB_EnvGetAttr(MADB_Env *Env, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength,
155 SQLINTEGER *StringLengthPtr)
156 {
157 MADB_CLEAR_ERROR(&Env->Error);
158 switch (Attribute) {
159 case SQL_ATTR_CONNECTION_POOLING:
160 *(SQLUINTEGER *)ValuePtr = SQL_CP_OFF;
161 break;
162 case SQL_ATTR_ODBC_VERSION:
163 *(SQLINTEGER *)ValuePtr= Env->OdbcVersion;
164 break;
165 case SQL_ATTR_OUTPUT_NTS:
166 *(SQLINTEGER *)ValuePtr= SQL_TRUE;
167 break;
168 default:
169 MADB_SetError(&Env->Error, MADB_ERR_HYC00, NULL, 0);
170 break;
171 }
172 return Env->Error.ReturnValue;
173 }
174 /* }}} */
0 /************************************************************************************
1 Copyright (C) 2013 SkySQL AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_environment_h_
19 #define _ma_environment_h_
20
21 MADB_Env *MADB_EnvInit();
22 SQLRETURN MADB_EnvFree(MADB_Env *Env);
23
24 SQLRETURN MADB_EnvSetAttr(MADB_Env* Env, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
25 SQLRETURN MADB_EnvGetAttr(MADB_Env *Env, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength,
26 SQLINTEGER *StringLengthPtr);
27
28 extern Client_Charset SourceAnsiCs;
29
30 #endif /* _ma_environment_h_ */
0 /************************************************************************************
1 Copyright (C) 2013,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 extern Client_Charset utf8;
21
22 /* {{{ MADB_ErrorList[] */
23 MADB_ERROR MADB_ErrorList[] =
24 {
25 { "00000", "", "", SQL_ERROR},
26 { "01000", "", "General warning", SQL_ERROR},
27 { "01001", "01S03", "Cursor operation conflict", SQL_ERROR},
28 { "01002", "", "Disconnect error", SQL_ERROR},
29 { "01003", "", "NULL value eliminated in set function", SQL_ERROR},
30 { "01004", "", "String data, right-truncated", SQL_ERROR},
31 { "01006", "", "Privilege not revoked", SQL_ERROR},
32 { "01007", "", "Privilege not granted", SQL_ERROR},
33 { "01S00", "", "Invalid connection string attribute", SQL_ERROR},
34 { "01S01", "", "Error in row", SQL_ERROR},
35 { "01S02", "", "Option value changed", SQL_ERROR},
36 { "01S06", "", "Attempt to fetch before the result set returned the first rowset", SQL_ERROR},
37 { "01S07", "", "Fractional truncation", SQL_ERROR},
38 { "01S08", "", "Error saving File DSN", SQL_ERROR},
39 { "01S09", "", "Invalid keyword", SQL_ERROR},
40 { "07001", "", "Wrong number of parameters", SQL_ERROR},
41 { "07002", "", "COUNT field incorrect", SQL_ERROR},
42 { "07005", "2400", "Prepared statement not a cursor-specification", SQL_ERROR},
43 { "07006", "", "Restricted data type attribute violation", SQL_ERROR},
44 { "07009", "S1002", "Invalid descriptor index", SQL_ERROR},
45 { "07S01", "", "Invalid use of default parameter", SQL_ERROR},
46 { "08001", "", "Client unable to establish connection", SQL_ERROR},
47 { "08002", "", "Connection name in use", SQL_ERROR},
48 { "08003", "", "Connection not open", SQL_ERROR},
49 { "08004", "", "Server rejected the connection", SQL_ERROR},
50 { "08007", "", "Connection failure during transaction", SQL_ERROR},
51 { "08S01", "", "Communication link failure", SQL_ERROR},
52 { "21S01", "", "Insert value list does not match column list", SQL_ERROR},
53 { "21S02", "", "Degree of derived table does not match column list", SQL_ERROR},
54 { "22001", "", "String data, right-truncated", SQL_ERROR},
55 { "22002", "", "Indicator variable required but not supplied", SQL_ERROR},
56 { "22003", "", "Numeric value out of range", SQL_ERROR},
57 { "22007", "22008", "Invalid datetime format", SQL_ERROR},
58 { "22008", "", "Datetime field overflow", SQL_ERROR},
59 { "22012", "", "Division by zero", SQL_ERROR},
60 { "22015", "", "Interval field overflow", SQL_ERROR},
61 { "22018", "22005", "Invalid character value for cast specification", SQL_ERROR},
62 { "22019", "", "Invalid escape character", SQL_ERROR},
63 { "22025", "", "Invalid escape sequence", SQL_ERROR},
64 { "22026", "", "String data, length mismatch", SQL_ERROR},
65 { "23000", "", "Integrity constraint violation", SQL_ERROR},
66 { "24000", "", "Invalid cursor state", SQL_ERROR},
67 { "25000", "", "Invalid transaction state", SQL_ERROR},
68 { "25S01", "", "Transaction state", SQL_ERROR},
69 { "25S02", "", "Transaction is still active", SQL_ERROR},
70 { "25S03", "", "Transaction is rolled back", SQL_ERROR},
71 { "28000", "", "Invalid authorization specification", SQL_ERROR},
72 { "34000", "", "Invalid cursor name", SQL_ERROR},
73 { "3C000", "", "Duplicate cursor name", SQL_ERROR},
74 { "3D000", "", "Invalid catalog name", SQL_ERROR},
75 { "3F000", "", "Invalid schema name", SQL_ERROR},
76 { "40001", "", "Serialization failure", SQL_ERROR},
77 { "40002", "", "Integrity constraint violation", SQL_ERROR},
78 { "40003", "", "Statement completion unknown", SQL_ERROR},
79 { "42000", "37000", "Syntax error or access violation", SQL_ERROR},
80 { "42S01", "S0001", "Base table or view already exists", SQL_ERROR},
81 { "42S02", "S0002", "Base table or view not found", SQL_ERROR},
82 { "42S11", "S0011", "Index already exists", SQL_ERROR},
83 { "42S12", "S0012", "Index not found", SQL_ERROR},
84 { "42S21", "S0021", "Column already exists", SQL_ERROR},
85 { "42S22", "S0022", "Column not found", SQL_ERROR},
86 { "44000", "", "WITH CHECK OPTION violation", SQL_ERROR},
87 { "HY000", "S1000", "General error", SQL_ERROR},
88 { "HY001", "S1001", "Memory allocation error", SQL_ERROR},
89 { "HY003", "S1003", "Invalid application buffer type", SQL_ERROR},
90 { "HY004", "S1004", "Invalid SQL data type", SQL_ERROR},
91 { "HY007", "S1010", "Associated statement is not prepared", SQL_ERROR},
92 { "HY008", "S1008", "Operation canceled", SQL_ERROR},
93 { "HY009", "S1009", "Invalid use of null pointer", SQL_ERROR},
94 { "HY010", "S1010", "Function sequence error", SQL_ERROR},
95 { "HY011", "S1011", "Attribute cannot be set now", SQL_ERROR},
96 { "HY012", "S1012", "Invalid transaction operation code", SQL_ERROR},
97 { "HY013", "", "Memory management error", SQL_ERROR},
98 { "HY014", "", "Limit on the number of handles exceeded", SQL_ERROR},
99 { "HY015", "", "No cursor name available", SQL_ERROR},
100 { "HY016", "", "Cannot modify an implementation row descriptor", SQL_ERROR},
101 { "HY017", "", "Invalid use of an automatically allocated descriptor handle", SQL_ERROR},
102 { "HY018", "70100", "Server declined cancel request", SQL_ERROR},
103 { "HY019", "22003", "Non-character and non-binary data sent in pieces", SQL_ERROR},
104 { "HY020", "", "Attempt to concatenate a null value", SQL_ERROR},
105 { "HY021", "", "Inconsistent descriptor information", SQL_ERROR},
106 { "HY024", "S1009", "Invalid attribute value", SQL_ERROR},
107 { "HY090", "S1009", "Invalid string or buffer length", SQL_ERROR},
108 { "HY091", "S1091", "Invalid descriptor field identifier", SQL_ERROR},
109 { "HY092", "S1092", "Invalid attribute/option identifier", SQL_ERROR},
110 { "HY095", "", "Function type out of range", SQL_ERROR},
111 { "HY096", "S1096", "Invalid information type", SQL_ERROR},
112 { "HY097", "S1097", "Column type out of range", SQL_ERROR},
113 { "HY098", "S1098", "Scope type out of range", SQL_ERROR},
114 { "HY099", "S1099", "Nullable type out of range", SQL_ERROR},
115 { "HY100", "S1100", "Uniqueness option type out of range", SQL_ERROR},
116 { "HY101", "S1101", "Accuracy option type out of range", SQL_ERROR},
117 { "HY103", "S1103", "Invalid retrieval code", SQL_ERROR},
118 { "HY104", "S1104", "Invalid precision or scale value", SQL_ERROR},
119 { "HY105", "S1105", "Invalid parameter type", SQL_ERROR},
120 { "HY106", "S1106", "Fetch type out of range", SQL_ERROR},
121 { "HY107", "S1107", "Row value out of range", SQL_ERROR},
122 { "HY109", "S1109", "Invalid cursor position", SQL_ERROR},
123 { "HY110", "S1110", "Invalid driver completion", SQL_ERROR},
124 { "HY111", "S1111", "Invalid bookmark value", SQL_ERROR},
125 { "HYC00", "S1C00", "Optional feature not implemented", SQL_ERROR},
126 { "HYT00", "S1T00", "Timeout expired", SQL_ERROR},
127 { "HYT01", "", "Connection timeout expired", SQL_ERROR},
128 { "IM001", "", "Driver does not support this function", SQL_ERROR},
129 { "IM002", "", "Data source name not found and no default driver specified", SQL_ERROR},
130 { "IM003", "", "Specified driver could not be loaded", SQL_ERROR},
131 { "IM004", "", "Driver's SQLAllocHandle on SQL_HANDLE_ENV failed", SQL_ERROR},
132 { "IM005", "", "Driver's SQLAllocHandle on SQL_HANDLE_DBC failed", SQL_ERROR},
133 { "IM006", "", "Driver's SQLSetConnectAttr failed", SQL_ERROR},
134 { "IM007", "", "No data source or driver specified; dialog prohibited", SQL_ERROR},
135 { "IM008", "", "Dialog failed", SQL_ERROR},
136 { "IM009", "", "Unable to load translation DL", SQL_ERROR},
137 { "IM010", "", "Data source name too long", SQL_ERROR},
138 { "IM011", "", "Driver name too long", SQL_ERROR},
139 { "IM012", "", "DRIVER keyword syntax error", SQL_ERROR},
140 { "IM013", "", "Trace file error", SQL_ERROR},
141 { "IM014", "", "Invalid name of File DSN", SQL_ERROR},
142 { "IM015", "", "Corrupt file data source", SQL_ERROR},
143 { "S1000", "", "General error", SQL_ERROR},
144 { "S1107", "", "Row value out of range", SQL_ERROR},
145 { "S1C00", "", "Optional feature not implemented", SQL_ERROR},
146 { 0,0,0, -1}
147 };
148 /* }}} */
149
150
151 char* MADB_PutErrorPrefix(MADB_Dbc *dbc, MADB_Error *error)
152 {
153 /* If prefix is already there - we do not write again. One shoud reset error->PrefixLen in order to force */
154 if (error->PrefixLen == 0)
155 {
156 error->PrefixLen= strlen(MARIADB_ODBC_ERR_PREFIX);
157 strcpy_s(error->SqlErrorMsg, SQL_MAX_MESSAGE_LENGTH + 1, MARIADB_ODBC_ERR_PREFIX);
158 if (dbc != NULL && dbc->mariadb != NULL)
159 {
160 error->PrefixLen += _snprintf(error->SqlErrorMsg + error->PrefixLen,
161 SQL_MAX_MESSAGE_LENGTH + 1 - error->PrefixLen, "[%s]", mysql_get_server_info(dbc->mariadb));
162 }
163 }
164 return error->SqlErrorMsg + error->PrefixLen;
165 }
166
167
168 SQLRETURN MADB_SetNativeError(MADB_Error *Error, SQLSMALLINT HandleType, void *Ptr)
169 {
170 char *Sqlstate= NULL, *Errormsg= NULL;
171 int NativeError= 0;
172
173 switch (HandleType) {
174 case SQL_HANDLE_DBC:
175 Sqlstate= (char *)mysql_sqlstate((MYSQL *)Ptr);
176 Errormsg= (char *)mysql_error((MYSQL *)Ptr);
177 NativeError= mysql_errno((MYSQL *)Ptr);
178 break;
179 case SQL_HANDLE_STMT:
180 Sqlstate= (char *)mysql_stmt_sqlstate((MYSQL_STMT *)Ptr);
181 Errormsg= (char *)mysql_stmt_error((MYSQL_STMT *)Ptr);
182 NativeError= mysql_stmt_errno((MYSQL_STMT *)Ptr);
183 break;
184 }
185 /* work-around of probalby a bug in mariadb_stmt_execute_direct, that returns 1160 in case of lost connection */
186 if ((NativeError == 2013 || NativeError == 2006 || NativeError == 1160) && (strcmp(Sqlstate, "HY000") == 0 || strcmp(Sqlstate, "00000") == 0))
187 {
188 Sqlstate= "08S01";
189 }
190
191 Error->ReturnValue= SQL_ERROR;
192 if (Errormsg)
193 {
194 strcpy_s(Error->SqlErrorMsg + Error->PrefixLen, SQL_MAX_MESSAGE_LENGTH + 1 - Error->PrefixLen, Errormsg);
195 }
196 if (Sqlstate)
197 strcpy_s(Error->SqlState, SQLSTATE_LENGTH + 1, Sqlstate);
198 Error->NativeError= NativeError;
199 if (Error->SqlState[0] == '0')
200 Error->ReturnValue= (Error->SqlState[1] == '0') ? SQL_SUCCESS :
201 (Error->SqlState[1] == '1') ? SQL_SUCCESS_WITH_INFO : SQL_ERROR;
202
203 return Error->ReturnValue;
204 }
205
206 /* {{{ MADB_SetError */
207 SQLRETURN MADB_SetError(MADB_Error *Error,
208 unsigned int SqlErrorCode,
209 const char *NativeErrorMsg,
210 unsigned int NativeError)
211 {
212 unsigned int ErrorCode= SqlErrorCode;
213
214 Error->ErrorNum= 0;
215 if ((NativeError == 2013 || NativeError == 2006 || NativeError == 1160) && SqlErrorCode == MADB_ERR_HY000)
216 ErrorCode= MADB_ERR_08S01;
217
218 Error->ErrRecord= &MADB_ErrorList[ErrorCode];
219
220 Error->ReturnValue= SQL_ERROR;
221
222 if (NativeErrorMsg)
223 {
224 strcpy_s(Error->SqlErrorMsg + Error->PrefixLen, SQL_MAX_MESSAGE_LENGTH + 1 - Error->PrefixLen, NativeErrorMsg);
225 }
226 else
227 {
228 strcpy_s(Error->SqlErrorMsg + Error->PrefixLen, SQL_MAX_MESSAGE_LENGTH + 1 - Error->PrefixLen,
229 MADB_ErrorList[ErrorCode].SqlErrorMsg);
230 }
231 strcpy_s(Error->SqlState, SQLSTATE_LENGTH + 1, MADB_ErrorList[ErrorCode].SqlState);
232 Error->NativeError= NativeError;
233 /* Check the return code */
234 if (Error->SqlState[0] == '0')
235 Error->ReturnValue= (Error->SqlState[1] == '0') ? SQL_SUCCESS :
236 (Error->SqlState[1] == '1') ? SQL_SUCCESS_WITH_INFO : SQL_ERROR;
237
238 return Error->ReturnValue;
239 }
240 /* }}} */
241
242 /* {{{ MADB_CopyError */
243 void MADB_CopyError(MADB_Error *ErrorTo, MADB_Error *ErrorFrom)
244 {
245 ErrorTo->NativeError= ErrorFrom->NativeError;
246 ErrorTo->ReturnValue= ErrorFrom->ReturnValue;
247 ErrorTo->PrefixLen= ErrorFrom->PrefixLen;
248 strcpy_s(ErrorTo->SqlState, SQLSTATE_LENGTH + 1, ErrorFrom->SqlState);
249 strcpy_s(ErrorTo->SqlErrorMsg, SQL_MAX_MESSAGE_LENGTH + 1, ErrorFrom->SqlErrorMsg);
250 }
251 /* }}} */
252
253 /* {{{ MADB_GetDiagRec */
254 SQLRETURN MADB_GetDiagRec(MADB_Error *Err, SQLSMALLINT RecNumber,
255 void *SQLState, SQLINTEGER *NativeErrorPtr,
256 void *MessageText, SQLSMALLINT BufferLength,
257 SQLSMALLINT *TextLengthPtr, my_bool isWChar,
258 SQLINTEGER OdbcVersion)
259 {
260 MADB_Error InternalError;
261 char *SqlStateVersion= Err->SqlState;
262 SQLSMALLINT Length= 0;
263
264 InternalError.PrefixLen= 0;
265 MADB_CLEAR_ERROR(&InternalError);
266 if (RecNumber > 1)
267 return SQL_NO_DATA;
268
269 /* check if we have to map the SQLState to ODBC version 2 state */
270 if (OdbcVersion == SQL_OV_ODBC2)
271 {
272 int i= 0;
273 while (MADB_ErrorList[i].SqlState[0])
274 {
275 if (strcmp(Err->SqlState, MADB_ErrorList[i].SqlState) == 0)
276 {
277 if (MADB_ErrorList[i].SqlStateV2[0])
278 SqlStateVersion= MADB_ErrorList[i].SqlStateV2;
279 break;
280 }
281 ++i;
282 }
283 }
284
285 if (NativeErrorPtr)
286 *NativeErrorPtr= Err->NativeError;
287 if (SQLState)
288 MADB_SetString(isWChar ? &utf8 : 0, (void *)SQLState, SQL_SQLSTATE_SIZE + 1,
289 SqlStateVersion, SQL_SQLSTATE_SIZE, &InternalError);
290 if (MessageText)
291 Length= (SQLSMALLINT)MADB_SetString(isWChar ? &utf8 : 0, (void*)MessageText, BufferLength,
292 Err->SqlErrorMsg, strlen(Err->SqlErrorMsg), &InternalError);
293 if (TextLengthPtr)
294 *TextLengthPtr= (SQLSMALLINT)strlen(Err->SqlErrorMsg);
295
296 if (!MessageText || !BufferLength)
297 return SQL_SUCCESS;
298 return InternalError.ReturnValue;
299 }
300 /* }}} */
301
302 /* {{{ MADB_GetDiagField */
303 SQLRETURN MADB_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
304 SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, SQLPOINTER
305 DiagInfoPtr, SQLSMALLINT BufferLength,
306 SQLSMALLINT *StringLengthPtr, my_bool isWChar)
307 {
308 MADB_Error *Err= NULL;
309 MADB_Stmt *Stmt= NULL;
310 MADB_Desc *Desc= NULL;
311 MADB_Dbc *Dbc= NULL;
312 MADB_Env *Env= NULL;
313 MADB_Error Error;
314 SQLLEN Length;
315
316 if (StringLengthPtr)
317 *StringLengthPtr= 0;
318
319 Error.PrefixLen= 0;
320 MADB_CLEAR_ERROR(&Error);
321
322 if (RecNumber > 1)
323 return SQL_NO_DATA;
324
325 switch(HandleType) {
326 case SQL_HANDLE_DBC:
327 Dbc= (MADB_Dbc *)Handle;
328 Err= &Dbc->Error;
329 break;
330 case SQL_HANDLE_STMT:
331 Stmt= (MADB_Stmt *)Handle;
332 Err= &Stmt->Error;
333 break;
334 case SQL_HANDLE_ENV:
335 Env= (MADB_Env *)Handle;
336 Err= &Env->Error;
337 break;
338 case SQL_HANDLE_DESC:
339 Desc= (MADB_Desc *)Handle;
340 Err= &Desc->Error;
341 break;
342 default:
343 return SQL_INVALID_HANDLE;
344 }
345
346 switch(DiagIdentifier) {
347 case SQL_DIAG_CURSOR_ROW_COUNT:
348 if (!Stmt)
349 return SQL_ERROR;
350 *(SQLLEN *)DiagInfoPtr= (Stmt->result) ?(SQLLEN)mysql_stmt_num_rows(Stmt->stmt) : 0;
351 break;
352 case SQL_DIAG_DYNAMIC_FUNCTION:
353 if (!Stmt)
354 return SQL_ERROR;
355 /* Todo */
356 break;
357 case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
358 if (!Stmt)
359 return SQL_ERROR;
360 *(SQLINTEGER *)DiagInfoPtr= 0;
361 break;
362 case SQL_DIAG_NUMBER:
363 *(SQLINTEGER *)DiagInfoPtr= 1;
364 break;
365 case SQL_DIAG_RETURNCODE:
366 *(SQLRETURN *)DiagInfoPtr= Err->ReturnValue;
367 break;
368 case SQL_DIAG_ROW_COUNT:
369 if (HandleType != SQL_HANDLE_STMT ||
370 !Stmt)
371 return SQL_ERROR;
372 *(SQLLEN *)DiagInfoPtr= (Stmt->stmt) ? (SQLLEN)mysql_stmt_affected_rows(Stmt->stmt) : 0;
373 break;
374 case SQL_DIAG_CLASS_ORIGIN:
375 Length= MADB_SetString(isWChar ? &utf8 : 0, DiagInfoPtr, isWChar ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
376 strncmp(Err->SqlState, "IM", 2)== 0 ? "ODBC 3.0" : "ISO 9075", SQL_NTS, &Error);
377 if (StringLengthPtr)
378 *StringLengthPtr= (SQLSMALLINT)Length;
379 break;
380 case SQL_DIAG_COLUMN_NUMBER:
381 *(SQLINTEGER *)DiagInfoPtr= SQL_COLUMN_NUMBER_UNKNOWN;
382 break;
383 case SQL_DIAG_CONNECTION_NAME:
384 /* MariaDB ODBC Driver always returns an empty string */
385 if (StringLengthPtr)
386 *StringLengthPtr= 0;
387 DiagInfoPtr= (isWChar) ? (SQLPOINTER)L"" : (SQLPOINTER)"";
388 break;
389 case SQL_DIAG_MESSAGE_TEXT:
390 Length= MADB_SetString(isWChar ? &utf8 : 0, DiagInfoPtr, isWChar ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
391 Err->SqlErrorMsg, strlen(Err->SqlErrorMsg), &Error);
392 if (StringLengthPtr)
393 *StringLengthPtr= (SQLSMALLINT)Length;
394 break;
395 case SQL_DIAG_NATIVE:
396 *(SQLINTEGER *)DiagInfoPtr= Err->NativeError;
397 break;
398 case SQL_DIAG_ROW_NUMBER:
399 if (HandleType != SQL_HANDLE_STMT ||
400 RecNumber < 1)
401 return SQL_ERROR;
402 *(SQLLEN*)DiagInfoPtr= SQL_ROW_NUMBER_UNKNOWN;
403 break;
404 case SQL_DIAG_SERVER_NAME:
405 {
406 char *ServerName= "";
407 if (Stmt && Stmt->stmt)
408 ServerName= Stmt->stmt->mysql->host;
409 else if (Dbc && Dbc->mariadb)
410 ServerName= Dbc->mariadb->host;
411 Length= MADB_SetString(isWChar ? &utf8 : 0, DiagInfoPtr,
412 isWChar ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
413 ServerName ? ServerName : "", ServerName ? strlen(ServerName) : 0, &Error);
414 if (StringLengthPtr)
415 *StringLengthPtr= (SQLSMALLINT)Length;
416 }
417 break;
418 case SQL_DIAG_SQLSTATE:
419 Length= MADB_SetString(isWChar ? &utf8 : 0, DiagInfoPtr,
420 isWChar ? BufferLength / sizeof(SQLWCHAR) : BufferLength, Err->SqlState, strlen(Err->SqlState), &Error);
421 if (StringLengthPtr)
422 *StringLengthPtr= (SQLSMALLINT)Length;
423
424 break;
425 case SQL_DIAG_SUBCLASS_ORIGIN:
426 Length= MADB_SetString(isWChar ? &utf8 : 0, DiagInfoPtr,
427 isWChar ? BufferLength / sizeof(SQLWCHAR) : BufferLength, "ODBC 3.0", 8, &Error);
428 if (StringLengthPtr)
429 *StringLengthPtr= (SQLSMALLINT)Length;
430 break;
431 default:
432 return SQL_ERROR;
433 }
434 if (isWChar && StringLengthPtr)
435 *StringLengthPtr*= sizeof(SQLWCHAR);
436 return Error.ReturnValue;
437 }
0 /************************************************************************************
1 Copyright (C) 2013,2015 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_error_h_
19 #define _ma_error_h_
20
21 extern MADB_ERROR MADB_ErrorList[];
22
23 enum enum_madb_error {
24 MADB_ERR_00000=0,
25 MADB_ERR_01000,
26 MADB_ERR_01001,
27 MADB_ERR_01002,
28 MADB_ERR_01003,
29 MADB_ERR_01004,
30 MADB_ERR_01006,
31 MADB_ERR_01007,
32 MADB_ERR_01S00,
33 MADB_ERR_01S01,
34 MADB_ERR_01S02,
35 MADB_ERR_01S06,
36 MADB_ERR_01S07,
37 MADB_ERR_01S08,
38 MADB_ERR_01S09,
39 MADB_ERR_07001,
40 MADB_ERR_07002,
41 MADB_ERR_07005,
42 MADB_ERR_07006,
43 MADB_ERR_07009,
44 MADB_ERR_07S01,
45 MADB_ERR_08001,
46 MADB_ERR_08002,
47 MADB_ERR_08003,
48 MADB_ERR_08004,
49 MADB_ERR_08007,
50 MADB_ERR_08S01,
51 MADB_ERR_21S01,
52 MADB_ERR_21S02,
53 MADB_ERR_22001,
54 MADB_ERR_22002,
55 MADB_ERR_22003,
56 MADB_ERR_22007,
57 MADB_ERR_22008,
58 MADB_ERR_22012,
59 MADB_ERR_22015,
60 MADB_ERR_22018,
61 MADB_ERR_22019,
62 MADB_ERR_22025,
63 MADB_ERR_22026,
64 MADB_ERR_23000,
65 MADB_ERR_24000,
66 MADB_ERR_25000,
67 MADB_ERR_25S01,
68 MADB_ERR_25S02,
69 MADB_ERR_25S03,
70 MADB_ERR_28000,
71 MADB_ERR_34000,
72 MADB_ERR_3C000,
73 MADB_ERR_3D000,
74 MADB_ERR_3F000,
75 MADB_ERR_40001,
76 MADB_ERR_40002,
77 MADB_ERR_40003,
78 MADB_ERR_42000,
79 MADB_ERR_42S01,
80 MADB_ERR_42S02,
81 MADB_ERR_42S11,
82 MADB_ERR_42S12,
83 MADB_ERR_42S21,
84 MADB_ERR_42S22,
85 MADB_ERR_44000,
86 MADB_ERR_HY000,
87 MADB_ERR_HY001,
88 MADB_ERR_HY003,
89 MADB_ERR_HY004,
90 MADB_ERR_HY007,
91 MADB_ERR_HY008,
92 MADB_ERR_HY009,
93 MADB_ERR_HY010,
94 MADB_ERR_HY011,
95 MADB_ERR_HY012,
96 MADB_ERR_HY013,
97 MADB_ERR_HY014,
98 MADB_ERR_HY015,
99 MADB_ERR_HY016,
100 MADB_ERR_HY017,
101 MADB_ERR_HY018,
102 MADB_ERR_HY019,
103 MADB_ERR_HY020,
104 MADB_ERR_HY021,
105 MADB_ERR_HY024,
106 MADB_ERR_HY090,
107 MADB_ERR_HY091,
108 MADB_ERR_HY092,
109 MADB_ERR_HY095,
110 MADB_ERR_HY096,
111 MADB_ERR_HY097,
112 MADB_ERR_HY098,
113 MADB_ERR_HY099,
114 MADB_ERR_HY100,
115 MADB_ERR_HY101,
116 MADB_ERR_HY103,
117 MADB_ERR_HY104,
118 MADB_ERR_HY105,
119 MADB_ERR_HY106,
120 MADB_ERR_HY107,
121 MADB_ERR_HY109,
122 MADB_ERR_HY110,
123 MADB_ERR_HY111,
124 MADB_ERR_HYC00,
125 MADB_ERR_HYT00,
126 MADB_ERR_HYT01,
127 MADB_ERR_IM001,
128 MADB_ERR_IM002,
129 MADB_ERR_IM003,
130 MADB_ERR_IM004,
131 MADB_ERR_IM005,
132 MADB_ERR_IM006,
133 MADB_ERR_IM007,
134 MADB_ERR_IM008,
135 MADB_ERR_IM009,
136 MADB_ERR_IM010,
137 MADB_ERR_IM011,
138 MADB_ERR_IM012,
139 MADB_ERR_IM013,
140 MADB_ERR_IM014,
141 MADB_ERR_IM015,
142 MADB_ERR_S1000,
143 MADB_ERR_S1107,
144 MADB_ERR_S1C00,
145 };
146 char* MADB_PutErrorPrefix(MADB_Dbc *dbc, MADB_Error *error);
147
148 SQLRETURN MADB_SetError(MADB_Error *Error, unsigned int SqlErrorCode, const char *SqlErrorMsg, unsigned int NativeError);
149 SQLRETURN MADB_SetNativeError(MADB_Error *Error, SQLSMALLINT HandleType, void *Ptr);
150 void MADB_CopyError(MADB_Error *ErrorTo, MADB_Error *ErrorFrom);
151 SQLRETURN MADB_GetDiagRec(MADB_Error *Err, SQLSMALLINT RecNumber,
152 void *SQLState, SQLINTEGER *NativeErrorPtr,
153 void *MessageText, SQLSMALLINT BufferLength,
154 SQLSMALLINT *TextLengthPtr, my_bool isWChar,
155 SQLINTEGER OdbcVersion);
156 SQLRETURN MADB_GetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
157 SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, SQLPOINTER
158 DiagInfoPtr, SQLSMALLINT BufferLength,
159 SQLSMALLINT *StringLengthPtr, my_bool isWChar);
160
161 #define MADB_CLEAR_ERROR(a) \
162 strcpy_s((a)->SqlState, SQL_SQLSTATE_SIZE+1, MADB_ErrorList[MADB_ERR_00000].SqlState); \
163 (a)->SqlErrorMsg[(a)->PrefixLen]= 0; \
164 (a)->NativeError= 0;\
165 (a)->ReturnValue= SQL_SUCCESS;\
166 (a)->ErrorNum= 0;
167
168 #define MADB_CLEAR_HANDLE_ERROR(handle_type, handle) \
169 switch (handle_type) { \
170 case SQL_HANDLE_ENV: \
171 MADB_CLEAR_ERROR(&((MADB_Env *)Handle)->Error); \
172 break; \
173 case SQL_HANDLE_DBC: \
174 MADB_CLEAR_ERROR(&((MADB_Dbc *)Handle)->Error); \
175 break; \
176 case SQL_HANDLE_STMT:\
177 MADB_CLEAR_ERROR(&((MADB_Stmt *)Handle)->Error); \
178 }
179
180 #define MADB_CHECK_HANDLE_CLEAR_ERROR(handle_type, handle) \
181 if (handle == 0) return SQL_INVALID_HANDLE;\
182 MADB_CLEAR_HANDLE_ERROR(handle_type, handle) \
183
184
185 #define MADB_NOT_IMPLEMENTED(HANDLE)\
186 MADB_SetError(&(HANDLE)->Error, MADB_ERR_IM001, NULL, 0);\
187 return SQL_ERROR;
188
189 #define MADB_CHECK_ATTRIBUTE(Handle, Attr, ValidAttrs)\
190 {\
191 SQLULEN x=1, ok=0, my_attr=(SQLULEN)(Attr);\
192 while (x <= ValidAttrs[0] && !ok)\
193 if ((ok= ValidAttrs[x++] == my_attr))\
194 if (!ok)\
195 {\
196 MADB_SetError(&(Handle)->Error,MADB_ERR_HY024, NULL, 0);\
197 return (Handle)->Error.ReturnValue;\
198 }\
199 }
200
201 #endif /* _ma_error_h_ */
0 /************************************************************************************
1 Copyright (C) 2013, 2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19 #include <stdint.h>
20
21 #define MADB_FIELD_IS_BINARY(_field) ((_field)->charsetnr == BINARY_CHARSETNR)
22
23 void CloseMultiStatements(MADB_Stmt *Stmt)
24 {
25 unsigned int i;
26
27 for (i=0; i < STMT_COUNT(Stmt->Query); ++i)
28 {
29 MDBUG_C_PRINT(Stmt->Connection, "-->closing %0x", Stmt->MultiStmts[i]);
30 if (Stmt->MultiStmts[i] != NULL)
31 {
32 mysql_stmt_close(Stmt->MultiStmts[i]);
33 }
34 }
35 MADB_FREE(Stmt->MultiStmts);
36 Stmt->stmt= NULL;
37 }
38
39
40 MYSQL_STMT* MADB_NewStmtHandle(MADB_Stmt *Stmt)
41 {
42 static const my_bool UpdateMaxLength= 1;
43 MYSQL_STMT* stmt= mysql_stmt_init(Stmt->Connection->mariadb);
44
45 if (stmt != NULL)
46 {
47 mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &UpdateMaxLength);
48 }
49 else
50 {
51 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
52 }
53
54 return stmt;
55 }
56
57 /* Required, but not sufficient condition */
58 BOOL QueryIsPossiblyMultistmt(MADB_QUERY *Query)
59 {
60 return Query->QueryType != MADB_QUERY_CREATE_PROC && Query->QueryType != MADB_QUERY_CREATE_FUNC &&
61 Query->QueryType != MADB_QUERY_CREATE_DEFINER;
62 }
63
64
65 /* Trims spaces and/or ';' at the end of query */
66 int SqlRtrim(char *StmtStr, int Length)
67 {
68 if (Length > 0)
69 {
70 char *end= StmtStr + Length - 1;
71 while (end > StmtStr && (isspace(0x000000ff & *end) || *end == ';'))
72 {
73 *end= '\0';
74 --end;
75 --Length;
76 }
77 }
78
79 return Length;
80 }
81
82
83 unsigned int GetMultiStatements(MADB_Stmt *Stmt, BOOL ExecDirect)
84 {
85 int i= 0;
86 unsigned int MaxParams= 0;
87 char *p= Stmt->Query.RefinedText;
88
89 Stmt->MultiStmtNr= 0;
90 Stmt->MultiStmts= (MYSQL_STMT **)MADB_CALLOC(sizeof(MYSQL_STMT) * STMT_COUNT(Stmt->Query));
91
92 while (p < Stmt->Query.RefinedText + Stmt->Query.RefinedLength)
93 {
94 Stmt->MultiStmts[i]= i == 0 ? Stmt->stmt : MADB_NewStmtHandle(Stmt);
95 MDBUG_C_PRINT(Stmt->Connection, "-->inited&preparing %0x(%d,%s)", Stmt->MultiStmts[i], i, p);
96
97 if (mysql_stmt_prepare(Stmt->MultiStmts[i], p, (unsigned long)strlen(p)))
98 {
99 MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->MultiStmts[i]);
100 CloseMultiStatements(Stmt);
101
102 /* Last paranoid attempt make sure that we did not have a parsing error.
103 More to preserve "backward-compatimility" - we did this before, but before trying to
104 prepare "multi-statement". */
105 if (i == 0 && Stmt->Error.NativeError !=1295 /*ER_UNSUPPORTED_PS*/)
106 {
107 Stmt->stmt= MADB_NewStmtHandle(Stmt);
108 if (mysql_stmt_prepare(Stmt->stmt, STMT_STRING(Stmt), (unsigned long)strlen(STMT_STRING(Stmt))))
109 {
110 MADB_STMT_CLOSE_STMT(Stmt);
111 }
112 else
113 {
114 MADB_DeleteSubqueries(&Stmt->Query);
115 return 0;
116 }
117 }
118 return 1;
119 }
120 if (mysql_stmt_param_count(Stmt->MultiStmts[i]) > MaxParams)
121 {
122 MaxParams= mysql_stmt_param_count(Stmt->MultiStmts[i]);
123 }
124 p+= strlen(p) + 1;
125 ++i;
126 }
127
128 if (MaxParams)
129 {
130 Stmt->params= (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * MaxParams);
131 }
132
133 return 0;
134 }
135
136
137 my_bool MADB_CheckPtrLength(SQLINTEGER MaxLength, char *Ptr, SQLINTEGER NameLen)
138 {
139 if(!Ptr)
140 return TRUE;
141 if ((NameLen == SQL_NTS && strlen(Ptr) >(size_t) MaxLength) || NameLen > MaxLength)
142 return FALSE;
143 return TRUE;
144 }
145
146 int MADB_GetWCharType(int Type)
147 {
148 switch (Type) {
149 case SQL_CHAR:
150 return SQL_WCHAR;
151 case SQL_VARCHAR:
152 return SQL_WVARCHAR;
153 case SQL_LONGVARCHAR:
154 return SQL_WLONGVARCHAR;
155 default:
156 return Type;
157 }
158 }
159
160 int MADB_KeyTypeCount(MADB_Dbc *Connection, char *TableName, int KeyFlag)
161 {
162 int Count= 0;
163 unsigned int i;
164 char StmtStr[1024];
165 char *p= StmtStr;
166 char Database[65]= {'\0'};
167 MADB_Stmt *Stmt= NULL;
168 MADB_Stmt *KeyStmt;
169
170 Connection->Methods->GetAttr(Connection, SQL_ATTR_CURRENT_CATALOG, Database, 65, NULL, FALSE);
171 p+= _snprintf(p, 1024, "SELECT * FROM ");
172 if (Database[0] != '\0')
173 {
174 p+= _snprintf(p, sizeof(StmtStr) - strlen(p), "`%s`.", Database);
175 }
176 p+= _snprintf(p, sizeof(StmtStr) - strlen(p), "%s LIMIT 0", TableName);
177 if (MA_SQLAllocHandle(SQL_HANDLE_STMT, (SQLHANDLE)Connection, (SQLHANDLE*)&Stmt) == SQL_ERROR ||
178 Stmt->Methods->ExecDirect(Stmt, (char *)StmtStr, SQL_NTS) == SQL_ERROR ||
179 Stmt->Methods->Fetch(Stmt) == SQL_ERROR)
180 {
181 goto end;
182 }
183 KeyStmt= (MADB_Stmt *)Stmt;
184 for (i=0; i < mysql_stmt_field_count(KeyStmt->stmt); i++)
185 if (KeyStmt->stmt->fields[i].flags & KeyFlag)
186 Count++;
187 end:
188 if (Stmt)
189 Stmt->Methods->StmtFree(Stmt, SQL_DROP);
190 return Count;
191 }
192
193 /* {{{ MADB_get_single_row */
194 my_bool MADB_get_single_row(MADB_Dbc *Connection,
195 const char *StmtString,
196 SQLINTEGER Length,
197 unsigned int NumCols,
198 char **Buffers,
199 size_t *Buffer_Lengths)
200 {
201 MYSQL_RES *result;
202 MYSQL_ROW row;
203
204 LOCK_MARIADB(Connection);
205 if (mysql_real_query(Connection->mariadb, StmtString, Length) ||
206 mysql_field_count(Connection->mariadb) < NumCols)
207 return 1;
208
209 if ((result= mysql_store_result(Connection->mariadb)) &&
210 (row= mysql_fetch_row(result)))
211 {
212 unsigned int i;
213
214 UNLOCK_MARIADB(Connection);
215
216 for (i=0; i < NumCols; i++)
217 strncpy_s(Buffers[i], Buffer_Lengths[i], row[i], Connection->mariadb->fields[i].max_length);
218 mysql_free_result(result);
219 return 0;
220 }
221 UNLOCK_MARIADB(Connection);
222
223 return 1;
224 }
225 /* }}} */
226
227 /* {{{ MADB_CheckODBCType */
228 BOOL MADB_CheckODBCType(SQLSMALLINT Type)
229 {
230 switch(Type)
231 {
232 case SQL_C_CHAR:
233 case SQL_C_WCHAR:
234 case SQL_C_SSHORT:
235 case SQL_C_SHORT:
236 case SQL_C_USHORT:
237 case SQL_C_SLONG:
238 case SQL_C_LONG:
239 case SQL_C_ULONG:
240 case SQL_C_FLOAT:
241 case SQL_C_DOUBLE:
242 case SQL_C_BIT:
243 case SQL_C_STINYINT:
244 case SQL_C_TINYINT:
245 case SQL_C_UTINYINT:
246 case SQL_C_SBIGINT:
247 case SQL_C_UBIGINT:
248 case SQL_C_BINARY:
249 case SQL_C_TYPE_DATE:
250 case SQL_C_TYPE_TIME:
251 case SQL_C_TYPE_TIMESTAMP:
252 case SQL_C_NUMERIC:
253 #if (ODBCVER>=0x0350)
254 case SQL_C_GUID:
255 #endif
256 case SQL_C_DEFAULT:
257 return TRUE;
258 default:
259 return FALSE;
260 }
261 }
262
263 /* {{{ MADB_GetTypeFromConciseType */
264 SQLSMALLINT MADB_GetTypeFromConciseType(SQLSMALLINT ConciseType)
265 {
266 switch (ConciseType)
267 {
268 /* todo: support for interval. currently we map only date/time types */
269 case SQL_C_DATE:
270 case SQL_C_TIME:
271 case SQL_C_TIMESTAMP:
272 case SQL_TYPE_DATE:
273 case SQL_TYPE_TIME:
274 case SQL_TYPE_TIMESTAMP:
275 return SQL_DATETIME;
276 case SQL_C_INTERVAL_YEAR:
277 case SQL_C_INTERVAL_YEAR_TO_MONTH:
278 case SQL_C_INTERVAL_MONTH:
279 case SQL_C_INTERVAL_DAY:
280 case SQL_C_INTERVAL_DAY_TO_HOUR:
281 case SQL_C_INTERVAL_DAY_TO_MINUTE:
282 case SQL_C_INTERVAL_DAY_TO_SECOND:
283 case SQL_C_INTERVAL_HOUR:
284 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
285 case SQL_C_INTERVAL_HOUR_TO_SECOND:
286 case SQL_C_INTERVAL_MINUTE:
287 case SQL_C_INTERVAL_MINUTE_TO_SECOND:
288 case SQL_C_INTERVAL_SECOND:
289 return SQL_INTERVAL;
290 default:
291 return ConciseType;
292 }
293 }
294 /* }}} */
295
296 /* {{{ MADB_GetTypeName */
297 char *MADB_GetTypeName(MYSQL_FIELD *Field)
298 {
299 switch(Field->type) {
300 case MYSQL_TYPE_DECIMAL:
301 case MYSQL_TYPE_NEWDECIMAL:
302 return "decimal";
303 case MYSQL_TYPE_NULL:
304 return "null";
305 case MYSQL_TYPE_TINY:
306 return (Field->flags & NUM_FLAG) ? "tinyint" : "char";
307 case MYSQL_TYPE_SHORT:
308 return "smallint";
309 case MYSQL_TYPE_LONG:
310 return "integer";
311 case MYSQL_TYPE_FLOAT:
312 return "float";
313 case MYSQL_TYPE_DOUBLE:
314 return "double";
315 case MYSQL_TYPE_TIMESTAMP:
316 return "timestamp";
317 case MYSQL_TYPE_LONGLONG:
318 return "bigint";
319 case MYSQL_TYPE_INT24:
320 return "mediumint";
321 case MYSQL_TYPE_DATE:
322 return "date";
323 case MYSQL_TYPE_TIME:
324 return "time";
325 case MYSQL_TYPE_DATETIME:
326 return "datetime";
327 case MYSQL_TYPE_YEAR:
328 return "year";
329 case MYSQL_TYPE_NEWDATE:
330 return "date";
331 case MYSQL_TYPE_VARCHAR:
332 case MYSQL_TYPE_VAR_STRING:
333 return MADB_FIELD_IS_BINARY(Field) ? "varbinary" : "varchar";
334 case MYSQL_TYPE_BIT:
335 return "bit";
336 case MYSQL_TYPE_ENUM:
337 return "enum";
338 case MYSQL_TYPE_SET:
339 return "set";
340 case MYSQL_TYPE_TINY_BLOB:
341 return MADB_FIELD_IS_BINARY(Field) ? "tinyblob" : "tinytext";
342 case MYSQL_TYPE_MEDIUM_BLOB:
343 return MADB_FIELD_IS_BINARY(Field) ? "mediumblob" : "mediumtext";
344 case MYSQL_TYPE_LONG_BLOB:
345 return MADB_FIELD_IS_BINARY(Field) ? "longblob" : "longtext";
346 case MYSQL_TYPE_BLOB:
347 return MADB_FIELD_IS_BINARY(Field) ? "blob" : "text";
348 case MYSQL_TYPE_STRING:
349 return MADB_FIELD_IS_BINARY(Field) ? "binary" : "char";
350 case MYSQL_TYPE_GEOMETRY:
351 return "geometry";
352 default:
353 return "";
354 }
355 }
356 /* }}} */
357
358 MYSQL_RES *MADB_GetDefaultColumnValues(MADB_Stmt *Stmt, MYSQL_FIELD *fields)
359 {
360 MADB_DynString DynStr;
361 unsigned int i;
362 MYSQL_RES *result= NULL;
363
364 MADB_InitDynamicString(&DynStr, "SELECT COLUMN_NAME, COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='", 512, 512);
365 if (MADB_DynstrAppend(&DynStr, fields[0].db) ||
366 MADB_DynstrAppend(&DynStr, "' AND TABLE_NAME='") ||
367 MADB_DynstrAppend(&DynStr, fields[0].org_table) ||
368 MADB_DynstrAppend(&DynStr, "' AND COLUMN_NAME IN ("))
369 goto error;
370
371 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
372 {
373 MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ);
374
375 if (!Rec->inUse || MADB_ColumnIgnoredInAllRows(Stmt->Ard, Rec) == TRUE)
376 {
377 continue;
378 }
379 if (MADB_DynstrAppend(&DynStr, i > 0 ? ",'" : "'") ||
380 MADB_DynstrAppend(&DynStr, fields[i].org_name) ||
381 MADB_DynstrAppend(&DynStr, "'"))
382 {
383 goto error;
384 }
385 }
386 if (MADB_DynstrAppend(&DynStr, ") AND COLUMN_DEFAULT IS NOT NULL"))
387 goto error;
388
389 LOCK_MARIADB(Stmt->Connection);
390 if (mysql_query(Stmt->Connection->mariadb, DynStr.str))
391 goto error;
392 result= mysql_store_result(Stmt->Connection->mariadb);
393
394 error:
395 UNLOCK_MARIADB(Stmt->Connection);
396 MADB_DynstrFree(&DynStr);
397 return result;
398 }
399
400 char *MADB_GetDefaultColumnValue(MYSQL_RES *res, const char *Column)
401 {
402 MYSQL_ROW row;
403
404 if (res == NULL || !res->row_count)
405 return NULL;
406 mysql_data_seek(res, 0);
407 while ((row= mysql_fetch_row(res)))
408 {
409 if (_stricmp(row[0], Column) == 0)
410 return _strdup(row[1]);
411 }
412 return NULL;
413 }
414
415 SQLLEN MADB_GetDataSize(SQLSMALLINT SqlType, SQLLEN OctetLength, BOOL Unsigned,
416 SQLSMALLINT Precision, SQLSMALLINT Scale, const MARIADB_CHARSET_INFO *Charset)
417 {
418 switch(SqlType)
419 {
420 case SQL_BIT:
421 return 1;
422 case SQL_TINYINT:
423 return 3;
424 case SQL_SMALLINT:
425 return 5;
426 case SQL_INTEGER:
427 return 10;
428 case SQL_BIGINT:
429 return 20 - test(Unsigned != FALSE);
430 case SQL_REAL:
431 return 7;
432 case SQL_DOUBLE:
433 case SQL_FLOAT:
434 return 15;
435 case SQL_DECIMAL:
436 case SQL_NUMERIC:
437 return Precision;
438 case SQL_TYPE_DATE:
439 return SQL_DATE_LEN;
440 case SQL_TYPE_TIME:
441 return SQL_TIME_LEN + MADB_FRACTIONAL_PART(Scale);
442 case SQL_TYPE_TIMESTAMP:
443 return SQL_TIMESTAMP_LEN + MADB_FRACTIONAL_PART(Scale);
444 case SQL_BINARY:
445 case SQL_VARBINARY:
446 case SQL_LONGVARBINARY:
447 return OctetLength;
448 case SQL_GUID:
449 return 36;;
450 default:
451 {
452 if (Charset == NULL || Charset->char_maxlen < 2/*i.e.0||1*/)
453 {
454 return OctetLength;
455 }
456 else
457 {
458 return OctetLength/Charset->char_maxlen;
459 }
460 }
461 }
462 }
463
464 /* {{{ MADB_GetDisplaySize */
465 size_t MADB_GetDisplaySize(MYSQL_FIELD *Field, MARIADB_CHARSET_INFO *charset)
466 {
467 /* Todo: check these values with output from mysql --with-columntype-info */
468 switch (Field->type) {
469 case MYSQL_TYPE_NULL:
470 return 1;
471 case MYSQL_TYPE_BIT:
472 return (Field->length == 1) ? 1 : (Field->length + 7) / 8 * 2;
473 case MYSQL_TYPE_TINY:
474 return 4 - test(Field->flags & UNSIGNED_FLAG);
475 case MYSQL_TYPE_SHORT:
476 case MYSQL_TYPE_YEAR:
477 return 6 - test(Field->flags & UNSIGNED_FLAG);
478 case MYSQL_TYPE_INT24:
479 return 9 - test(Field->flags & UNSIGNED_FLAG);
480 case MYSQL_TYPE_LONG:
481 return 11 - test(Field->flags & UNSIGNED_FLAG);
482 case MYSQL_TYPE_LONGLONG:
483 return 20;
484 case MYSQL_TYPE_DOUBLE:
485 return 15;
486 case MYSQL_TYPE_FLOAT:
487 return 7;
488 case MYSQL_TYPE_DECIMAL:
489 case MYSQL_TYPE_NEWDECIMAL:
490 return Field->length;
491 case MYSQL_TYPE_DATE:
492 return SQL_DATE_LEN; /* YYYY-MM-DD */
493 case MYSQL_TYPE_TIME:
494 return SQL_TIME_LEN + MADB_FRACTIONAL_PART(Field->decimals); /* HH:MM:SS.ffffff */
495 case MYSQL_TYPE_NEWDATE:
496 case MYSQL_TYPE_TIMESTAMP:
497 case MYSQL_TYPE_DATETIME:
498 return SQL_TIMESTAMP_LEN + MADB_FRACTIONAL_PART(Field->decimals);
499 case MYSQL_TYPE_BLOB:
500 case MYSQL_TYPE_ENUM:
501 case MYSQL_TYPE_GEOMETRY:
502 case MYSQL_TYPE_LONG_BLOB:
503 case MYSQL_TYPE_MEDIUM_BLOB:
504 case MYSQL_TYPE_SET:
505 case MYSQL_TYPE_STRING:
506 case MYSQL_TYPE_TINY_BLOB:
507 case MYSQL_TYPE_VARCHAR:
508 case MYSQL_TYPE_VAR_STRING:
509 {
510 if (MADB_FIELD_IS_BINARY(Field))
511 {
512 return Field->length*2; /* ODBC specs says we should give 2 characters per byte to display binaray data in hex form */
513 }
514 else if (charset == NULL || charset->char_maxlen < 2/*i.e.0||1*/)
515 {
516 return Field->length;
517 }
518 else
519 {
520 return Field->length/charset->char_maxlen;
521 }
522 }
523 default:
524 return SQL_NO_TOTAL;
525 }
526 }
527 /* }}} */
528
529 /* {{{ MADB_GetOctetLength */
530 size_t MADB_GetOctetLength(MYSQL_FIELD *Field, unsigned short MaxCharLen)
531 {
532 size_t Length= MIN(MADB_INT_MAX32, Field->length);
533
534 switch (Field->type) {
535 case MYSQL_TYPE_NULL:
536 return 1;
537 case MYSQL_TYPE_BIT:
538 return (Field->length + 7) / 8;
539 case MYSQL_TYPE_TINY:
540 return 1;
541 case MYSQL_TYPE_YEAR:
542 case MYSQL_TYPE_SHORT:
543 return 2;
544 case MYSQL_TYPE_INT24:
545 return 3;
546 case MYSQL_TYPE_LONG:
547 return 4;
548 case MYSQL_TYPE_LONGLONG:
549 return 8;
550 case MYSQL_TYPE_DOUBLE:
551 return 8;
552 case MYSQL_TYPE_FLOAT:
553 return 4;
554 case MYSQL_TYPE_DECIMAL:
555 case MYSQL_TYPE_NEWDECIMAL:
556 return Field->length;
557 case MYSQL_TYPE_DATE:
558 return sizeof(SQL_DATE_STRUCT);
559 case MYSQL_TYPE_TIME:
560 return sizeof(SQL_TIME_STRUCT);
561 case MYSQL_TYPE_NEWDATE:
562 case MYSQL_TYPE_TIMESTAMP:
563 case MYSQL_TYPE_DATETIME:
564 return sizeof(SQL_TIMESTAMP_STRUCT);
565 case MYSQL_TYPE_BLOB:
566 case MYSQL_TYPE_ENUM:
567 case MYSQL_TYPE_GEOMETRY:
568 case MYSQL_TYPE_LONG_BLOB:
569 case MYSQL_TYPE_MEDIUM_BLOB:
570 case MYSQL_TYPE_TINY_BLOB:
571 return Length;
572 case MYSQL_TYPE_SET:
573 case MYSQL_TYPE_STRING:
574 case MYSQL_TYPE_VARCHAR:
575 case MYSQL_TYPE_VAR_STRING:
576 return Length; /* Field->length is calculated using current charset */
577 default:
578 return SQL_NO_TOTAL;
579 }
580 }
581 /* }}} */
582
583 /* {{{ MADB_GetDefaultType */
584 int MADB_GetDefaultType(int SQLDataType)
585 {
586 switch(SQLDataType)
587 {
588 case SQL_BIGINT:
589 return SQL_C_SBIGINT;
590 case SQL_BINARY:
591 return SQL_C_BINARY;
592 case SQL_BIT:
593 return SQL_C_BIT;
594 case SQL_CHAR:
595 return SQL_C_CHAR;
596 case SQL_DATE:
597 case SQL_TYPE_DATE:
598 return SQL_C_DATE;
599 case SQL_DECIMAL:
600 return SQL_C_CHAR;
601 case SQL_DOUBLE:
602 return SQL_C_DOUBLE;
603 case SQL_FLOAT:
604 return SQL_C_FLOAT;
605 case SQL_INTEGER:
606 return SQL_C_LONG;
607 case SQL_LONGVARBINARY:
608 return SQL_C_BINARY;
609 case SQL_LONGVARCHAR:
610 return SQL_C_CHAR;
611 case SQL_NUMERIC:
612 return SQL_C_CHAR;
613 case SQL_REAL:
614 return SQL_C_FLOAT;
615 case SQL_SMALLINT:
616 return SQL_C_SHORT;
617 case SQL_TIME:
618 case SQL_TYPE_TIME:
619 return SQL_C_TIME;
620 case SQL_TIMESTAMP:
621 case SQL_TYPE_TIMESTAMP:
622 return SQL_C_TIMESTAMP;
623 case SQL_TINYINT:
624 return SQL_C_TINYINT;
625 case SQL_VARBINARY:
626 return SQL_C_BINARY;
627 case SQL_VARCHAR:
628 return SQL_C_CHAR;
629 default:
630 return SQL_C_CHAR;
631 }
632 }
633 /* }}} */
634
635 /* {{{ MapMariadDbToOdbcType */
636 /* It's not quite right to mix here C and SQL types, even though constants are sort of equal */
637 SQLSMALLINT MapMariadDbToOdbcType(MYSQL_FIELD *field)
638 {
639 switch (field->type) {
640 case MYSQL_TYPE_BIT:
641 if (field->length > 1)
642 return SQL_BINARY;
643 return SQL_BIT;
644 case MYSQL_TYPE_NULL:
645 return SQL_VARCHAR;
646 case MYSQL_TYPE_TINY:
647 return field->flags & NUM_FLAG ? SQL_TINYINT : SQL_CHAR;
648 case MYSQL_TYPE_YEAR:
649 case MYSQL_TYPE_SHORT:
650 return SQL_SMALLINT;
651 case MYSQL_TYPE_INT24:
652 case MYSQL_TYPE_LONG:
653 return SQL_INTEGER;
654 case MYSQL_TYPE_FLOAT:
655 return SQL_REAL;
656 case MYSQL_TYPE_DOUBLE:
657 return SQL_DOUBLE;
658 case MYSQL_TYPE_TIMESTAMP:
659 case MYSQL_TYPE_DATETIME:
660 return SQL_TYPE_TIMESTAMP;
661 case MYSQL_TYPE_NEWDATE:
662 case MYSQL_TYPE_DATE:
663 return SQL_TYPE_DATE;
664 case MYSQL_TYPE_TIME:
665 return SQL_TYPE_TIME;
666 case MYSQL_TYPE_TINY_BLOB:
667 case MYSQL_TYPE_BLOB:
668 case MYSQL_TYPE_MEDIUM_BLOB:
669 case MYSQL_TYPE_LONG_BLOB:
670 return MADB_FIELD_IS_BINARY(field) ? SQL_LONGVARBINARY : SQL_LONGVARCHAR;
671 case MYSQL_TYPE_LONGLONG:
672 return SQL_BIGINT;
673 case MYSQL_TYPE_STRING:
674 return MADB_FIELD_IS_BINARY(field) ? SQL_BINARY : SQL_CHAR;
675 case MYSQL_TYPE_VAR_STRING:
676 return MADB_FIELD_IS_BINARY(field) ? SQL_VARBINARY : SQL_VARCHAR;
677 case MYSQL_TYPE_SET:
678 case MYSQL_TYPE_ENUM:
679 return SQL_CHAR;
680 case MYSQL_TYPE_GEOMETRY:
681 return SQL_LONGVARBINARY;
682 case MYSQL_TYPE_DECIMAL:
683 case MYSQL_TYPE_NEWDECIMAL:
684 return SQL_DECIMAL;
685 default:
686 return SQL_UNKNOWN_TYPE;
687 }
688 }
689
690 /* }}} */
691 /* {{{ MADB_GetTypeLength */
692 size_t MADB_GetTypeLength(SQLINTEGER SqlDataType, size_t Length)
693 {
694 switch(SqlDataType)
695 {
696 case SQL_C_BIT:
697 case SQL_C_TINYINT:
698 case SQL_C_STINYINT:
699 case SQL_C_UTINYINT:
700 return 1;
701 case SQL_C_SHORT:
702 case SQL_C_SSHORT:
703 case SQL_C_USHORT:
704 return 2;
705 case SQL_C_LONG:
706 case SQL_C_SLONG:
707 case SQL_C_ULONG:
708 return sizeof(SQLINTEGER);
709 case SQL_C_UBIGINT:
710 case SQL_C_SBIGINT:
711 return sizeof(long long);
712 case SQL_C_DOUBLE:
713 return sizeof(SQLDOUBLE);
714 case SQL_C_FLOAT:
715 return sizeof(SQLFLOAT);
716 case SQL_C_NUMERIC:
717 return sizeof(SQL_NUMERIC_STRUCT);
718 case SQL_C_TYPE_TIME:
719 case SQL_C_TIME:
720 return sizeof(SQL_TIME_STRUCT);
721 case SQL_C_TYPE_DATE:
722 case SQL_C_DATE:
723 return sizeof(SQL_DATE_STRUCT);
724 case SQL_C_TYPE_TIMESTAMP:
725 case SQL_C_TIMESTAMP:
726 return sizeof(SQL_TIMESTAMP_STRUCT);
727 default:
728 return Length;
729 }
730 }
731 /* }}} */
732
733 /* {{{ MADB_GetMaDBTypeAndLength */
734 int MADB_GetMaDBTypeAndLength(SQLINTEGER SqlDataType, my_bool *Unsigned, unsigned long *Length)
735 {
736 *Unsigned= 0;
737 switch(SqlDataType)
738 {
739 case SQL_C_BIT:
740 case SQL_C_TINYINT:
741 case SQL_C_STINYINT:
742 case SQL_C_UTINYINT:
743 *Length= 1;
744 *Unsigned= (SqlDataType == SQL_C_UTINYINT);
745
746 return MYSQL_TYPE_TINY;
747
748 case SQL_C_SHORT:
749 case SQL_C_SSHORT:
750 case SQL_C_USHORT:
751 *Length= 2;
752 *Unsigned= (SqlDataType == SQL_C_USHORT);
753
754 return MYSQL_TYPE_SHORT;
755
756 case SQL_C_LONG:
757 case SQL_C_SLONG:
758 case SQL_C_ULONG:
759 *Length= sizeof(SQLINTEGER);
760 *Unsigned= (SqlDataType == SQL_C_ULONG);
761 return MYSQL_TYPE_LONG;
762 case SQL_C_UBIGINT:
763 case SQL_C_SBIGINT:
764 *Length= sizeof(long long);
765 *Unsigned= (SqlDataType == SQL_C_UBIGINT);
766 return MYSQL_TYPE_LONGLONG;
767 case SQL_C_DOUBLE:
768 *Length= sizeof(SQLDOUBLE);
769 return MYSQL_TYPE_DOUBLE;
770 case SQL_C_FLOAT:
771 *Length =sizeof(SQLFLOAT);
772 return MYSQL_TYPE_FLOAT;
773 case SQL_C_NUMERIC:
774 /**Length= sizeof(SQL_NUMERIC_STRUCT);*/
775 return MYSQL_TYPE_DECIMAL;
776 case SQL_C_TYPE_TIME:
777 case SQL_C_TIME:
778 *Length= sizeof(SQL_TIME_STRUCT);
779 return MYSQL_TYPE_TIME;
780 case SQL_C_TYPE_DATE:
781 case SQL_C_DATE:
782 *Length= sizeof(SQL_DATE_STRUCT);
783 return MYSQL_TYPE_DATE;
784 case SQL_C_TYPE_TIMESTAMP:
785 case SQL_C_TIMESTAMP:
786 *Length= sizeof(SQL_TIMESTAMP_STRUCT);
787 return MYSQL_TYPE_TIMESTAMP;
788 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
789 case SQL_C_INTERVAL_HOUR_TO_SECOND:
790 *Length= sizeof(SQL_INTERVAL_STRUCT);
791 return MYSQL_TYPE_TIME;
792 case SQL_C_CHAR:
793 return MYSQL_TYPE_STRING;
794 default:
795 return MYSQL_TYPE_BLOB;
796 }
797 }
798 /* }}} */
799
800 void MADB_CopyOdbcTsToMadbTime(SQL_TIMESTAMP_STRUCT *Src, MYSQL_TIME *Dst)
801 {
802 Dst->year= Src->year;
803 Dst->month= Src->month;
804 Dst->day= Src->day;
805 Dst->hour= Src->hour;
806 Dst->minute= Src->minute;
807 Dst->second= Src->second;
808 Dst->second_part= Src->fraction / 1000;
809 }
810
811 void MADB_CopyMadbTimeToOdbcTs(MYSQL_TIME *Src, SQL_TIMESTAMP_STRUCT *Dst)
812 {
813 Dst->year= Src->year;
814 Dst->month= Src->month;
815 Dst->day= Src->day;
816 Dst->hour= Src->hour;
817 Dst->minute= Src->minute;
818 Dst->second= Src->second;
819 Dst->fraction= Src->second_part*1000;
820 }
821
822 SQLRETURN MADB_CopyMadbTimestamp(MADB_Stmt *Stmt, MYSQL_TIME *tm, SQLPOINTER DataPtr, SQLLEN *Length, SQLLEN *Ind,
823 SQLSMALLINT CType, SQLSMALLINT SqlType)
824 {
825 SQLLEN Dummy;
826
827 Length= Length == NULL ? &Dummy : Length;
828
829 switch(CType)
830 {
831 case SQL_C_TIMESTAMP:
832 case SQL_C_TYPE_TIMESTAMP:
833 {
834 SQL_TIMESTAMP_STRUCT *ts= (SQL_TIMESTAMP_STRUCT *)DataPtr;
835
836 if (ts != NULL)
837 {
838 /* If time converted to timestamp - fraction is set to 0, date is set to current date */
839 if (SqlType == SQL_TIME || SqlType == SQL_TYPE_TIME)
840 {
841 time_t sec_time;
842 struct tm * cur_tm;
843
844 sec_time= time(NULL);
845 cur_tm= localtime(&sec_time);
846
847 ts->year= 1900 + cur_tm->tm_year;
848 ts->month= cur_tm->tm_mon + 1;
849 ts->day= cur_tm->tm_mday;
850 ts->fraction= 0;
851 }
852 else
853 {
854 ts->year= tm->year;
855 ts->month= tm->month;
856 ts->day= tm->day;
857 ts->fraction= tm->second_part * 1000;
858 }
859 ts->hour= tm->hour;
860 ts->minute= tm->minute;
861 ts->second= tm->second;
862
863 if (ts->year + ts->month + ts->day + ts->hour + ts->minute + ts->fraction + ts->second == 0)
864 {
865 if (Ind != NULL)
866 {
867 *Ind= SQL_NULL_DATA;
868 }
869 else
870 {
871 return MADB_SetError(&Stmt->Error, MADB_ERR_22002, NULL, 0);
872 }
873 break;
874 }
875 }
876 *Length= sizeof(SQL_TIMESTAMP_STRUCT);
877 }
878 break;
879 case SQL_C_TIME:
880 case SQL_C_TYPE_TIME:
881 {
882 SQL_TIME_STRUCT *ts= (SQL_TIME_STRUCT *)DataPtr;
883
884 if (ts != NULL)
885 {
886 /* tm(buffer from MYSQL_BIND) can be NULL. And that happens if ts(app's buffer) is null */
887 if (!VALID_TIME(tm))
888 {
889 return MADB_SetError(&Stmt->Error, MADB_ERR_22007, NULL, 0);
890 }
891
892 ts->hour= tm->hour;
893 ts->minute= tm->minute;
894 ts->second= tm->second;
895
896 *Length= sizeof(SQL_TIME_STRUCT);
897
898 if (tm->second_part)
899 {
900 return MADB_SetError(&Stmt->Error, MADB_ERR_01S07, NULL, 0);
901 }
902 }
903 }
904 break;
905 case SQL_C_DATE:
906 case SQL_TYPE_DATE:
907 {
908 SQL_DATE_STRUCT *ts= (SQL_DATE_STRUCT *)DataPtr;
909
910 if (ts != NULL)
911 {
912 ts->year= tm->year;
913 ts->month= tm->month;
914 ts->day= tm->day;
915 if (ts->year + ts->month + ts->day == 0)
916 {
917 if (Ind != NULL)
918 {
919 *Ind= SQL_NULL_DATA;
920 }
921 else
922 {
923 return MADB_SetError(&Stmt->Error, MADB_ERR_22002, NULL, 0);
924 }
925 break;
926 }
927 }
928 *Length= sizeof(SQL_DATE_STRUCT);
929 }
930 break;
931 }
932
933 return SQL_SUCCESS;
934 }
935
936
937 void *GetBindOffset(MADB_Desc *Desc, MADB_DescRecord *Record, void *Ptr, SQLULEN RowNumber, size_t PtrSize)
938 {
939 size_t BindOffset= 0;
940
941 /* This is not quite clear - I'd imagine, that if BindOffset is set, then Ptr can be NULL.
942 Makes perfect sense in case of row-based binding - setting pointers to offset in structure, and BindOffset to the begin of array.
943 One of members would have 0 offset then. But specs are rather against that, and other drivers also don't support such interpretation */
944 if (Ptr == NULL)
945 {
946 return NULL;
947 }
948 if (Desc->Header.BindOffsetPtr != NULL)
949 {
950 BindOffset= (size_t)*Desc->Header.BindOffsetPtr;
951 }
952
953 /* row wise binding */
954 if (Desc->Header.BindType == SQL_BIND_BY_COLUMN ||
955 Desc->Header.BindType == SQL_PARAM_BIND_BY_COLUMN)
956 {
957 BindOffset+= PtrSize * RowNumber;
958 }
959 else
960 {
961 BindOffset+= Desc->Header.BindType * RowNumber;
962 }
963
964 return (char *)Ptr + BindOffset;
965 }
966
967 /* Checking if column ignored in all bound rows. Should hel*/
968 BOOL MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec)
969 {
970 SQLULEN row;
971 SQLLEN *IndicatorPtr;
972
973 for (row= 0; row < Desc->Header.ArraySize; ++row)
974 {
975 IndicatorPtr= (SQLLEN *)GetBindOffset(Desc, Rec, Rec->IndicatorPtr, row, sizeof(SQLLEN));
976
977 if (IndicatorPtr == NULL || *IndicatorPtr != SQL_COLUMN_IGNORE)
978 {
979 return FALSE;
980 }
981 }
982
983 return TRUE;
984 }
985
986
987 void MADB_NumericInit(SQL_NUMERIC_STRUCT *number, MADB_DescRecord *Ard)
988 {
989 if (!number)
990 return;
991 number->precision= (SQLCHAR)Ard->Precision;
992 number->scale= (SQLCHAR)Ard->Scale;
993 memset(number->val, 0, sizeof(number->val));
994 }
995
996 /* {{{ MADB_CharToSQLNumeric */
997 int MADB_CharToSQLNumeric(char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdRecord, SQL_NUMERIC_STRUCT *dst_buffer, unsigned long RowNumber)
998 {
999 char *p;
1000 SQL_NUMERIC_STRUCT *number= dst_buffer != NULL ? dst_buffer :
1001 (SQL_NUMERIC_STRUCT *)GetBindOffset(Ard, ArdRecord, ArdRecord->DataPtr, RowNumber, ArdRecord->OctetLength);
1002 int ret= 0;
1003
1004 if (!buffer || !number)
1005 return ret;
1006
1007 p= trim(buffer);
1008 MADB_NumericInit(number, ArdRecord);
1009
1010 if (!(number->sign= (*p=='-') ? 0 : 1))
1011 p++;
1012 if (!*p)
1013 return FALSE;
1014
1015 if (number->precision == 0)
1016 {
1017 number->precision= MADB_DEFAULT_PRECISION;
1018 }
1019
1020 while (*p=='0')
1021 {
1022 p++;
1023 }
1024 if (*p)
1025 {
1026 int i;
1027 int bit, hval, tv, dig, sta, olen;
1028 int tmp_digit= 0;
1029 int leading_zeros= 0;
1030 char *dot= strchr(p, '.');
1031 char digits[100];
1032 short digits_count= 0;
1033
1034 /* Overflow check */
1035 if (number->precision > 0 && (dot - p) > number->precision)
1036 return MADB_ERR_22003;
1037
1038 if (dot && number->scale > 0)
1039 {
1040 short digits_total= 0,
1041 digits_significant= 0;
1042 digits_count= (short)(dot - p);
1043 memcpy(digits, p, digits_count);
1044 p= dot + 1;
1045 while (*p)
1046 {
1047 /* ignore non numbers */
1048 if (!isdigit(0x000000ff & *p))
1049 break;
1050 digits_total++;
1051 /* ignore trailing zeros */
1052 if (*p != '0')
1053 {
1054 digits_significant= digits_total;
1055 }
1056 p++;
1057 }
1058
1059 if (digits_count + number->scale > number->precision)
1060 {
1061 int i;
1062 /* if digits are zero there is no overflow */
1063 for (i=1; i <= digits_significant; i++)
1064 {
1065 p= dot + i;
1066 if (*p != '0')
1067 return MADB_ERR_22003;
1068 }
1069 }
1070
1071 memcpy(digits + digits_count, dot + 1, digits_significant);
1072 if (number->scale > digits_significant)
1073 {
1074 for (i= digits_count + digits_significant; i < number->precision && i < digits_count +number->scale; ++i)
1075 {
1076 digits[i]= '0';
1077 }
1078 digits_significant= number->scale;
1079 }
1080 digits_count+= digits_significant;
1081 }
1082 else
1083 {
1084 char *start= p;
1085 while (*p && isdigit(0x000000ff & *p))
1086 p++;
1087 /* check overflow */
1088 if (p - start > number->precision)
1089 {
1090 return MADB_ERR_22003;
1091 }
1092 digits_count= (short)(p - start);
1093 memcpy(digits, start, digits_count);
1094 number->scale= ArdRecord->Scale ? ArdRecord->Scale : 0;
1095 }
1096
1097 /* Rounding */
1098 if (number->scale < 0)
1099 {
1100 int64_t OldVal, Val;
1101 int64_t RoundNumber= (int64_t)pow(10.0, -number->scale);
1102
1103 digits[number->precision]= 0;
1104 Val= _atoi64(digits);
1105
1106 OldVal= Val;
1107 Val= (Val + RoundNumber / 2) / RoundNumber * RoundNumber;
1108 if (OldVal != Val)
1109 return MADB_ERR_22003;
1110 _snprintf(digits, sizeof(digits), "%lld", Val);
1111 digits_count= (short)strlen(digits);
1112 if (digits_count > number->precision)
1113 return MADB_ERR_22003;
1114 }
1115
1116 digits_count= MIN(digits_count, MADB_DEFAULT_PRECISION);
1117 for (hval = 0, bit = 1L, sta = 0, olen = 0; sta < digits_count;)
1118 {
1119 for (dig = 0, i = sta; i < digits_count; i++)
1120 {
1121 tv = dig * 10 + digits[i] - '0';
1122 dig = tv % 2;
1123 digits[i] = tv / 2 + '0';
1124 if (i == sta && tv < 2)
1125 sta++;
1126 }
1127 if (dig > 0)
1128 hval |= bit;
1129 bit <<= 1;
1130 if (bit >= (1L << 8))
1131 {
1132 number->val[olen++] = hval;
1133 hval = 0;
1134 bit = 1L;
1135 if (olen >= SQL_MAX_NUMERIC_LEN - 1)
1136 {
1137 //number->scale = sta - number->precision;
1138 //ret= MADB_ERR_22003;
1139 break;
1140 }
1141 }
1142 }
1143 if (hval && olen < SQL_MAX_NUMERIC_LEN - 1)
1144 {
1145 number->val[olen++] = hval;
1146 }
1147 }
1148 return ret;
1149 }
1150
1151 /* {{{ MADB_GetHexString */
1152 size_t MADB_GetHexString(char *BinaryBuffer, size_t BinaryLength,
1153 char *HexBuffer, size_t HexLength)
1154 {
1155 const char HexDigits[]= "0123456789ABCDEF";
1156 char *Start= HexBuffer;
1157 size_t CurrentLength= HexLength;
1158
1159 if (!HexBuffer || !BinaryBuffer)
1160 return 0;
1161
1162 while (BinaryLength-- && CurrentLength > 2)
1163 {
1164 *HexBuffer++=HexDigits[*BinaryBuffer >> 4];
1165 *HexBuffer++=HexDigits[*BinaryBuffer & 0x0F];
1166 BinaryBuffer++;
1167 CurrentLength-= 2;
1168 }
1169 *HexBuffer= 0;
1170 return (HexBuffer - Start);
1171 }
1172
1173
1174 SQLRETURN MADB_DaeStmt(MADB_Stmt *Stmt, SQLUSMALLINT Operation)
1175 {
1176 char *TableName= MADB_GetTableName(Stmt);
1177 char *CatalogName= MADB_GetCatalogName(Stmt);
1178 MADB_DynString DynStmt;
1179
1180 MADB_CLEAR_ERROR(&Stmt->Error);
1181 memset(&DynStmt, 0, sizeof(MADB_DynString));
1182
1183 if (Stmt->DaeStmt)
1184 Stmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
1185 Stmt->DaeStmt= NULL;
1186
1187 if (!SQL_SUCCEEDED(MA_SQLAllocHandle(SQL_HANDLE_STMT, (SQLHANDLE)Stmt->Connection, (SQLHANDLE *)&Stmt->DaeStmt)))
1188 {
1189 MADB_CopyError(&Stmt->Error, &Stmt->Connection->Error);
1190 goto end;
1191 }
1192
1193 switch(Operation)
1194 {
1195 case SQL_ADD:
1196 if (MADB_InitDynamicString(&DynStmt, "INSERT INTO ", 1024, 1024) ||
1197 MADB_DynStrAppendQuoted(&DynStmt, CatalogName) ||
1198 MADB_DynstrAppend(&DynStmt, ".") ||
1199 MADB_DynStrAppendQuoted(&DynStmt, TableName)||
1200 MADB_DynStrUpdateSet(Stmt, &DynStmt))
1201 {
1202 MADB_DynstrFree(&DynStmt);
1203 return Stmt->Error.ReturnValue;
1204 }
1205 Stmt->DataExecutionType= MADB_DAE_ADD;
1206 break;
1207 case SQL_DELETE:
1208 if (MADB_InitDynamicString(&DynStmt, "DELETE FROM ", 1024, 1024) ||
1209 MADB_DynStrAppendQuoted(&DynStmt, CatalogName) ||
1210 MADB_DynstrAppend(&DynStmt, ".") ||
1211 MADB_DynStrAppendQuoted(&DynStmt, TableName) ||
1212 MADB_DynStrGetWhere(Stmt, &DynStmt, TableName, FALSE))
1213 {
1214 MADB_DynstrFree(&DynStmt);
1215 return Stmt->Error.ReturnValue;
1216 }
1217 Stmt->DataExecutionType= MADB_DAE_DELETE;
1218 break;
1219 case SQL_UPDATE:
1220 if (MADB_InitDynamicString(&DynStmt, "UPDATE ", 1024, 1024) ||
1221 MADB_DynStrAppendQuoted(&DynStmt, CatalogName) ||
1222 MADB_DynstrAppend(&DynStmt, ".") ||
1223 MADB_DynStrAppendQuoted(&DynStmt, TableName)||
1224 MADB_DynStrUpdateSet(Stmt, &DynStmt)||
1225 MADB_DynStrGetWhere(Stmt, &DynStmt, TableName, FALSE))
1226 {
1227 MADB_DynstrFree(&DynStmt);
1228 return Stmt->Error.ReturnValue;
1229 }
1230 Stmt->DataExecutionType= MADB_DAE_UPDATE;
1231 break;
1232 }
1233
1234 if (!SQL_SUCCEEDED(Stmt->DaeStmt->Methods->Prepare(Stmt->DaeStmt, DynStmt.str, SQL_NTS, FALSE)))
1235 {
1236 MADB_CopyError(&Stmt->Error, &Stmt->DaeStmt->Error);
1237 Stmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
1238 }
1239
1240 end:
1241 MADB_DynstrFree(&DynStmt);
1242 return Stmt->Error.ReturnValue;
1243
1244 }
1245
1246
1247 int MADB_FindNextDaeParam(MADB_Desc *Desc, int InitialParam, SQLSMALLINT RowNumber)
1248 {
1249 int i;
1250 MADB_DescRecord *Record;
1251
1252 for (i= InitialParam > -1 ? InitialParam + 1 : 0; i < Desc->Header.Count; i++)
1253 {
1254 if ((Record= MADB_DescGetInternalRecord(Desc, i, MADB_DESC_READ)))
1255 {
1256 if (Record->OctetLengthPtr)
1257 {
1258 /* Stmt->DaeRowNumber is 1 based */
1259 SQLLEN *OctetLength = (SQLLEN *)GetBindOffset(Desc, Record, Record->OctetLengthPtr, RowNumber > 1 ? RowNumber - 1 : 0, sizeof(SQLLEN));
1260 if (PARAM_IS_DAE(OctetLength))
1261 {
1262 return i;
1263 }
1264 }
1265 }
1266 }
1267
1268 return MADB_NOPARAM;
1269 }
1270
1271
1272 BOOL MADB_IsNumericType(SQLSMALLINT ConciseType)
1273 {
1274 switch (ConciseType)
1275 {
1276 case SQL_C_DOUBLE:
1277 case SQL_C_FLOAT:
1278 case SQL_DECIMAL:
1279 return TRUE;
1280 }
1281
1282 return MADB_IsIntType(ConciseType);
1283 }
1284
1285
1286 BOOL MADB_IsIntType(SQLSMALLINT ConciseType)
1287 {
1288 switch (ConciseType)
1289 {
1290 case SQL_C_TINYINT:
1291 case SQL_C_STINYINT:
1292 case SQL_C_UTINYINT:
1293 case SQL_C_SHORT:
1294 case SQL_C_SSHORT:
1295 case SQL_C_USHORT:
1296 case SQL_C_LONG:
1297 case SQL_C_SLONG:
1298 case SQL_C_ULONG:
1299 case SQL_C_UBIGINT:
1300 case SQL_C_SBIGINT:
1301 case SQL_BIGINT:
1302 return TRUE;
1303 }
1304 return FALSE;
1305 }
1306
1307 /* Now it's more like installing result */
1308 void MADB_InstallStmt(MADB_Stmt *Stmt, MYSQL_STMT *stmt)
1309 {
1310 Stmt->stmt= stmt;
1311
1312 if (mysql_stmt_field_count(Stmt->stmt) == 0)
1313 {
1314 MADB_DescFree(Stmt->Ird, TRUE);
1315 Stmt->AffectedRows= mysql_stmt_affected_rows(Stmt->stmt);
1316 }
1317 else
1318 {
1319 Stmt->AffectedRows= 0;
1320 MADB_StmtResetResultStructures(Stmt);
1321 MADB_DescSetIrdMetadata(Stmt, mysql_fetch_fields(FetchMetadata(Stmt)), mysql_stmt_field_count(Stmt->stmt));
1322 }
1323 }
0 /************************************************************************************
1 Copyright (C) 2013,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_helper_h_
19 #define _ma_helper_h_
20
21 void CloseMultiStatements(MADB_Stmt *Stmt);
22 MYSQL_STMT* MADB_NewStmtHandle(MADB_Stmt *Stmt);
23 BOOL QueryIsPossiblyMultistmt(MADB_QUERY *Query);
24 int SqlRtrim(char *StmtStr, int Length);
25 unsigned int GetMultiStatements(MADB_Stmt *Stmt, BOOL ExecDirect);
26 int MADB_KeyTypeCount(MADB_Dbc *Connection, char *TableName, int KeyFlag);
27 MYSQL_RES *MADB_ReadDefaultValues(MADB_Dbc *Dbc, const char *Catalog, const char *TableName);
28 int MADB_GetDefaultType(int SQLDataType);
29 void MADB_CopyOdbcTsToMadbTime(SQL_TIMESTAMP_STRUCT *Src, MYSQL_TIME *Dst);
30 void MADB_CopyMadbTimeToOdbcTs(MYSQL_TIME *Src, SQL_TIMESTAMP_STRUCT *Dst);
31 SQLRETURN MADB_CopyMadbTimestamp(MADB_Stmt *Stmt, MYSQL_TIME *tm, SQLPOINTER DataPtr, SQLLEN *Length, SQLLEN *Ind,
32 SQLSMALLINT CType, SQLSMALLINT SqlType);
33 int MADB_GetWCharType(int Type);
34 my_bool MADB_get_single_row(MADB_Dbc *Connection,
35 const char *StmtString,
36 SQLINTEGER Length,
37 unsigned int NumCols,
38 char **Buffers,
39 size_t *Buffer_Lengths);
40 BOOL MADB_CheckODBCType(SQLSMALLINT Type);
41 SQLSMALLINT MADB_GetTypeFromConciseType(SQLSMALLINT ConciseType);
42 size_t MADB_GetTypeLength(SQLINTEGER SqlDataType, size_t Length);
43 SQLLEN MADB_GetDataSize(SQLSMALLINT SqlType, SQLLEN OctetLength, BOOL Unsigned,
44 SQLSMALLINT Precision, SQLSMALLINT Scale, const MARIADB_CHARSET_INFO *Charset);
45 int MADB_GetMaDBTypeAndLength(SQLINTEGER SqlDataType, my_bool *Unsigned, unsigned long *Length);
46 //char *MADB_GetDefaultColumnValue(MADB_Stmt *Stmt, char *Schema, char *TableName, char *Column);
47 SQLSMALLINT MapMariadDbToOdbcType(MYSQL_FIELD *field);
48 size_t MADB_GetHexString(char *BinaryBuffer, size_t BinaryLength,
49 char *HexBuffer, size_t HexLength);
50
51 size_t MADB_GetDisplaySize(MYSQL_FIELD *Field, MARIADB_CHARSET_INFO *charset);
52 size_t MADB_GetOctetLength(MYSQL_FIELD *Field, unsigned short MaxCharLen);
53 char * MADB_GetTypeName(MYSQL_FIELD *Field);
54
55 char * ltrim(char *Str);
56 char * trim(char *Str);
57
58 my_bool MADB_CheckPtrLength(SQLINTEGER MaxLength, char *Ptr, SQLINTEGER NameLen);
59 void * GetBindOffset(MADB_Desc *Ard, MADB_DescRecord *ArdRecord, void *Ptr, SQLULEN RowNumber, size_t PtrSize);
60 BOOL MADB_ColumnIgnoredInAllRows(MADB_Desc *Desc, MADB_DescRecord *Rec);
61
62 SQLRETURN MADB_DaeStmt(MADB_Stmt *Stmt, SQLUSMALLINT Operation);
63 MYSQL_RES * MADB_GetDefaultColumnValues(MADB_Stmt *Stmt, MYSQL_FIELD *fields);
64 char * MADB_GetDefaultColumnValue(MYSQL_RES *res, const char *Column);
65
66 /* SQL_NUMERIC stuff */
67 int MADB_CharToSQLNumeric (char *buffer, MADB_Desc *Ard, MADB_DescRecord *ArdRecord,
68 SQL_NUMERIC_STRUCT *dst_buffer, unsigned long RowNumber);
69 void MADB_NumericInit (SQL_NUMERIC_STRUCT *number, MADB_DescRecord *Ard);
70
71 int MADB_FindNextDaeParam (MADB_Desc *Desc, int InitialParam, SQLSMALLINT RowNumber);
72
73 BOOL MADB_IsNumericType(SQLSMALLINT ConciseType);
74 BOOL MADB_IsIntType (SQLSMALLINT ConciseType);
75
76 /* For multistatement picks stmt handler pointed by stored index, and sets it as "current" stmt handler */
77 void MADB_InstallStmt (MADB_Stmt *Stmt, MYSQL_STMT *stmt);
78
79 /* for dummy binding */
80 extern my_bool DummyError;
81
82 /* Stringify macros */
83 #define XSTR(s) STR(s)
84 #define STR(s) #s
85
86 #define MADB_INT_MAX32 0x7FFFFFFFL
87
88 #ifndef MIN
89 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
90 #endif
91 #ifndef MAX
92 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
93 #endif
94 #ifndef test
95 #define test(a) ((a) ? 1 : 0)
96 #endif
97
98 #define BUFFER_CHAR_LEN(blen,wchar) (wchar) ? (blen) / sizeof(SQLWCHAR) : (blen)
99
100 #define MADB_FREE(a) \
101 free((a));\
102 (a)= NULL;
103 #define MADB_ALLOC(a) malloc((a))
104 #define MADB_CALLOC(a) calloc((a) > 0 ? (a) : 1, sizeof(char))
105 #define MADB_REALLOC(a,b) realloc((a),(b))
106
107 /* If required to free old memory pointed by current ptr, and set new value */
108 #define MADB_RESET(ptr, newptr) do {\
109 char *local_new_ptr= (newptr);\
110 if (local_new_ptr != ptr) {\
111 free((char*)(ptr));\
112 if (local_new_ptr != NULL)\
113 (ptr)= _strdup(local_new_ptr);\
114 else\
115 (ptr)= NULL;\
116 }\
117 } while(0)
118
119 #define MADB_SET_NUM_VAL(TYPE, PTR, VALUE, LENGTHPTR)\
120 {\
121 if((PTR))\
122 *(TYPE *)(PTR)= (VALUE);\
123 if((LENGTHPTR))\
124 *(LENGTHPTR)= sizeof(TYPE);\
125 }
126
127 #define MADB_SET_INTVAL(PTR, LEN, INTTYPE, VALUE) \
128 {\
129 if((PTR))\
130 *((INTTYPE *)PTR)= (VALUE); \
131 LEN=sizeof(INTTYPE);\
132 }
133
134 #define MADB_IS_EMPTY(STR) ((STR)==NULL || *(STR)=='\0')
135
136 #define MADB_FRACTIONAL_PART(_decimals) ((_decimals) > 0 ? (_decimals) + 1/*Decimal point*/ : 0)
137
138 #endif
0 /************************************************************************************
1 Copyright (C) 2013, 2017 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 MADB_TypeInfo TypeInfoV3[]=
21 {
22 {"BIT",SQL_BIT,1,"","","NULL",1,1,3,0,0,0,"BIT",0,0,0,0,10, SQL_BIT},
23 {"BOOL",SQL_BIT,1,"","","NULL",1,1,3,0,0,0,"BOOL",0,0,0,0,10, SQL_BIT},
24 {"TINYINT",SQL_TINYINT,3,"","","NULL",1,0,3,SQL_FALSE,0,1,"TINYINT",0,0,0,0,10, SQL_TINYINT},
25 {"TINYINT UNSIGNED",SQL_TINYINT,3,"","","NULL",1,0,3,SQL_TRUE,0,1,"TINYINT UNSIGNED",0,0,0,0,10, SQL_TINYINT},
26 {"BIGINT",SQL_BIGINT,19,"","","NULL",1,0,3,SQL_FALSE,0,1,"BIGINT",0,0,0,0,10, SQL_BIGINT},
27 {"BIGINT UNSIGNED",SQL_BIGINT,20,"","","NULL",1,0,3,1,0,1,"BIGINT UNSIGNED",0,0,0,0,10, SQL_BIGINT},
28 {"LONG VARBINARY",SQL_LONGVARBINARY,16777215,"\\'","\\'","NULL",1,1,3,0,0,0,"LONG VARBINARY",0,0,0,0,10, SQL_LONGVARBINARY},
29 {"MEDIUMBLOB",SQL_LONGVARBINARY,16777215,"\\'","\\'","NULL",1,1,3,0,0,0,"MEDIUMBLOB",0,0,0,0,10, SQL_LONGVARBINARY},
30 {"LONGBLOB",SQL_LONGVARBINARY,2147483647,"\\'","\\'","NULL",1,1,3,0,0,0,"LONGBLOB",0,0,0,0,10, SQL_LONGVARBINARY},
31 {"BLOB",SQL_LONGVARBINARY,65535,"\\'","\\'","NULL",1,1,3,0,0,0,"BLOB",0,0,0,0,10, SQL_LONGVARBINARY},
32 {"TINYBLOB",SQL_LONGVARBINARY,255,"\\'","\\'","NULL",1,1,3,0,0,0,"TINYBLOB",0,0,0,0,10, SQL_LONGVARBINARY},
33 {"VARBINARY",SQL_VARBINARY,255,"\\'","\\'","'length'",1,1,3,0,0,0,"VARBINARY",0,0,0,0,10, SQL_VARBINARY},
34 {"BINARY",SQL_BINARY,255,"\\'","\\'","'length'",1,1,3,0,0,0,"BINARY",0,0,0,0,10, SQL_BINARY},
35 {"LONG VARCHAR",SQL_LONGVARCHAR,16777215,"\\'","\\'","NULL",1,0,3,0,0,0,"LONG VARCHAR",0,0,0,0,10, SQL_LONGVARCHAR},
36 {"MEDIUMTEXT",SQL_LONGVARCHAR,16777215,"\\'","\\'","NULL",1,0,3,0,0,0,"MEDIUMTEXT",0,0,0,0,10, SQL_LONGVARCHAR},
37 {"LONGTEXT",SQL_LONGVARCHAR,2147483647,"\\'","\\'","NULL",1,0,3,0,0,0,"LONGTEXT",0,0,0,0,10, SQL_LONGVARCHAR},
38 {"TEXT",SQL_LONGVARCHAR,65535,"\\'","\\'","NULL",1,0,3,0,0,0,"TEXT",0,0,0,0,10, SQL_LONGVARCHAR},
39 {"TINYTEXT",SQL_LONGVARCHAR,255,"\\'","\\'","NULL",1,0,3,0,0,0,"TINYTEXT",0,0,0,0,10, SQL_LONGVARCHAR},
40 {"CHAR",SQL_CHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"CHAR",0,0,0,0,10, SQL_CHAR},
41 {"NUMERIC",SQL_NUMERIC,65,"","","'precision,scale'",1,0,3,0,0,1,"NUMERIC", -308,308,0,0,10, SQL_NUMERIC}, /* Todo: ?? */
42 {"DECIMAL",SQL_DECIMAL,65,"","","'precision,scale'",1,0,3,0,0,1,"DECIMAL",-308,308,0,0,10, SQL_DECIMAL},
43 {"INTEGER",SQL_INTEGER,10,"","","NULL",1,0,3,SQL_FALSE,0,1,"INTEGER",0,0,0,0,10,SQL_INTEGER},
44 {"INTEGER UNSIGNED",SQL_INTEGER,10,"","","NULL",1,0,3,1,0,1,"INTEGER UNSIGNED",0,0,0,0,10, SQL_INTEGER},
45 {"INT",SQL_INTEGER,10,"","","NULL",1,0,3,SQL_FALSE,0,1,"INT",0,0,0,0,10, SQL_INTEGER},
46 {"INT UNSIGNED",SQL_INTEGER,10,"","","NULL",1,0,3,1,0,1,"INT UNSIGNED",0,0,0,0,10, SQL_INTEGER},
47 {"MEDIUMINT",SQL_INTEGER,7,"","","NULL",1,0,3,SQL_FALSE,0,1,"MEDIUMINT",0,0,0,0,10},
48 {"MEDIUMINT UNSIGNED",SQL_INTEGER,8,"","","NULL",1,0,3,1,0,1,"MEDIUMINT UNSIGNED",0,0,0,0,10, SQL_INTEGER},
49 {"SMALLINT",SQL_SMALLINT,5,"","","NULL",1,0,3,SQL_FALSE,0,1,"SMALLINT",0,0,0,0,10, SQL_SMALLINT},
50 {"SMALLINT UNSIGNED",SQL_SMALLINT,5,"","","NULL",1,0,3,1,0,1,"SMALLINT UNSIGNED",0,0,0,0,10, SQL_SMALLINT},
51 {"FLOAT",SQL_FLOAT,10,"","","'precision,scale'",1,0,3,0,0,1,"FLOAT",-38,38,0,0,10, SQL_FLOAT},
52 {"DOUBLE",SQL_DOUBLE,17,"","","'precision,scale'",1,0,3,0,0,1,"DOUBLE",-308,308,0,0,10, SQL_DOUBLE},
53 {"DOUBLE PRECISION",SQL_DOUBLE,17,"","","'precision,scale'",1,0,3,0,0,1,"DOUBLE PRECISION",-308,308,0,0,10, SQL_DOUBLE},
54 {"REAL",SQL_DOUBLE,17,"","","'precision,scale'",1,0,3,0,0,1,"REAL",-308,308,0,0,10, SQL_DOUBLE},
55 {"VARCHAR",SQL_VARCHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"VARCHAR",0,0,0,0,10, SQL_VARCHAR},
56 {"ENUM",SQL_VARCHAR,65535,"\\'","\\'","NULL",1,0,3,0,0,0,"ENUM",0,0,0,0,10, SQL_VARCHAR},
57 {"SET",SQL_VARCHAR,64,"\\'","\\'","NULL",1,0,3,0,0,0,"SET",0,0,0,0,10, SQL_VARCHAR},
58 {"DATE",SQL_TYPE_DATE,10,"\\'","\\'","NULL",1,0,3,0,0,0,"DATE",0,0,0,0,10, SQL_DATETIME},
59 {"TIME",SQL_TYPE_TIME,8,"\\'","\\'","NULL",1,0,3,0,0,0,"TIME",0,0,0,0,10, SQL_DATETIME},
60 {"DATETIME",SQL_TYPE_TIMESTAMP,16,"\\'","\\'","NULL",1,0,3,0,0,0,"DATETIME",0,0,0,0,10, SQL_DATETIME},
61 {"TIMESTAMP",SQL_TYPE_TIMESTAMP,16,"\\'","\\'","'scale'",1,0,3,0,0,0,"TIMESTAMP",0,0,0,0,10, SQL_DATETIME},
62 {"CHAR",SQL_WCHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"CHAR",0,0,0,0,10, SQL_WCHAR},
63 {"VARCHAR",SQL_WVARCHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"VARCHAR",0,0,0,0,10, SQL_WVARCHAR},
64 {"LONG VARCHAR",SQL_WLONGVARCHAR,16777215,"\\'","\\'","NULL",1,0,3,0,0,0,"LONG VARCHAR",0,0,0,0,10, SQL_LONGVARCHAR},
65 {NULL,0,0,NULL,NULL,NULL,0,0,0,0,0,0,NULL,0,0,0,0,0}
66 };
67
68 MADB_TypeInfo TypeInfoV2[]=
69 {
70 {"BIT",SQL_BIT,1,"","","NULL",1,1,3,0,0,0,"BIT",0,0,0,0,10, SQL_BIT},
71 {"BOOL",SQL_BIT,1,"","","NULL",1,1,3,0,0,0,"BOOL",0,0,0,0,10, SQL_BIT},
72 {"TINYINT",SQL_TINYINT,3,"","","NULL",1,0,3,SQL_FALSE,0,1,"TINYINT",0,0,0,0,10, SQL_TINYINT},
73 {"TINYINT UNSIGNED",SQL_TINYINT,3,"","","NULL",1,0,3,SQL_FALSE,0,1,"TINYINT UNSIGNED",0,0,0,0,10, SQL_TINYINT},
74 {"BIGINT",SQL_BIGINT,19,"","","NULL",1,0,3,SQL_FALSE,0,1,"BIGINT",0,0,0,0,10, SQL_BIGINT},
75 {"BIGINT UNSIGNED",SQL_BIGINT,20,"","","NULL",1,0,3,SQL_TRUE,0,1,"BIGINT UNSIGNED",0,0,0,0,10, SQL_BIGINT},
76 {"LONG VARBINARY",SQL_LONGVARBINARY,16777215,"\\'","\\'","NULL",1,1,3,0,0,0,"LONG VARBINARY",0,0,0,0,10, SQL_LONGVARBINARY},
77 {"MEDIUMBLOB",SQL_LONGVARBINARY,16777215,"\\'","\\'","NULL",1,1,3,0,0,0,"MEDIUMBLOB",0,0,0,0,10, SQL_LONGVARBINARY},
78 {"LONGBLOB",SQL_LONGVARBINARY,2147483647,"\\'","\\'","NULL",1,1,3,0,0,0,"LONGBLOB",0,0,0,0,10, SQL_LONGVARBINARY},
79 {"BLOB",SQL_LONGVARBINARY,65535,"\\'","\\'","NULL",1,1,3,0,0,0,"BLOB",0,0,0,0,10, SQL_LONGVARBINARY},
80 {"TINYBLOB",SQL_LONGVARBINARY,255,"\\'","\\'","NULL",1,1,3,0,0,0,"TINYBLOB",0,0,0,0,10, SQL_LONGVARBINARY},
81 {"VARBINARY",SQL_VARBINARY,255,"\\'","\\'","'length'",1,1,3,0,0,0,"VARBINARY",0,0,0,0,10, SQL_VARBINARY},
82 {"BINARY",SQL_BINARY,255,"\\'","\\'","'length'",1,1,3,0,0,0,"BINARY",0,0,0,0,10, SQL_BINARY},
83 {"LONG VARCHAR",SQL_LONGVARCHAR,16777215,"\\'","\\'","NULL",1,0,3,0,0,0,"LONG VARCHAR",0,0,0,0,10, SQL_LONGVARCHAR},
84 {"MEDIUMTEXT",SQL_LONGVARCHAR,16777215,"\\'","\\'","NULL",1,0,3,0,0,0,"MEDIUMTEXT",0,0,0,0,10, SQL_LONGVARCHAR},
85 {"LONGTEXT",SQL_LONGVARCHAR,2147483647,"\\'","\\'","NULL",1,0,3,0,0,0,"LONGTEXT",0,0,0,0,10, SQL_LONGVARCHAR},
86 {"TEXT",SQL_LONGVARCHAR,65535,"\\'","\\'","NULL",1,0,3,0,0,0,"TEXT",0,0,0,0,10, SQL_LONGVARCHAR},
87 {"TINYTEXT",SQL_LONGVARCHAR,255,"\\'","\\'","NULL",1,0,3,0,0,0,"TINYTEXT",0,0,0,0,10, SQL_LONGVARCHAR},
88 {"CHAR",SQL_CHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"CHAR",0,0,0,0,10, SQL_CHAR},
89 {"NUMERIC",SQL_NUMERIC,65,"","","'precision,scale'",1,0,3,0,0,1,"NUMERIC", -308,308,0,0,10, SQL_NUMERIC}, /* Todo: ?? */
90 {"DECIMAL",SQL_DECIMAL,65,"","","'precision,scale'",1,0,3,0,0,1,"DECIMAL",-308,308,0,0,10, SQL_DECIMAL},
91 {"INTEGER",SQL_INTEGER,10,"","","NULL",1,0,3,SQL_FALSE,0,1,"INTEGER",0,0,0,0,10,SQL_INTEGER},
92 {"INTEGER UNSIGNED",SQL_INTEGER,10,"","","NULL",1,0,3,1,0,1,"INTEGER UNSIGNED",0,0,0,0,10, SQL_INTEGER},
93 {"INT",SQL_INTEGER,10,"","","NULL",1,0,3,SQL_FALSE,0,1,"INT",0,0,0,0,10, SQL_INTEGER},
94 {"INT UNSIGNED",SQL_INTEGER,10,"","","NULL",1,0,3,1,0,1,"INT UNSIGNED",0,0,0,0,10, SQL_INTEGER},
95 {"MEDIUMINT",SQL_INTEGER,7,"","","NULL",1,0,3,SQL_FALSE,0,1,"MEDIUMINT",0,0,0,0,10},
96 {"MEDIUMINT UNSIGNED",SQL_INTEGER,8,"","","NULL",1,0,3,1,0,1,"MEDIUMINT UNSIGNED",0,0,0,0,10, SQL_INTEGER},
97 {"SMALLINT",SQL_SMALLINT,5,"","","NULL",1,0,3,SQL_FALSE,0,1,"SMALLINT",0,0,0,0,10, SQL_SMALLINT},
98 {"SMALLINT UNSIGNED",SQL_SMALLINT,5,"","","NULL",1,0,3,1,0,1,"SMALLINT UNSIGNED",0,0,0,0,10, SQL_SMALLINT},
99 {"FLOAT",SQL_FLOAT,10,"","","'precision,scale'",1,0,3,0,0,1,"FLOAT",-38,38,0,0,10, SQL_FLOAT},
100 {"DOUBLE",SQL_DOUBLE,17,"","","'precision,scale'",1,0,3,0,0,1,"DOUBLE",-308,308,0,0,10, SQL_DOUBLE},
101 {"DOUBLE PRECISION",SQL_DOUBLE,17,"","","'precision,scale'",1,0,3,0,0,1,"DOUBLE PRECISION",-308,308,0,0,10, SQL_DOUBLE},
102 {"REAL",SQL_DOUBLE,17,"","","'precision,scale'",1,0,3,0,0,1,"REAL",-308,308,0,0,10, SQL_DOUBLE},
103 {"VARCHAR",SQL_VARCHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"VARCHAR",0,0,0,0,10, SQL_VARCHAR},
104 {"ENUM",SQL_VARCHAR,65535,"\\'","\\'","NULL",1,0,3,0,0,0,"ENUM",0,0,0,0,10, SQL_VARCHAR},
105 {"SET",SQL_VARCHAR,64,"\\'","\\'","NULL",1,0,3,0,0,0,"SET",0,0,0,0,10, SQL_VARCHAR},
106 {"DATE",SQL_DATE,10,"\\'","\\'","NULL",1,0,3,0,0,0,"DATE",0,0,0,0,10, SQL_DATETIME},
107 {"TIME",SQL_TIME,18,"\\'","\\'","NULL",1,0,3,0,0,0,"TIME",0,0,0,0,10, SQL_DATETIME},
108 {"DATETIME",SQL_TIMESTAMP,27,"\\'","\\'","NULL",1,0,3,0,0,0,"DATETIME",0,0,0,0,10, SQL_DATETIME},
109 {"TIMESTAMP",SQL_TIMESTAMP,27,"\\'","\\'","'scale'",1,0,3,0,0,0,"TIMESTAMP",0,0,0,0,10, SQL_DATETIME},
110 {"CHAR",SQL_WCHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"CHAR",0,0,0,0,10, SQL_WCHAR},
111 {"VARCHAR",SQL_WVARCHAR,255,"\\'","\\'","'length'",1,0,3,0,0,0,"VARCHAR",0,0,0,0,10, SQL_WVARCHAR},
112 {"LONG VARCHAR",SQL_WLONGVARCHAR,16777215,"\\'","\\'","NULL",1,0,3,0,0,0,"LONG VARCHAR",0,0,0,0,10, SQL_WLONGVARCHAR},
113 {NULL,0,0,NULL,NULL,NULL,0,0,0,0,0,0,NULL,0,0,0,0,0}
114 };
115
116 static MADB_ShortTypeInfo gtiDefType[19]= {{0, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0}, {SQL_INTEGER, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0},
117 /*7*/ {SQL_SMALLINT, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0},
118 /*11*/ {SQL_SMALLINT, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0}, {0, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0},
119 /*16*/ {SQL_SMALLINT, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0}, {SQL_INTEGER, 0, 0, 0}, {SQL_SMALLINT, 0, 0, 0} };
120 /* {{{ MADB_GetTypeInfo */
121 SQLRETURN MADB_GetTypeInfo(SQLHSTMT StatementHandle,
122 SQLSMALLINT DataType)
123 {
124 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
125 SQLRETURN ret;
126 my_bool isFirst= TRUE;
127 char StmtStr[5120];
128 char *p= StmtStr;
129 int i;
130 MADB_TypeInfo *TypeInfo= TypeInfoV3;
131
132 if (Stmt->Connection->Environment->OdbcVersion == SQL_OV_ODBC2)
133 {
134 TypeInfo= TypeInfoV2;
135 /* We need to map time types */
136 switch(DataType) {
137 case SQL_TYPE_TIMESTAMP:
138 DataType=SQL_TIMESTAMP;
139 break;
140 case SQL_TYPE_DATE:
141 DataType= SQL_DATE;
142 break;
143 case SQL_TYPE_TIME:
144 DataType= SQL_TIME;
145 break;
146 default:
147 break;
148 }
149 }
150
151 StmtStr[0]= 0;
152 for (i=0;TypeInfo[i].TypeName; i++)
153 {
154 if (DataType == SQL_ALL_TYPES ||
155 TypeInfo[i].DataType == DataType)
156 {
157 if(isFirst)
158 {
159 isFirst= FALSE;
160 p+= _snprintf(p, 5120 - strlen(StmtStr),
161 "SELECT '%s' AS TYPE_NAME, %d AS DATA_TYPE, %lu AS COLUMN_SIZE, '%s' AS LITERAL_PREFIX, "
162 "'%s' AS LITERAL_SUFFIX, %s AS CREATE_PARAMS, %d AS NULLABLE, %d AS CASE_SENSITIVE, "
163 "%d AS SEARCHABLE, %d AS UNSIGNED_ATTRIBUTE, %d AS FIXED_PREC_SCALE, %d AS AUTO_UNIQUE_VALUE, "
164 "'%s' AS LOCAL_TYPE_NAME, %d AS MINIMUM_SCALE, %d AS MAXIMUM_SCALE, "
165 "%d AS SQL_DATA_TYPE, "
166 "%d AS SQL_DATETIME_SUB, %d AS NUM_PREC_RADIX, NULL AS INTERVAL_PRECISION ",
167 TypeInfo[i].TypeName,TypeInfo[i].DataType,TypeInfo[i].ColumnSize,TypeInfo[i].LiteralPrefix,
168 TypeInfo[i].LiteralSuffix,TypeInfo[i].CreateParams,TypeInfo[i].Nullable,TypeInfo[i].CaseSensitive,
169 TypeInfo[i].Searchable,TypeInfo[i].Unsigned,TypeInfo[i].FixedPrecScale,TypeInfo[i].AutoUniqueValue,
170 TypeInfo[i].LocalTypeName,TypeInfo[i].MinimumScale,TypeInfo[i].MaximumScale,
171 TypeInfo[i].SqlDataType,
172 TypeInfo[i].SqlDateTimeSub,TypeInfo[i].NumPrecRadix);
173 }
174 else
175 p+= _snprintf(p, 5120 - strlen(StmtStr),
176 "UNION SELECT '%s', %d, %lu , '%s', "
177 "'%s', %s, %d, %d, "
178 "%d, %d, %d, %d, "
179 "'%s', %d, %d, "
180 "%d, "
181 "%d, %d, NULL ",
182 TypeInfo[i].TypeName,TypeInfo[i].DataType,TypeInfo[i].ColumnSize,TypeInfo[i].LiteralPrefix,
183 TypeInfo[i].LiteralSuffix,TypeInfo[i].CreateParams,TypeInfo[i].Nullable,TypeInfo[i].CaseSensitive,
184 TypeInfo[i].Searchable,TypeInfo[i].Unsigned,TypeInfo[i].FixedPrecScale,TypeInfo[i].AutoUniqueValue,
185 TypeInfo[i].LocalTypeName,TypeInfo[i].MinimumScale,TypeInfo[i].MaximumScale,
186 TypeInfo[i].SqlDataType,
187 TypeInfo[i].SqlDateTimeSub,TypeInfo[i].NumPrecRadix);
188 }
189 }
190 ret= Stmt->Methods->ExecDirect(Stmt, StmtStr, SQL_NTS);
191 if (SQL_SUCCEEDED(ret))
192 {
193 MADB_FixColumnDataTypes(Stmt, gtiDefType);
194 }
195 return ret;
196 }
197 /* }}} */
0 /************************************************************************************
1 Copyright (C) 2013, 2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_info_h_
19 #define _ma_info_h_
20
21 typedef struct
22 {
23 char *TypeName;
24 SQLSMALLINT DataType;
25 SQLINTEGER ColumnSize;
26 char *LiteralPrefix;
27 char *LiteralSuffix;
28 char *CreateParams;
29 SQLSMALLINT Nullable;
30 SQLSMALLINT CaseSensitive;
31 SQLSMALLINT Searchable;
32 SQLSMALLINT Unsigned;
33 SQLSMALLINT FixedPrecScale;
34 SQLSMALLINT AutoUniqueValue;
35 char *LocalTypeName;
36 SQLSMALLINT MinimumScale;
37 SQLSMALLINT MaximumScale;
38 SQLSMALLINT SqlDataType1;
39 SQLSMALLINT SqlDateTimeSub;
40 SQLINTEGER NumPrecRadix;
41 SQLSMALLINT IntervalPrecision;
42 SQLSMALLINT SqlDataType;
43 } MADB_TypeInfo;
44
45
46 SQLRETURN MADB_GetTypeInfo(SQLHSTMT StatementHandle,
47 SQLSMALLINT DataType);
48
49 #endif /* _ma_info_h_ */
0 /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
1 2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 */
18
19 /********
20 *
21 * Code for lists, MADB_DynArray, and MADB_DynString copied (from C/C
22 *
23 ********/
24
25 /*
26 *************** Code for handling dubble-linked lists in C *********
27 */
28
29 #include <ma_odbc.h>
30
31 /*
32 How much overhead does malloc have. The code often allocates
33 something like 1024-MALLOC_OVERHEAD bytes
34 */
35 #define MALLOC_OVERHEAD 8
36
37 /* Add a element to start of list */
38
39 MADB_List *MADB_ListAdd(MADB_List *root, MADB_List *element)
40 {
41 if (root)
42 {
43 if (root->prev) /* If add in mid of list */
44 root->prev->next= element;
45 element->prev=root->prev;
46 root->prev=element;
47 }
48 else
49 element->prev=0;
50 element->next=root;
51 return(element); /* New root */
52 }
53
54
55 MADB_List *MADB_ListDelete(MADB_List *root, MADB_List *element)
56 {
57 if (element->prev)
58 element->prev->next=element->next;
59 else
60 root=element->next;
61 if (element->next)
62 element->next->prev=element->prev;
63 return root;
64 }
65
66
67 void MADB_ListFree(MADB_List *root, unsigned int free_data)
68 {
69 MADB_List *next;
70 while (root)
71 {
72 next=root->next;
73 if (free_data)
74 free(root->data);
75 free(root);
76 root=next;
77 }
78 }
79
80
81 MADB_List *MADB_ListCons(void *data, MADB_List *list)
82 {
83 MADB_List *new_charset=(MADB_List*) malloc(sizeof(MADB_List));
84 if (!new_charset)
85 return 0;
86 new_charset->data=data;
87 return MADB_ListAdd(list,new_charset);
88 }
89
90
91 MADB_List *MADB_ListReverse(MADB_List *root)
92 {
93 MADB_List *last;
94
95 last=root;
96 while (root)
97 {
98 last=root;
99 root=root->next;
100 last->next=last->prev;
101 last->prev=root;
102 }
103 return last;
104 }
105
106 unsigned int MADB_ListLength(MADB_List *list)
107 {
108 unsigned int count;
109 for (count=0 ; list ; list=list->next, count++) ;
110 return count;
111 }
112
113
114 int MADB_ListWalk(MADB_List *list, MADB_ListWalkAction action, char * argument)
115 {
116 int error=0;
117 while (list)
118 {
119 if ((error = (*action)(list->data,argument)))
120 return error;
121 list= MADB_LIST_REST(list);
122 }
123 return 0;
124 }
125
126
127 /************************** MADB_DynString ***************************/
128 /*
129 Code for handling strings with can grow dynamicly.
130 Copyright Monty Program KB.
131 By monty.
132 */
133
134 my_bool MADB_InitDynamicString(MADB_DynString *str, const char *init_str,
135 size_t init_alloc, size_t alloc_increment)
136 {
137 unsigned int length;
138
139 if (!alloc_increment)
140 alloc_increment=128;
141 length=1;
142 if (init_str && (length= (unsigned int) strlen(init_str)+1) < init_alloc)
143 init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment;
144 if (!init_alloc)
145 init_alloc=alloc_increment;
146
147 if (!(str->str=(char*) malloc(init_alloc)))
148 return(TRUE);
149 str->length=length-1;
150 if (init_str)
151 memcpy(str->str,init_str,length);
152 str->max_length=init_alloc;
153 str->alloc_increment=alloc_increment;
154 return(FALSE);
155 }
156
157 my_bool MADB_DynstrSet(MADB_DynString *str, const char *init_str)
158 {
159 unsigned int length;
160
161 if (init_str && (length= (unsigned int) strlen(init_str)+1) > str->max_length)
162 {
163 str->max_length=((length+str->alloc_increment-1)/str->alloc_increment)*
164 str->alloc_increment;
165 if (!str->max_length)
166 str->max_length=str->alloc_increment;
167 if (!(str->str=(char*) realloc(str->str,str->max_length)))
168 return(TRUE);
169 }
170 if (init_str)
171 {
172 str->length=length-1;
173 memcpy(str->str,init_str,length);
174 }
175 else
176 str->length=0;
177 return(FALSE);
178 }
179
180
181 my_bool MADB_DynstrRealloc(MADB_DynString *str, size_t additional_size)
182 {
183 if (!additional_size) return(FALSE);
184 if (str->length + additional_size > str->max_length)
185 {
186 str->max_length=((str->length + additional_size+str->alloc_increment-1)/
187 str->alloc_increment)*str->alloc_increment;
188 if (!(str->str=(char*) realloc(str->str,str->max_length)))
189 return(TRUE);
190 }
191 return(FALSE);
192 }
193
194
195 my_bool MADB_DynstrAppend(MADB_DynString *str, const char *append)
196 {
197 return MADB_DynstrAppendMem(str,append,strlen(append));
198 }
199
200
201 my_bool MADB_DynstrAppendMem(MADB_DynString *str, const char *append,
202 size_t length)
203 {
204 char *new_ptr;
205 if (str->length+length >= str->max_length)
206 {
207 size_t new_length=(str->length+length+str->alloc_increment)/
208 str->alloc_increment;
209 new_length*=str->alloc_increment;
210 if (!(new_ptr=(char*) realloc(str->str,new_length)))
211 return TRUE;
212 str->str=new_ptr;
213 str->max_length=new_length;
214 }
215 memcpy(str->str + str->length,append,length);
216 str->length+=length;
217 str->str[str->length]=0; /* Safety for C programs */
218 return FALSE;
219 }
220
221
222 void MADB_DynstrFree(MADB_DynString *str)
223 {
224 if (str->str)
225 {
226 free(str->str);
227 str->str=0;
228 }
229 }
230
231 char *MADB_DynstrMake(register char *dst, register const char *src, size_t length)
232 {
233 while (length--)
234 if (! (*dst++ = *src++))
235 return dst-1;
236 *dst=0;
237 return dst;
238 }
239
240
241 /************* MADB_DynArray - Handling of arrays that can grow dynamicly. **************/
242
243 #undef SAFEMALLOC /* Problems with threads */
244
245
246 /*
247 Initiate array and alloc space for init_alloc elements. Array is usable
248 even if space allocation failed
249 */
250
251 my_bool MADB_InitDynamicArray(MADB_DynArray *array, unsigned int element_size,
252 unsigned int init_alloc, unsigned int alloc_increment)
253 {
254 if (!alloc_increment)
255 {
256 alloc_increment=MAX((8192-MALLOC_OVERHEAD)/element_size,16);
257 if (init_alloc > 8 && alloc_increment > init_alloc * 2)
258 alloc_increment=init_alloc*2;
259 }
260
261 if (!init_alloc)
262 init_alloc=alloc_increment;
263 array->elements=0;
264 array->max_element=init_alloc;
265 array->alloc_increment=alloc_increment;
266 array->size_of_element=element_size;
267 if (!(array->buffer=(char*) malloc(element_size*init_alloc)))
268 {
269 array->max_element=0;
270 return(TRUE);
271 }
272 return(FALSE);
273 }
274
275
276 my_bool MADB_InsertDynamic(MADB_DynArray *array, void *element)
277 {
278 void *buffer;
279 if (array->elements == array->max_element)
280 { /* Call only when nessesary */
281 if (!(buffer=MADB_AllocDynamic(array)))
282 return TRUE;
283 }
284 else
285 {
286 buffer=array->buffer+(array->elements * array->size_of_element);
287 array->elements++;
288 }
289 memcpy(buffer,element,(size_t) array->size_of_element);
290 return FALSE;
291 }
292
293
294 /* Alloc room for one element */
295
296 unsigned char *MADB_AllocDynamic(MADB_DynArray *array)
297 {
298 if (array->elements == array->max_element)
299 {
300 char *new_ptr;
301 if (!(new_ptr=(char*) realloc(array->buffer,(array->max_element+
302 array->alloc_increment)*
303 array->size_of_element)))
304 return 0;
305 array->buffer=new_ptr;
306 array->max_element+=array->alloc_increment;
307 }
308 return (unsigned char *)array->buffer+(array->elements++ * array->size_of_element);
309 }
310
311
312 /* remove last element from array and return it */
313
314 unsigned char *MADB_PopDynamic(MADB_DynArray *array)
315 {
316 if (array->elements)
317 return (unsigned char *)array->buffer+(--array->elements * array->size_of_element);
318 return 0;
319 }
320
321
322 my_bool MADB_SetDynamic(MADB_DynArray *array, void * element, unsigned int idx)
323 {
324 if (idx >= array->elements)
325 {
326 if (idx >= array->max_element)
327 {
328 unsigned int size;
329 char *new_ptr;
330 size=(idx+array->alloc_increment)/array->alloc_increment;
331 size*= array->alloc_increment;
332 if (!(new_ptr=(char*) realloc(array->buffer,size*
333 array->size_of_element)))
334 return TRUE;
335 array->buffer=new_ptr;
336 array->max_element=size;
337 }
338 memset((array->buffer+array->elements*array->size_of_element), 0,
339 (idx - array->elements)*array->size_of_element);
340 array->elements=idx+1;
341 }
342 memcpy(array->buffer+(idx * array->size_of_element),element,
343 (size_t) array->size_of_element);
344 return FALSE;
345 }
346
347
348 void MADB_GetDynamic(MADB_DynArray *array, void * element, unsigned int idx)
349 {
350 if (idx >= array->elements)
351 {
352 memset(element, 0, array->size_of_element);
353 return;
354 }
355 memcpy(element,array->buffer+idx*array->size_of_element,
356 (size_t) array->size_of_element);
357 }
358
359
360 void MADB_DeleteDynamic(MADB_DynArray *array)
361 {
362 if (array->buffer)
363 {
364 free(array->buffer);
365 array->buffer=0;
366 array->elements=array->max_element=0;
367 }
368 }
369
370
371 void MADB_DeleteDynamicElement(MADB_DynArray *array, unsigned int idx)
372 {
373 char *ptr=array->buffer+array->size_of_element*idx;
374 array->elements--;
375 memmove(ptr,ptr+array->size_of_element,
376 (array->elements-idx)*array->size_of_element);
377 }
378
379
380 void MADB_FreezeSizeDynamic(MADB_DynArray *array)
381 {
382 unsigned int elements=MAX(array->elements,1);
383
384 if (array->buffer && array->max_element != elements)
385 {
386 array->buffer=(char*) realloc(array->buffer,
387 elements*array->size_of_element);
388 array->max_element=elements;
389 }
390 }
0 /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
1 2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 */
18 #ifndef _MA_LEGACY_HELPERS_H
19 #define _MA_LEGACY_HELPERS_H
20
21 /********
22 *
23 * Function definitions, types, macros for MADB_List, MADB_DynArray, and MADB_DynString copied from C/C
24 *
25 ********/
26
27 /*
28 *************** Dubble-linked lists *********
29 */
30 typedef struct st_ma_odbc_list {
31 struct st_ma_odbc_list *prev, *next;
32 void *data;
33 } MADB_List;
34
35 typedef int(*MADB_ListWalkAction)(void *, void *);
36
37 /* Add a element to start of list */
38 MADB_List *MADB_ListAdd(MADB_List *root, MADB_List *element);
39 MADB_List *MADB_ListDelete(MADB_List *root, MADB_List *element);
40 void MADB_ListFree(MADB_List *root, unsigned int free_data);
41 MADB_List *MADB_ListCons(void *data, MADB_List *list);
42 MADB_List *MADB_ListReverse(MADB_List *root);
43 unsigned int MADB_ListLength(MADB_List *list);
44 int MADB_ListWalk(MADB_List *list, MADB_ListWalkAction action, char *argument);
45
46 #define MADB_LIST_REST(a) ((a)->next)
47 #define MADB_LIST_PUSH(a,b) (a)=MADB_ListCons((b),(a))
48 #define MADB_LIST_POP(A) {MADB_List *old=(A); (A)=MADB_ListDelete(old,old) ; free((char *) old); }
49
50 /************************** MADB_DynString ************************/
51 typedef struct st_ma_odbc_dynstr {
52 char *str;
53 size_t length,max_length,alloc_increment;
54 } MADB_DynString;
55
56 my_bool MADB_InitDynamicString(MADB_DynString *str, const char *init_str,
57 size_t init_alloc, size_t alloc_increment);
58 my_bool MADB_DynstrSet(MADB_DynString *str, const char *init_str);
59 my_bool MADB_DynstrRealloc(MADB_DynString *str, size_t additional_size);
60 my_bool MADB_DynstrAppend(MADB_DynString *str, const char *append);
61 my_bool MADB_DynstrAppendMem(MADB_DynString *str, const char *append,
62 size_t length);
63 void MADB_DynstrFree(MADB_DynString *str);
64 char *MADB_DynstrMake(register char *dst, register const char *src, size_t length);
65
66 /************* MADB_DynArray - Arrays that can grow dynamicly. **************/
67 typedef struct ma_odbc_st_dynarr {
68 char *buffer;
69 unsigned int elements,max_element;
70 unsigned int alloc_increment;
71 unsigned int size_of_element;
72 } MADB_DynArray;
73
74 my_bool MADB_InitDynamicArray(MADB_DynArray *array, unsigned int element_size,
75 unsigned int init_alloc, unsigned int alloc_increment);
76 my_bool MADB_InsertDynamic(MADB_DynArray *array, void *element);
77 /* Alloc room for one element */
78 unsigned char *MADB_AllocDynamic(MADB_DynArray *array);
79 /* remove last element from array and return it */
80 unsigned char *MADB_PopDynamic(MADB_DynArray *array);
81 my_bool MADB_SetDynamic(MADB_DynArray *array, void * element, unsigned int idx);
82 void MADB_GetDynamic(MADB_DynArray *array, void * element, unsigned int idx);
83 void MADB_DeleteDynamic(MADB_DynArray *array);
84 void MADB_DeleteDynamicElement(MADB_DynArray *array, unsigned int idx);
85 void MADB_FreezeSizeDynamic(MADB_DynArray *array);
86
87 #endif /* #ifndef _MA_LEGACY_HELPERS_H */
0 /************************************************************************************
1 Copyright (C) 2013,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_odbc_h_
19 #define _ma_odbc_h_
20
21 #include <ma_odbc_version.h>
22
23 #ifdef _WIN32
24 # include "ma_platform_win32.h"
25 #else
26 # include "ma_platform_posix.h"
27 #endif
28
29 #include <stdlib.h>
30
31 #include <mysql.h>
32
33 #include <ma_legacy_helpers.h>
34
35 #include <sql.h>
36 #include <sqlext.h>
37 #include <odbcinst.h>
38
39 #include <errmsg.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <math.h>
43 #include <stddef.h>
44 #include <assert.h>
45 #include <time.h>
46
47
48 typedef struct st_ma_odbc_connection MADB_Dbc;
49 typedef struct st_ma_odbc_stmt MADB_Stmt;
50
51 typedef struct st_ma_odbc_error
52 {
53 char SqlState[SQL_SQLSTATE_SIZE + 1];
54 char SqlStateV2[SQLSTATE_LENGTH + 1];
55 char SqlErrorMsg[SQL_MAX_MESSAGE_LENGTH + 1];
56 SQLRETURN ReturnValue;
57 } MADB_ERROR;
58
59 typedef struct
60 {
61 char SqlState[SQLSTATE_LENGTH + 1];
62 SQLINTEGER NativeError;
63 char SqlErrorMsg[SQL_MAX_MESSAGE_LENGTH + 1];
64 size_t PrefixLen;
65 SQLRETURN ReturnValue;
66 MADB_ERROR *ErrRecord;
67 /* Order number of last requested error record */
68 unsigned int ErrorNum;
69 } MADB_Error;
70
71 typedef struct
72 {
73 SQLUINTEGER TargetType;
74 SQLPOINTER TargetValuePtr;
75 SQLLEN BufferLength;
76 SQLLEN Utf8BufferLength;
77 SQLLEN *StrLen_or_Ind;
78 void *InternalBuffer; /* used for conversion */
79 } MADB_ColBind;
80
81 typedef struct
82 {
83 SQLSMALLINT InputOutputType;
84 SQLSMALLINT ValueType;
85 SQLSMALLINT ParameterType;
86 SQLULEN ColumnSize;
87 SQLSMALLINT DecimalDigits;
88 SQLPOINTER ParameterValuePtr;
89 SQLLEN BufferLength;
90 SQLLEN *StrLen_or_IndPtr;
91 void *InternalBuffer; /* used for conversion */
92 } MADB_ParmBind;
93
94 typedef struct
95 {
96 /* Header */
97 SQLSMALLINT AllocType;
98 SQLULEN ArraySize;
99 SQLUSMALLINT *ArrayStatusPtr;
100 SQLULEN *BindOffsetPtr;
101 SQLULEN BindType;
102 SQLSMALLINT Count;
103 /* TODO: In IPD this is SQLUINTEGER* field */
104 SQLULEN *RowsProcessedPtr;
105 /* Header end */
106 } MADB_Header;
107
108 typedef struct
109 {
110 SQLUINTEGER BindSize; /* size of each structure if using * Row-wise Binding */
111 SQLUSMALLINT *RowOperationPtr;
112 SQLULEN *RowOffsetPtr;
113 MADB_ColBind *ColumnBind;
114 MYSQL_BIND *Bind;
115 SQLSMALLINT Allocated;
116 } MADB_Ard;
117
118 typedef struct
119 {
120 SQLLEN ParamsetSize;
121 SQLUINTEGER ParamBindType;
122 SQLUSMALLINT *ParamOperationPtr;
123 SQLULEN *ParamOffsetPtr;
124 MADB_ParmBind *ParamBind;
125 MYSQL_BIND *Bind;
126 SQLSMALLINT Allocated;
127 SQLLEN Dummy; /* dummy item to fit APD to ARD */
128 } MADB_Apd;
129
130 typedef struct
131 {
132 MADB_Stmt *stmt;
133 SQLULEN *RowsFetched;
134 SQLUSMALLINT *RowStatusArray;
135 SQLUINTEGER FieldCount;
136 SQLSMALLINT Allocated;
137 MYSQL_FIELD *Fields;
138 } MADB_Ird;
139
140 typedef struct
141 {
142 MADB_Header Header;
143 #if (ODBCVER >= 0x0300)
144 SQLUINTEGER *ParamProcessedPtr;
145 #else
146 SQLULEN *ParamProcessedPtr; /* SQLParamOptions */
147 #endif /* ODBCVER */
148 SQLUSMALLINT *ParamStatusPtr;
149 SQLSMALLINT Allocated;
150 MADB_ParmBind *Parameters;
151 } MADB_Ipd;
152
153 typedef struct {
154 SQLINTEGER AutoUniqueValue;
155 char *BaseCatalogName;
156 char *BaseColumnName;
157 char *BaseTableName;
158 SQLINTEGER CaseSensitive;
159 char *CatalogName;
160 char *ColumnName;
161 SQLSMALLINT ConciseType;
162 SQLPOINTER DataPtr;
163 SQLSMALLINT DateTimeIntervalCode;
164 SQLINTEGER DateTimeIntervalPrecision;
165 SQLINTEGER DescLength;
166 SQLLEN DisplaySize;
167 SQLSMALLINT FixedPrecScale;
168 SQLLEN *IndicatorPtr;
169 char *Label;
170 SQLULEN Length;
171 char *LiteralPrefix;
172 char *LiteralSuffix;
173 char *LocalTypeName;
174 SQLSMALLINT Nullable;
175 SQLINTEGER NumPrecRadix;
176 SQLLEN OctetLength;
177 SQLLEN *OctetLengthPtr;
178 SQLSMALLINT ParameterType;
179 SQLSMALLINT Precision;
180 SQLSMALLINT RowVer;
181 SQLSMALLINT Scale;
182 char *SchemaName;
183 SQLSMALLINT Searchable;
184 char *TableName;
185 SQLSMALLINT Type;
186 char *TypeName;
187 SQLSMALLINT Unnamed;
188 SQLSMALLINT Unsigned;
189 SQLSMALLINT Updateable;
190 unsigned long InternalLength; /* This to be used in the MYSQL_BIND. Thus is the type */
191 char *InternalBuffer; /* used for internal conversion */
192 char *DefaultValue;
193 char *DaeData;
194 SQLULEN DaeDataLength; /* Doesn't seem to be used anywhere */
195 my_bool PutData;
196 my_bool inUse;
197 my_bool TruncError;
198 } MADB_DescRecord;
199
200 typedef struct
201 {
202 MADB_Header Header;
203 SQLINTEGER DescType; /* SQL_ATTR_APP_ROW_DESC or SQL_ATTR_APP_PARAM_DESC */
204 my_bool AppType; /* Allocated by Application ? */
205 MADB_DynArray Records;
206 MADB_DynArray Stmts;
207 MADB_Error Error;
208 MADB_Dbc * Dbc; /* Disconnect must automatically free allocated descriptors. Thus
209 descriptor has to know the connection it is allocated on */
210 MADB_List ListItem; /* To store in the dbc */
211 union {
212 MADB_Ard Ard;
213 MADB_Apd Apd;
214 MADB_Ipd Ipd;
215 MADB_Ird Ird;
216 } Fields;
217 } MADB_Desc;
218
219 struct st_ma_desc_fldid
220 {
221 SQLSMALLINT FieldIdentifier;
222 SQLSMALLINT Access[4];
223 };
224
225 struct st_ma_stmt_methods;
226
227 typedef struct
228 {
229 SQLLEN MaxRows;
230 SQLLEN MaxLength;
231 SQLLEN KeysetSize;
232 SQLUINTEGER CursorType;
233 SQLUINTEGER ScrollConcurrency;
234 SQLUINTEGER RetrieveData;
235 SQLUINTEGER UseBookmarks;
236 void* BookmarkPtr;
237 SQLLEN BookmarkLength;
238 SQLSMALLINT BookmarkType;
239 SQLULEN MetadataId;
240 SQLULEN SimulateCursor;
241 } MADB_StmtOptions;
242
243 /* TODO: To check is it 0 or 1 based? not quite clear from its usage */
244 typedef struct
245 {
246 char *Name;
247 SQLLEN Position;
248 SQLLEN RowsetSize;
249 } MADB_Cursor;
250
251 enum MADB_DaeType {MADB_DAE_NORMAL=0, MADB_DAE_ADD=1, MADB_DAE_UPDATE=2, MADB_DAE_DELETE=3};
252
253 #define RESET_DAE_STATUS(Stmt_Hndl) (Stmt_Hndl)->Status=0; (Stmt_Hndl)->PutParam= -1
254 #define MARK_DAE_DONE(Stmt_Hndl) (Stmt_Hndl)->Status=0; (Stmt_Hndl)->PutParam= (Stmt_Hndl)->ParamCount
255
256 #define PARAM_IS_DAE(Len_Ptr) ((Len_Ptr) && (*(Len_Ptr) == SQL_DATA_AT_EXEC || *(Len_Ptr) <= SQL_LEN_DATA_AT_EXEC_OFFSET))
257 #define DAE_DONE(Stmt_Hndl) ((Stmt_Hndl)->PutParam >= (Stmt_Hndl)->ParamCount)
258
259 enum MADB_StmtState {MADB_SS_INITED= 0, MADB_SS_EMULATED= 1, MADB_SS_PREPARED= 2, MADB_SS_EXECUTED= 3, MADB_SS_OUTPARAMSFETCHED= 4};
260
261 #define STMT_WAS_PREPARED(Stmt_Hndl) (Stmt_Hndl->State >= MADB_SS_EMULATED)
262 #define RESET_STMT_STATE(Stmt_Hndl) Stmt_Hndl->State= STMT_WAS_PREPARED(Stmt_Hndl) ?\
263 (Stmt_Hndl->State == MADB_SS_EMULATED ? MADB_SS_EMULATED : MADB_SS_PREPARED) :\
264 MADB_SS_INITED
265
266 /* Struct used to define column type when driver has to fix it (in catalog functions + SQLGetTypeInfo) */
267 typedef struct
268 {
269 SQLSMALLINT SqlType;
270 my_bool Unsigned;
271 SQLSMALLINT Nullable;
272 SQLLEN OctetLength;
273
274 } MADB_ShortTypeInfo;
275
276 typedef struct
277 {
278 unsigned int ArraySize;
279 my_bool HasRowsToSkip;
280
281 } MADB_BulkOperationInfo;
282
283 /* Stmt struct needs definitions from my_parse.h */
284 #include <ma_parse.h>
285
286 #define STMT_STRING(STMT) (STMT)->Query.Original
287
288 struct st_ma_odbc_stmt
289 {
290 MADB_Dbc *Connection;
291 struct st_ma_stmt_methods *Methods;
292 MADB_StmtOptions Options;
293 MADB_Error Error;
294 MADB_Cursor Cursor;
295 MYSQL_STMT *stmt;
296 MYSQL_RES *metadata;
297 MADB_List ListItem;
298 MADB_QUERY Query;
299 SQLSMALLINT ParamCount;
300 enum MADB_DaeType DataExecutionType;
301 MYSQL_RES *DefaultsResult;
302 int ArrayOffset;
303 SQLSETPOSIROW DaeRowNumber;
304 int Status;
305 MADB_DescRecord *PutDataRec;
306 MADB_Stmt *DaeStmt;
307 MADB_Stmt *PositionedCursor;
308 my_bool PositionedCommand;
309 enum MADB_StmtState State;
310 MYSQL_STMT **MultiStmts;
311 unsigned int MultiStmtNr;
312 unsigned int MultiStmtMaxParam;
313 SQLLEN LastRowFetched;
314 MYSQL_BIND *result;
315 MYSQL_BIND *params;
316 int PutParam;
317 my_bool RebindParams;
318 my_bool bind_done;
319 long long AffectedRows;
320 unsigned long *CharOffset;
321 unsigned long *Lengths;
322 char *TableName;
323 char *CatalogName;
324 MADB_ShortTypeInfo *ColsTypeFixArr;
325 MADB_BulkOperationInfo Bulk;
326 /* Application Descriptors */
327 MADB_Desc *Apd;
328 MADB_Desc *Ard;
329 MADB_Desc *Ird;
330 MADB_Desc *Ipd;
331 /* Internal Descriptors */
332 MADB_Desc *IApd;
333 MADB_Desc *IArd;
334 MADB_Desc *IIrd;
335 MADB_Desc *IIpd;
336 };
337
338 typedef struct st_ma_odbc_environment {
339 MADB_Error Error;
340 CRITICAL_SECTION cs;
341 MADB_List *Dbcs;
342 SQLUINTEGER Trace;
343 SQLWCHAR *TraceFile;
344 SQLINTEGER OdbcVersion;
345 SQLINTEGER OutputNTS;
346 } MADB_Env;
347
348
349 #include <ma_dsn.h>
350
351
352 typedef struct st_client_charset
353 {
354 unsigned int CodePage;
355 MARIADB_CHARSET_INFO *cs_info;
356 } Client_Charset;
357
358 struct st_ma_odbc_connection
359 {
360 MYSQL *mariadb; /* handle to a mariadb connection */
361 CRITICAL_SECTION cs; /* mutex */
362 MADB_Env *Environment; /* global environment */
363 MADB_Dsn *Dsn;
364 struct st_ma_connection_methods *Methods;
365 MADB_Error Error;
366
367 Client_Charset Charset;
368 Client_Charset *ConnOrSrcCharset; /* "Source" here stands for which charset Windows DM was using as source, when converted to unicode.
369 We have to use same charset to recode from unicode to get same string as application sent it.
370 For Unicode application that is the same as "Charset", or in case of ANSI on Windows - defaulst system codepage */
371 char *DataBase;
372 MADB_List ListItem;
373 MADB_List *Stmts;
374 MADB_List *Descrs;
375 /* Attributes */
376 SQLINTEGER AccessMode;
377 my_bool IsAnsi;
378 SQLINTEGER IsolationLevel; /* tx_isolation */
379 SQLULEN AsyncEnable;
380 SQLUINTEGER AutoIpd;
381 SQLUINTEGER AutoCommit;
382 SQLUINTEGER ConnectionDead;
383 SQLUINTEGER ConnectionTimeout;
384 unsigned long Options;
385 char *CatalogName;
386 SQLPOINTER EnlistInDtc;
387 SQLUINTEGER LoginTimeout;
388 SQLUINTEGER MetadataId;
389 SQLULEN OdbcCursors;
390 SQLUINTEGER PacketSize;
391 HWND QuietMode;
392 SQLUINTEGER Trace;
393 char *TraceFile;
394 SQLINTEGER TxnIsolation;
395 SQLINTEGER CursorCount;
396 char ServerCapabilities;
397 };
398
399 typedef BOOL (__stdcall *PromptDSN)(HWND hwnd, MADB_Dsn *Dsn);
400
401 typedef struct
402 {
403 void *LibraryHandle;
404 PromptDSN Call;
405 } MADB_Prompt;
406
407 SQLRETURN DSNPrompt_Lookup(MADB_Prompt *prompt, const char *SetupLibName, MADB_Dbc *Dbc);
408 int DSNPrompt_Free (MADB_Prompt *prompt);
409
410 int InitClientCharset (Client_Charset *cc, const char * name);
411 void CopyClientCharset(Client_Charset * Src, Client_Charset * Dst);
412 void CloseClientCharset(Client_Charset *cc);
413
414 /* Default precision of SQL_NUMERIC */
415 #define MADB_DEFAULT_PRECISION 38
416 #define BINARY_CHARSETNR 63
417 /* Inexistent param id */
418 #define MADB_NOPARAM -1
419 /* Macros to guard communications with the server.
420 TODO: make it(locking) optional depending on designated connection string option */
421 #define LOCK_MARIADB(Dbc) EnterCriticalSection(&(Dbc)->cs)
422 #define UNLOCK_MARIADB(Dbc) LeaveCriticalSection(&(Dbc)->cs)
423
424 /* Enabling tracing */
425 #define MAODBC_DEBUG 1
426 /* Macro checks return of the suplied SQLRETURN function call, checks if it is succeeded, and in case of error pushes error up */
427 #define RETURN_ERROR_OR_CONTINUE(sqlreturn_func_call) {\
428 SQLRETURN rc= (sqlreturn_func_call);\
429 if (!SQL_SUCCEEDED(rc)) return rc;\
430 } while(0)
431
432 #define iOdbc() (sizeof(SQLWCHAR)==4)
433
434 #include <ma_error.h>
435 #include <ma_info.h>
436 #include <ma_environment.h>
437 #include <ma_connection.h>
438 #include <ma_debug.h>
439 #include <ma_desc.h>
440 #include <ma_statement.h>
441 #include <ma_string.h>
442 #include <ma_result.h>
443 #include <ma_driver.h>
444 #include <ma_helper.h>
445 #include <ma_server.h>
446 #include <ma_typeconv.h>
447 #include <ma_bulk.h>
448
449 /* SQLFunction calls inside MariaDB Connector/ODBC needs to be mapped,
450 * on non Windows platforms these function calls will call the driver
451 * manager function instead of our own function */
452 SQLRETURN MA_SQLAllocHandle(SQLSMALLINT HandleType,
453 SQLHANDLE InputHandle,
454 SQLHANDLE *OutputHandlePtr);
455
456 SQLRETURN MA_SQLBindParameter(SQLHSTMT StatementHandle,
457 SQLUSMALLINT ParameterNumber,
458 SQLSMALLINT InputOutputType,
459 SQLSMALLINT ValueType,
460 SQLSMALLINT ParameterType,
461 SQLULEN ColumnSize,
462 SQLSMALLINT DecimalDigits,
463 SQLPOINTER ParameterValuePtr,
464 SQLLEN BufferLength,
465 SQLLEN *StrLen_or_IndPtr);
466
467 SQLRETURN MA_SQLFreeStmt(SQLHSTMT StatementHandle,
468 SQLUSMALLINT Option);
469
470 SQLRETURN MA_SQLGetConnectAttr(SQLHDBC ConnectionHandle,
471 SQLINTEGER Attribute,
472 SQLPOINTER ValuePtr,
473 SQLINTEGER BufferLength,
474 SQLINTEGER *StringLengthPtr);
475
476 SQLRETURN MA_SQLPrepare(MADB_Stmt *Stmt,
477 SQLCHAR *StatementText,
478 SQLINTEGER TextLength);
479
480 SQLRETURN MA_SQLCancel(SQLHSTMT StatementHandle);
481
482 SQLRETURN MA_SQLGetDiagRec(SQLSMALLINT HandleType,
483 SQLHANDLE Handle,
484 SQLSMALLINT RecNumber,
485 SQLCHAR *SQLState,
486 SQLINTEGER *NativeErrorPtr,
487 SQLCHAR *MessageText,
488 SQLSMALLINT BufferLength,
489 SQLSMALLINT *TextLengthPtr);
490
491 SQLRETURN MA_SQLGetStmtAttr(SQLHSTMT StatementHandle,
492 SQLINTEGER Attribute,
493 SQLPOINTER ValuePtr,
494 SQLINTEGER BufferLength,
495 SQLINTEGER *StringLengthPtr);
496
497 SQLRETURN MA_SQLSetConnectAttr(SQLHDBC ConnectionHandle,
498 SQLINTEGER Attribute,
499 SQLPOINTER ValuePtr,
500 SQLINTEGER StringLength);
501
502 SQLRETURN MA_SQLSetStmtAttr(SQLHSTMT StatementHandle,
503 SQLINTEGER Attribute,
504 SQLPOINTER ValuePtr,
505 SQLINTEGER StringLength);
506
507 SQLRETURN MA_SQLAllocConnect(SQLHANDLE InputHandle,
508 SQLHANDLE *OutputHandlePtr);
509
510 SQLRETURN MADB_GetBookmark(MADB_Stmt *StatementHandle,
511 SQLSMALLINT TargetType,
512 SQLPOINTER TargetValuePtr,
513 SQLLEN BufferLength,
514 SQLLEN *StrLen_or_IndPtr);
515
516 SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr,
517 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, SQLLEN *NumericAttributePtr, my_bool IsWchar);
518
519 SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr,
520 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, SQLLEN *NumericAttributePtr, my_bool IsWchar);
521 #endif /* _ma_odbc_h_ */
0 /*
1 *
2 */
3
4 #ifndef _ma_odbc_version_h_
5 #define _ma_odbc_version_h_
6
7 #define MARIADB_ODBC_VERSION_MAJOR @MARIADB_ODBC_VERSION_MAJOR@
8 #define MARIADB_ODBC_VERSION_MINOR @MARIADB_ODBC_VERSION_MINOR@
9 #define MARIADB_ODBC_VERSION_PATCH @MARIADB_ODBC_VERSION_PATCH@
10
11 #define MARIADB_ODBC_VERSION "@MARIADB_ODBC_VERSION@"
12
13 #define MARIADB_ODBC_ERR_PREFIX "[ma-@MARIADB_ODBC_VERSION_MAJOR@.@MARIADB_ODBC_VERSION_MINOR@.@MARIADB_ODBC_VERSION_PATCH@]"
14
15 #define ODBCVER 0x0351
16
17 #define MADB_DEFAULT_PLUGINS_SUBDIR "@MARIADB_DEFAULT_PLUGINS_SUBDIR@"
18 #endif /* _ma_odbc_version_h_ */
0 /************************************************************************************
1 Copyright (C) 2013,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 #include <ma_odbc.h>
20
21 /* Minimal query length when we tried to avoid full parsing */
22 #define QUERY_LEN_FOR_POOR_MAN_PARSING 32768
23
24 char* SkipSpacesAndComments(char **CurPtr, size_t *Length, BOOL OverWrite)
25 {
26 char *End= *CurPtr + *Length, *Prev= NULL;
27
28 /* Making sure that we don't have leading whitespaces and/or comments,
29 and the string begins from something meainingful */
30 while (*CurPtr < End && *CurPtr != Prev)
31 {
32 Prev= *CurPtr;
33 *CurPtr= StripLeadingComments(*CurPtr, Length, OverWrite);
34 *CurPtr= ltrim(*CurPtr);
35 *Length= strlen(*CurPtr);
36 }
37
38 return *CurPtr;
39 }
40
41
42 char* SkipQuotedString(char **CurPtr, char *End, char Quote)
43 {
44 while (*CurPtr < End && **CurPtr != Quote)
45 {
46 /* Skipping backslash and next character, if needed */
47 if (**CurPtr == '\\')
48 {
49 ++*CurPtr;
50 /* Taking care of the case, when backslash is at last position */
51 if (*CurPtr == End)
52 {
53 break;
54 }
55 }
56 ++*CurPtr;
57 }
58
59 return *CurPtr;
60 }
61
62
63 char* SkipQuotedString_Noescapes(char **CurPtr, char *End, char Quote)
64 {
65 while (*CurPtr < End && **CurPtr != Quote)
66 {
67 ++*CurPtr;
68 }
69
70 return *CurPtr;
71 }
72
73
74 int MADB_ResetParser(MADB_Stmt *Stmt, char *OriginalQuery, SQLINTEGER OriginalLength)
75 {
76 MADB_DeleteQuery(&Stmt->Query);
77
78 if (OriginalQuery != NULL && OriginalLength > 0)
79 {
80 /* We can have here not NULL-terminated string as a source, thus we need to allocate, copy meaningful characters and
81 add NULL. strndup does that for us. StmtSopy may change, p points to the allocated memory */
82 Stmt->Query.allocated= Stmt->Query.RefinedText= strndup(OriginalQuery, OriginalLength);
83
84 if (Stmt->Query.allocated == NULL)
85 {
86 return 1;
87 }
88
89 Stmt->Query.RefinedLength= OriginalLength;
90 Stmt->Query.BatchAllowed= DSN_OPTION(Stmt->Connection, MADB_OPT_FLAG_MULTI_STATEMENTS) ? '\1' : '\0';
91 Stmt->Query.AnsiQuotes= MADB_SqlMode(Stmt->Connection, MADB_ANSI_QUOTES);
92 Stmt->Query.NoBackslashEscape= MADB_SqlMode(Stmt->Connection, MADB_NO_BACKSLASH_ESCAPES);
93 }
94
95 return 0;
96 }
97
98 void MADB_DeleteSubqueries(MADB_QUERY * Query)
99 {
100 unsigned int i;
101 SINGLE_QUERY SubQuery;
102
103 for (i= 0; i < Query->SubQuery.elements; ++i)
104 {
105 MADB_GetDynamic(&Query->SubQuery, (char *)&SubQuery, i);
106 MADB_DeleteDynamic(&SubQuery.ParamPos);
107 }
108 MADB_DeleteDynamic(&Query->SubQuery);
109 }
110
111 void MADB_AddSubQuery(MADB_QUERY * Query, char * SubQueryText, enum enum_madb_query_type QueryType)
112 {
113 SINGLE_QUERY SubQuery;
114
115 SubQuery.QueryText= SubQueryText;
116 SubQuery.QueryType= QueryType;
117 MADB_InitDynamicArray(&SubQuery.ParamPos, sizeof(unsigned int), 20, 20);
118
119 MADB_InsertDynamic(&Query->SubQuery, (char*)&SubQuery);
120 }
121
122
123 void MADB_DeleteQuery(MADB_QUERY *Query)
124 {
125 MADB_FREE(Query->allocated);
126 MADB_FREE(Query->Original);
127 MADB_DeleteDynamic(&Query->Tokens);
128
129 MADB_DeleteSubqueries(Query);
130
131 memset(Query, 0, sizeof(MADB_QUERY));
132 }
133
134 int MADB_ParseQuery(MADB_QUERY * Query)
135 {
136 /* make sure we don't have trailing whitespace or semicolon */
137 Query->RefinedLength= SqlRtrim(Query->RefinedText, (int)Query->RefinedLength);
138 Query->RefinedText= ltrim(Query->RefinedText);
139 Query->RefinedText= FixIsoFormat(Query->RefinedText, &Query->RefinedLength);
140 Query->RefinedLength-= Query->RefinedText - Query->allocated;
141
142 /* Making copy of "original" string, with minimal changes required to be able to execute */
143 Query->Original= strndup(Query->RefinedText, Query->RefinedLength);
144 SkipSpacesAndComments(&Query->RefinedText, &Query->RefinedLength, FALSE);
145
146 return ParseQuery(Query);
147 }
148
149 /*----------------- Tokens stuff ------------------*/
150
151 char *MADB_Token(MADB_QUERY *Query, unsigned int Idx)
152 {
153 char *p;
154 unsigned int Offset= 0;
155
156 p= Query->RefinedText;
157 if (!Query->Tokens.elements || !p)
158 return NULL;
159 if (Idx >= Query->Tokens.elements)
160 return NULL;
161
162 MADB_GetDynamic(&Query->Tokens, (char *)&Offset, Idx);
163 return Query->RefinedText + Offset;
164 }
165
166
167 my_bool MADB_CompareToken(MADB_QUERY *Query, unsigned int Idx, char *Compare, size_t Length, unsigned int *Offset)
168 {
169 char *TokenString;
170
171 if (!(TokenString= MADB_Token(Query, Idx)))
172 return FALSE;
173 if (_strnicmp(TokenString, Compare, Length) == 0)
174 {
175 if (Offset)
176 *Offset= (unsigned int)(TokenString - Query->RefinedText);
177 return TRUE;
178 }
179
180 return FALSE;
181 }
182
183 /* Not used atm, but may be useful */
184 unsigned int MADB_FindToken(MADB_QUERY *Query, char *Compare)
185 {
186 unsigned int i, TokenCount= Query->Tokens.elements;
187 unsigned int Offset= 0;
188
189 for (i=0; i < TokenCount; i++)
190 {
191 if (MADB_CompareToken(Query, i, Compare, strlen(Compare), &Offset))
192 return Offset;
193 }
194 return 0;
195 }
196
197
198 static char * ParseCursorName(MADB_QUERY *Query, unsigned int *Offset)
199 {
200 unsigned int i, TokenCount= Query->Tokens.elements;
201
202 if (TokenCount < 4)
203 {
204 return NULL;
205 }
206 for (i=0; i < TokenCount - 3; i++)
207 {
208 if (MADB_CompareToken(Query, i, "WHERE", 5, Offset) &&
209 MADB_CompareToken(Query, i+1, "CURRENT", 7, 0) &&
210 MADB_CompareToken(Query, i+2, "OF", 2, 0))
211 {
212 return MADB_Token(Query, i + 3);
213 }
214 }
215 return NULL;
216 }
217
218
219 static char * PoorManCursorName(MADB_QUERY *Query, unsigned int *Offset)
220 {
221 MADB_QUERY EndPiece;
222 char *Res;
223
224 memset(&EndPiece, 0, sizeof(MADB_QUERY));
225
226 /* We do poor man on long queries only, thus there is no need to check length */
227 EndPiece.RefinedText= ltrim(Query->RefinedText + Query->RefinedLength - MADB_MAX_CURSOR_NAME - 32/* "WHERE CURRENT OF" + spaces */);
228 EndPiece.RefinedLength= strlen(EndPiece.RefinedText);
229
230 /* As we did poor man parsing, we don't have full information about the query. Thus, parsing only this part at the end of the query -
231 we need tockens, to check if we have WHERE CURRENT OF in usual way */
232 if (ParseQuery(&EndPiece))
233 {
234 return NULL;
235 }
236
237 /* Now looking for cursor name in usual way */
238 Res= ParseCursorName(&EndPiece, Offset);
239
240 /* Incrementing Offset with the offset of our part of the query */
241 if (Res != NULL)
242 {
243 *Offset= (unsigned int)(*Offset + EndPiece.RefinedText - Query->RefinedText);
244 }
245
246 MADB_DeleteQuery(&EndPiece);
247
248 return Res;
249 }
250
251
252 char * MADB_ParseCursorName(MADB_QUERY *Query, unsigned int *Offset)
253 {
254 if (Query->PoorManParsing)
255 {
256 return PoorManCursorName(Query, Offset);
257 }
258
259 return ParseCursorName(Query, Offset);
260 }
261
262
263 enum enum_madb_query_type MADB_GetQueryType(const char *Token1, const char *Token2)
264 {
265 /* We need for the case when MS Access adds parenthesis around query - see ODBC-57*/
266 while (*Token1 && !isalpha(*Token1))
267 ++Token1;
268 if (_strnicmp(Token1, "SELECT", 6) == 0 || _strnicmp(Token1, "WITH", 4) == 0)
269 {
270 return MADB_QUERY_SELECT;
271 }
272 if (_strnicmp(Token1, "INSERT", 6) == 0)
273 {
274 return MADB_QUERY_INSERT;
275 }
276 if (_strnicmp(Token1, "UPDATE", 6) == 0)
277 {
278 return MADB_QUERY_UPDATE;
279 }
280 if (_strnicmp(Token1, "DELETE", 6) == 0)
281 {
282 return MADB_QUERY_DELETE;
283 }
284 if (_strnicmp(Token1, "CALL", 4) == 0)
285 {
286 return MADB_QUERY_CALL;
287 }
288 if (_strnicmp(Token1, "SHOW", 4) == 0)
289 {
290 return MADB_QUERY_SHOW;
291 }
292 if (_strnicmp(Token1, "ANALYZE", 7) == 0)
293 {
294 return MADB_QUERY_ANALYZE;
295 }
296 if (_strnicmp(Token1, "EXPLAIN", 7) == 0)
297 {
298 return MADB_QUERY_EXPLAIN;
299 }
300 if (_strnicmp(Token1, "CHECK", 5) == 0)
301 {
302 return MADB_QUERY_CHECK;
303 }
304 if (_strnicmp(Token1, "EXECUTE", 7) == 0)
305 {
306 return MADB_QUERY_EXECUTE;
307 }
308 if (_strnicmp(Token1, "CREATE", 6) == 0)
309 {
310 if (_strnicmp(Token2, "PROCEDURE", 9) == 0)
311 {
312 return MADB_QUERY_CREATE_PROC;
313 }
314 if (_strnicmp(Token2, "FUNCTION", 8) == 0)
315 {
316 return MADB_QUERY_CREATE_FUNC;
317 }
318 if (_strnicmp(Token2, "DEFINER", 7) == 0)
319 {
320 return MADB_QUERY_CREATE_DEFINER;
321 }
322 }
323 if (_strnicmp(Token1, "SET", 3) == 0)
324 {
325 if (_strnicmp(Token2, "NAMES", 5) == 0)
326 {
327 return MADB_QUERY_SET_NAMES;
328 }
329 else
330 {
331 return MADB_QUERY_SET;
332 }
333 }
334 if (_strnicmp(Token1, "DESC", 4) == 0)
335 {
336 return MADB_QUERY_DESCRIBE;
337 }
338 return MADB_QUERY_NO_RESULT;
339 }
340
341 /* -------------------- Tokens - End ----------------- */
342
343 /* Not used - rather a placeholder in case we need it */
344 const char * MADB_FindParamPlaceholder(MADB_Stmt *Stmt)
345 {
346 return STMT_STRING(Stmt);
347 }
348
349 /* Function assumes that query string has been trimmed */
350 char* FixIsoFormat(char * StmtString, size_t *Length)
351 {
352 if (StmtString[0] == '{' && StmtString[*Length -1] == '}')
353 {
354 char *Res;
355
356 ++StmtString;
357 StmtString[*Length - 1]= '\0';
358
359 Res= trim(StmtString);
360 *Length= strlen(Res);
361
362 return Res;
363 }
364
365 return StmtString;
366 }
367
368 #define SAVE_TOKEN(PTR2SAVE) do { Offset= (unsigned int)(PTR2SAVE - Query->RefinedText);\
369 MADB_InsertDynamic(&Query->Tokens, (char*)&Offset); } while(0)
370
371 static BOOL ShouldWeTryPoorManParsing(MADB_QUERY *Query)
372 {
373 return (Query->RefinedLength > QUERY_LEN_FOR_POOR_MAN_PARSING) && (strchr(Query->RefinedText, ';')) == NULL && (strchr(Query->RefinedText, '?') == NULL);
374 }
375
376 int ParseQuery(MADB_QUERY *Query)
377 {
378 char *p= Query->RefinedText, Quote;
379 BOOL ReadingToken= FALSE;
380 unsigned int Offset, StmtTokensCount= 0;
381 size_t Length= Query->RefinedLength;
382 char *end= p + Length, *CurQuery= NULL, *LastSemicolon= NULL;
383 enum enum_madb_query_type StmtType;
384
385 MADB_InitDynamicArray(&Query->Tokens, (unsigned int)sizeof(unsigned int), (unsigned int)MAX(Length/32, 20), (unsigned int)MAX(Length/20, 40));
386 MADB_InitDynamicArray(&Query->SubQuery, (unsigned int)sizeof(SINGLE_QUERY), (unsigned int)MAX(Length/64, 20), (unsigned int)MAX(Length/64, 40));
387
388 Query->PoorManParsing= ShouldWeTryPoorManParsing(Query);
389
390 while (p < end)
391 {
392 if (ReadingToken == FALSE)
393 {
394 Length= end - p;
395 SkipSpacesAndComments(&p, &Length, TRUE);
396
397 SAVE_TOKEN(p);
398
399 ++StmtTokensCount;
400 ReadingToken= TRUE;
401
402 /* On saving 1st statement's token, we are incrementing statements counter */
403 if (StmtTokensCount == 1)
404 {
405 CurQuery= p;
406 }
407 /* Having 2 first tockens we can get statement type. And we need to know it for the case of multistatement -
408 some statements may "legally" contain ';' */
409 else if (StmtTokensCount == 2)
410 {
411 /* We are currently at 2nd token of statement, and getting previous token position from Tokens array*/
412 StmtType= MADB_GetQueryType(MADB_Token(Query, Query->Tokens.elements - 2), p);
413 Query->ReturnsResult= Query->ReturnsResult || !QUERY_DOESNT_RETURN_RESULT(StmtType);
414 MADB_AddSubQuery(Query, CurQuery, StmtType);
415
416 /* If we on first statement, setting QueryType*/
417 if (Query->Tokens.elements == 2)
418 {
419 Query->QueryType= StmtType;
420 if (Query->PoorManParsing)
421 {
422 return 0;
423 }
424 }
425 }
426 switch (*p)
427 {
428 /* If some of them is opening a string, on the fall-through next `quote` won't be set,
429 as STRING_OR_COMMENT will be `true`. Likewise, if we are already in the string. But if we get hear,
430 we are not supposed to be inside a string */
431 case '"':
432 case '\'':
433 case '`':
434 {
435 char *SavePosition;
436 Quote= *p++;
437 SavePosition= p; /* In case we go past eos while looking for ending quote */
438 if (Query->NoBackslashEscape || Quote == '`' || /* Backtick works with ANSI_QUOTES */
439 (Query->AnsiQuotes && Quote == '"'))/* In indetifier quotation backslash does not escape anything - CLI has error with that */
440 {
441 SkipQuotedString_Noescapes(&p, end, Quote);
442 }
443 else
444 {
445 SkipQuotedString(&p, end, Quote);
446 }
447 if (p >= end)
448 {
449 /* Basically we got ending quote here - possible in poor man case, when we look for cursor name starting from the position inside string.
450 Other options are bad query of parsing error */
451 p= SavePosition;
452 ReadingToken= FALSE;
453 }
454 break;
455 }
456 case '?': /* This can break token(w/out space char), and be beginning of a token.
457 Thus we need it in both places */
458 Query->HasParameters= 1;
459 /* Parameter placeholder is a complete token. And next one may begin right after it*/
460 ReadingToken= FALSE;
461 break;
462 case ';':
463 if (QueryIsPossiblyMultistmt(Query))
464 {
465 /* If batches are not allowed, we only need the fact, that this is multi-statement */
466 if (Query->BatchAllowed)
467 {
468 *p= '\0';
469 }
470 StmtTokensCount= 0;
471 }
472 ReadingToken= FALSE;
473 /* We should not move pointer here */
474 break;
475 }
476 }
477 else
478 {
479 switch (*p)
480 {
481 case '?':
482 case '"':
483 case '\'':
484 case '`':
485 case ' ':
486 case '\t':
487 case '\r':
488 case '\n':
489 case '-':
490 case '#':
491 case '/':
492 case ';':
493 ReadingToken= FALSE;
494 /* We should not move pointer here, since this can be already beginning of new token */
495 continue;
496 default:
497 break;
498 }
499 }
500
501 ++p;
502 }
503
504 return 0;
505 }
506
507
508 char * StripLeadingComments(char *Str, size_t *Length, BOOL OverWrite)
509 {
510 char *Res= Str;
511 int ClosingStrLen= 1;
512
513 /* There is nothing to strip for sure */
514 if (*Length == 0)
515 {
516 return Str;
517 }
518
519 if (strncmp(Str, "--", 2) == 0)
520 {
521 Res= strchr(Str + 2, '\n');
522 }
523 else if (*Str == '#')
524 {
525 Res= strchr(Str + 1, '\n');
526 }
527 else if (strncmp(Str, "/*", 2) == 0)
528 {
529 Res= strstr(Str + 2, "*/");
530 ClosingStrLen= 2;
531 }
532
533 if (Res != Str)
534 {
535 if (Res != NULL)
536 {
537 Res+= ClosingStrLen;
538 *Length-= Res - Str;
539 }
540 else /* We found comment opening string, but did not find the closing string */
541 {
542 /* Thus moving pointer to the end of the string */
543 Res= Str + *Length;
544 *Length= 0;
545 }
546
547 /* On request - overwriting comment with white spaces */
548 if (OverWrite)
549 {
550 memset(Str, ' ', Res - Str);
551 }
552 }
553
554 return Res;
555 }
0 /************************************************************************************
1 Copyright (C) 2013,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_parse_h_
19 #define _ma_parse_h_
20
21 #include <sqlext.h>
22
23
24 enum enum_madb_query_type { MADB_QUERY_NO_RESULT= 0, /* Default type for the query types we are not interested in */
25 MADB_QUERY_INSERT,
26 MADB_QUERY_UPDATE= SQL_UPDATE,
27 MADB_QUERY_DELETE= SQL_DELETE,
28 MADB_QUERY_CREATE_PROC,
29 MADB_QUERY_CREATE_FUNC,
30 MADB_QUERY_CREATE_DEFINER,
31 MADB_QUERY_SET,
32 MADB_QUERY_SET_NAMES,
33 MADB_QUERY_SELECT,
34 MADB_QUERY_SHOW,
35 MADB_QUERY_CALL,
36 MADB_QUERY_ANALYZE,
37 MADB_QUERY_EXPLAIN,
38 MADB_QUERY_CHECK,
39 MADB_QUERY_EXECUTE,
40 MADB_QUERY_DESCRIBE
41 };
42
43 typedef struct {
44 char *QueryText;
45 enum enum_madb_query_type QueryType;
46 MADB_DynArray ParamPos;
47 } SINGLE_QUERY;
48
49 typedef struct {
50 char * Original;
51 char * allocated; /* Pointer to the allocated area. The refined query may go to the right */
52 char * RefinedText;
53 size_t RefinedLength;
54 MADB_DynArray Tokens;
55 MADB_DynArray SubQuery; /* List of queries or batches of queries, that can be executed together at once */
56 /* So far only falg whether we have any parameters */
57 my_bool HasParameters;
58 /* This is more for multistatements for optimization - if none of queries returns result,
59 we can send them via text protocol */
60 my_bool ReturnsResult;
61 enum enum_madb_query_type QueryType;
62 my_bool PoorManParsing;
63
64 my_bool BatchAllowed;
65 my_bool AnsiQuotes;
66 my_bool NoBackslashEscape;
67
68 } MADB_QUERY;
69
70 #define PQUERY_UPDATE_LEN(PARSED_QUERY_PTR) (PARSED_QUERY_PTR)->RefinedLength= strlen((PARSED_QUERY_PTR)->RefinedLength)
71 #define STMT_COUNT(PARSED_QUERY) ((PARSED_QUERY).SubQuery.elements/* + 1*/)
72 #define QUERY_IS_MULTISTMT(PARSED_QUERY) (STMT_COUNT(PARSED_QUERY) > 1)
73
74 int MADB_ResetParser(MADB_Stmt *Stmt, char *OriginalQuery, SQLINTEGER OriginalLength);
75 void MADB_DeleteSubqueries(MADB_QUERY *Query);
76 void MADB_AddSubQuery(MADB_QUERY *Query, char *SubQueryText, enum enum_madb_query_type QueryType);
77
78 void MADB_DeleteQuery(MADB_QUERY *Query);
79 int MADB_ParseQuery(MADB_QUERY *Query);
80
81 #define QUERY_DOESNT_RETURN_RESULT(query_type) ((query_type) < MADB_QUERY_SELECT)
82
83 char * MADB_ParseCursorName(MADB_QUERY *Query, unsigned int *Offset);
84 unsigned int MADB_FindToken(MADB_QUERY *Query, char *Compare);
85
86 enum enum_madb_query_type MADB_GetQueryType(const char *Token1, const char *Token2);
87
88 const char * MADB_FindParamPlaceholder(MADB_Stmt *Stmt);
89 char * FixIsoFormat(char * StmtString, size_t *Length);
90 int ParseQuery(MADB_QUERY *Query);
91 char * StripLeadingComments(char *s, size_t *Length, BOOL OverWrite);
92
93 #endif /* _ma_parse_h_ */
0 /************************************************************************************
1 Copyright (C) 2014,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19
20 /* MariaDB ODBC driver helper functions for platforms other than windows(so far) */
21
22 /* NOTE If you change something in this program, please consider if other platform's version
23 of the function you are changing, needs to be changed accordingly */
24
25 #include <ma_odbc.h>
26 #include <stdarg.h>
27
28 extern MARIADB_CHARSET_INFO *DmUnicodeCs;
29 extern Client_Charset utf8;
30
31 char LogFile[256];
32
33
34 void InitializeCriticalSection(CRITICAL_SECTION *cs)
35 {
36 pthread_mutexattr_t attr;
37
38 pthread_mutexattr_init(&attr);
39 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
40 pthread_mutex_init(cs, &attr);
41 }
42
43 SQLRETURN DSNPrompt_Lookup(MADB_Prompt *prompt, const char * SetupLibName, MADB_Dbc *Dbc)
44 {
45 MADB_SetError(&Dbc->Error, MADB_ERR_HY000, "Prompting is not supported on this platform", 0);
46 return Dbc->Error.ReturnValue;
47 }
48
49
50 int DSNPrompt_Free (MADB_Prompt *prompt)
51 {
52 prompt->LibraryHandle= NULL;
53
54 return 0;
55 }
56
57 /* Mimicking of VS' _snprintf */
58 int _snprintf(char *buffer, size_t count, const char *format, ...)
59 {
60 va_list list;
61 va_start(list, format);
62 int result= vsnprintf(buffer, count, format, list);
63
64 va_end(list);
65
66 /* _snprintf returns negative number if buffer is not big enough */
67 if (result > count)
68 {
69 return count - result - 1;
70 }
71 return result;
72 }
73
74
75 int strcpy_s(char *dest, size_t buffer_size, const char *src)
76 {
77 size_t src_len;
78
79 if (dest == NULL)
80 {
81 return EINVAL;
82 }
83
84 if (src == NULL)
85 {
86 *dest= '\0';
87 return EINVAL;
88 }
89
90 src_len= strlen(src);
91
92 if (buffer_size < src_len + 1)
93 {
94 *dest= 0;
95 return ERANGE;
96 }
97
98 memcpy((void*)dest, (void*)src, src_len + 1);
99
100 return 0;
101 }
102
103
104 const char* GetDefaultLogDir()
105 {
106 const char *DefaultLogDir="/tmp";
107 char *tmp= getenv("HOME");
108
109 if (tmp)
110 {
111 DefaultLogDir= tmp;
112 }
113
114 _snprintf(LogFile, sizeof(LogFile), "%s/maodbc.log", DefaultLogDir);
115
116 return LogFile;
117 }
118
119
120 /* CharLen < 0 - treat as NTS */
121 SQLINTEGER SqlwcsOctetLen(const SQLWCHAR *str, SQLINTEGER *CharLen)
122 {
123 SQLINTEGER result= 0, inChars= *CharLen;
124
125 if (str)
126 {
127 while (inChars > 0 || (inChars < 0 && *str))
128 {
129 result+= DmUnicodeCs->mb_charlen(*str);
130 --inChars;
131 str+= DmUnicodeCs->mb_charlen(*str)/sizeof(SQLWCHAR);
132 }
133 }
134
135 if (*CharLen < 0)
136 {
137 *CharLen-= inChars;
138 }
139 return result;
140 }
141
142
143 SQLWCHAR *MADB_ConvertToWchar(const char *Ptr, SQLLEN PtrLength, Client_Charset* cc)
144 {
145 SQLWCHAR *WStr= NULL;
146 size_t Length= 0;
147
148 if (!Ptr)
149 return WStr;
150
151 if (PtrLength == SQL_NTS)
152 {
153 PtrLength= -1;
154 /* To copy terminating null as well */
155 Length= 1;
156 }
157
158 if (!cc || !cc->CodePage)
159 cc= &utf8;
160
161 Length+= MbstrOctetLen(Ptr, &PtrLength, cc->cs_info);
162
163 if ((WStr= (SQLWCHAR *)MADB_CALLOC(sizeof(SQLWCHAR) * (PtrLength + 1))))
164 {
165 size_t wstr_octet_len= sizeof(SQLWCHAR) * (PtrLength + 1);
166 /* TODO: Need error processing. i.e. if mariadb_convert_string returns -1 */
167 mariadb_convert_string(Ptr, &Length, cc->cs_info, (char*)WStr, &wstr_octet_len, DmUnicodeCs, NULL);
168 }
169
170 return WStr;
171 }
172
173
174 /* {{{ MADB_ConvertFromWChar */
175 char *MADB_ConvertFromWChar(const SQLWCHAR *Ptr, SQLINTEGER PtrLength, SQLULEN *Length, Client_Charset *cc,
176 BOOL *Error)
177 {
178 char *AscStr;
179 size_t AscLen= PtrLength, PtrOctetLen;
180 BOOL dummyError= 0;
181
182 if (Error)
183 {
184 *Error= 0;
185 }
186 else
187 {
188 Error= &dummyError;
189 }
190
191 if (cc == NULL || cc->CodePage < 1)
192 {
193 cc= &utf8;
194 }
195
196 if (PtrLength == SQL_NTS)
197 {
198 /*-1 - to calculate length as of nts */
199 SQLINTEGER InCharLen= -1;
200 PtrOctetLen= SqlwcsOctetLen(Ptr, &InCharLen);
201 /* Allocating +1 character for terminating symbol */
202 AscLen= (InCharLen+1)*cc->cs_info->char_maxlen;
203 }
204 else
205 {
206 /* PtrLength is in characters. mariadb_convert_string(iconv) needs bytes */
207 PtrOctetLen= SqlwcsOctetLen(Ptr, &PtrLength);
208 AscLen= PtrLength*cc->cs_info->char_maxlen;
209 }
210
211 if (!(AscStr = (char *)MADB_CALLOC(AscLen)))
212 return NULL;
213
214 AscLen= mariadb_convert_string((char*)Ptr, &PtrOctetLen, DmUnicodeCs, AscStr, &AscLen, cc->cs_info, Error);
215
216 if (AscLen != (size_t)-1)
217 {
218 if (PtrLength == -1 && AscLen > 0)
219 {
220 --AscLen;
221 }
222 }
223 else
224 {
225 MADB_FREE(AscStr);
226 AscLen= 0;
227 }
228 if (Length)
229 *Length= (SQLINTEGER)AscLen;
230
231 return AscStr;
232 }
233 /* }}} */
234
235 /* {{{ MADB_ConvertAnsi2Unicode
236 @AnsiLength[in] - number of bytes to copy, negative if AnsiString is Null terminated and the terminating blank has to be copied
237 @UnicodeLength[in] - size of output buffer in chars, that effectively mean in SQLWCHAR units
238 @LengthIndicator[out] - number of available characters not counting terminating null(unless it was included in AnsiLength, and IsNull
239 is FALSE)
240 @IsNull[in] - whether to copy terminating blank. The value has to be 1 or 0(TRUE/FALSE)
241 If AnsiString is negative, its value is neglected(null is copied)
242 @returns 1 in case of error, 0 otherwise */
243 int MADB_ConvertAnsi2Unicode(Client_Charset *cc, const char *AnsiString, SQLLEN AnsiLength,
244 SQLWCHAR *UnicodeString, SQLLEN UnicodeLength,
245 SQLLEN *LengthIndicator, BOOL IsNull, MADB_Error *Error)
246 {
247 SQLINTEGER RequiredLength;
248 SQLWCHAR *Tmp= UnicodeString;
249 int rc= 0, error;
250 size_t SrcOctetLen, DestOctetLen;
251
252 if (LengthIndicator)
253 *LengthIndicator= 0;
254
255 if (Error)
256 MADB_CLEAR_ERROR(Error);
257
258 if (!AnsiLength || UnicodeLength < 0)
259 {
260 if (Error)
261 MADB_SetError(Error, MADB_ERR_HY090, NULL, 0);
262 return 1;
263 }
264
265 if (AnsiLength == SQL_NTS || AnsiLength == -1)
266 {
267 IsNull= 1;
268 AnsiLength= strlen(AnsiString);
269 }
270
271 /* calculate required length */
272 RequiredLength= MbstrCharLen(AnsiString, AnsiLength, cc->cs_info) + IsNull;
273
274 /* Set LengthIndicator */
275 if (LengthIndicator)
276 *LengthIndicator= RequiredLength - IsNull;
277 /* No buffer length, no need to copy - got length and run */
278 if (!UnicodeLength)
279 return 0;
280
281 if (RequiredLength > UnicodeLength)
282 {
283 Tmp= (SQLWCHAR *)malloc(RequiredLength * sizeof(SQLWCHAR));
284 }
285 else
286 {
287 RequiredLength= UnicodeLength;
288 }
289
290 SrcOctetLen= AnsiLength + IsNull;
291 DestOctetLen= sizeof(SQLWCHAR) * RequiredLength;
292
293 RequiredLength= mariadb_convert_string(AnsiString, &SrcOctetLen, cc->cs_info,
294 (char*)Tmp, &DestOctetLen, DmUnicodeCs, &error);
295
296 if (RequiredLength < 1)
297 {
298 if (Error)
299 MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", error);
300 rc= 1;
301 goto end;
302 }
303
304 if (LengthIndicator)
305 *LengthIndicator= SqlwcsCharLen(Tmp, RequiredLength);
306
307 /* Truncation */
308 if (Tmp != UnicodeString)
309 {
310 memcpy((void*)UnicodeString, (void*)Tmp, (UnicodeLength-1)*sizeof(SQLWCHAR));
311 *(UnicodeString + UnicodeLength - 1)= 0;
312
313 if (Error)
314 MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
315 }
316 end:
317 if (Tmp != UnicodeString)
318 free(Tmp);
319 return rc;
320 }
321 /* }}} */
322
323 /* {{{ MADB_ConvertAnsi2Unicode
324 @returns number of characters available at Src */
325 SQLLEN MADB_SetString(Client_Charset* cc, void *Dest, SQLULEN DestLength,
326 const char *Src, SQLLEN SrcLength/*bytes*/, MADB_Error *Error)
327 {
328 SQLLEN Length= 0;
329
330 if (SrcLength == SQL_NTS)
331 {
332 if (Src != NULL)
333 {
334 /* Thinking about utf8 - Should be probably len in characters */
335 SrcLength= strlen(Src);
336 }
337 else
338 {
339 SrcLength= 0;
340 }
341 }
342
343 /* Not enough space */
344 if (!DestLength || !Dest)
345 {
346 if (Dest)
347 MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
348 if (!cc)
349 return SrcLength;
350 else
351 {
352 Length= MbstrCharLen(Src, SrcLength, cc->cs_info);
353
354 /* In case of !DestLength || !Dest(application didn't give buffer and probably wants to know required length)
355 * we most probably have empty Src, and Length will be equal 0 in this case.
356 * Taking source length as character length. MultiByteToWideChar on windows does that for us */
357 return Length == 0 && SrcLength > 0 ? SrcLength : Length;
358 }
359 }
360
361 if (!SrcLength || !Src || !strlen(Src))
362 {
363 memset((char *)Dest, 0, cc ? sizeof(SQLWCHAR) : sizeof(SQLCHAR));
364 return 0;
365 }
366
367 if (!cc)
368 {
369 strncpy_s((char *)Dest, DestLength, Src ? Src : "", _TRUNCATE);
370 /* strncpy does not write null at the end */
371 *((char *)Dest + MIN(SrcLength, DestLength - 1))= '\0';
372
373 if (Error && SrcLength >= DestLength)
374 MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
375 return SrcLength;
376 }
377 else
378 {
379 MADB_ConvertAnsi2Unicode(cc, Src, -1, (SQLWCHAR *)Dest, DestLength, &Length, TRUE, Error);
380 return Length;
381 }
382 }
383 /* }}} */
384
385
386 /* Stub - needed on windows only */
387 int GetSourceAnsiCs(Client_Charset *cc)
388 {
389 CopyClientCharset(&utf8, cc);
390 return cc->CodePage;
391 }
392
393 /* {{{ MADB_DSN_PossibleConnect(MADB_Dsn *) */
394 BOOL MADB_DSN_PossibleConnect(MADB_Dsn *Dsn)
395 {
396 return Dsn->Socket || (Dsn->ServerName && Dsn->Port > 0 && Dsn->IsTcpIp);
397 }
398
399
400 /* Stub - atm it looks like we don't need to do anything here */
401 void MADB_SetDefaultPluginsDir(MADB_Dbc *Dbc)
402 {
403 }
0 /************************************************************************************
1 Copyright (C) 2014 SkySQL AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19
20 /* MariaDB ODBC driver platform dependent declarations */
21
22 /* NOTE If you change something in this program, please consider if other platform's declaration
23 require similar change */
24
25
26 /* Only one "platform" header is supposed to be included */
27 #ifndef _ma_platform_x_h_
28 # define _ma_platform_x_h_
29
30 /* Need size_t */
31 #include <stdio.h>
32
33 #define __stdcall
34
35 #ifndef TRUE
36 # define TRUE 1
37 #endif
38 #ifndef FALSE
39 # define FALSE 0
40 #endif
41
42 //#define HAVE_UNICODE
43
44 #define MADB_DRIVER_NAME "libmaodbc.so"
45 #define CP_UTF8 65001
46
47 #define _strdup strdup
48 #define _stricmp strcasecmp
49 #define _strnicmp strncasecmp
50 #define _atoi64(str) strtoll((str), NULL, 10)
51
52 #define _i64toa(a,b,c) longlong2str((a),(b),(c))
53
54 /* Mimicking of VS' _snprintf */
55 int _snprintf(char *buffer, size_t count, const char *format, ...);
56
57 /* Error codes fo strcpy_s */
58 #ifndef EINVAL
59 # define EINVAL 22
60 #endif
61 #ifndef ERANGE
62 # define ERANGE 34
63 #endif
64 int strcpy_s(char *dest, size_t buffer_size, const char *src);
65
66 #define strncpy_s(a,b,c,d) strncpy((a),(c),(b))
67
68 /* Critical section -> pthread mutex */
69 #include <pthread.h>
70
71 #define CRITICAL_SECTION pthread_mutex_t
72
73 #define EnterCriticalSection(cs) pthread_mutex_lock((cs))
74 #define LeaveCriticalSection(cs) pthread_mutex_unlock((cs))
75 #define DeleteCriticalSection(cs) pthread_mutex_destroy((cs))
76
77 #ifndef TryEnterCriticalSection
78 # define TryEnterCriticalSection !pthread_mutex_trylock
79 #endif
80
81 void InitializeCriticalSection(CRITICAL_SECTION *cs);
82
83 #endif /*_ma_platform_x_h_ */
84
0 /************************************************************************************
1 Copyright (C) 2014,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19
20 /* MariaDB ODBC driver Win32 specific helper functions */
21
22 /* NOTE If you change something in this program, please consider if other platform's version
23 of the function you are changing, needs to be changed accordingly */
24
25 #include <ma_odbc.h>
26 #include "Shlwapi.h"
27
28 extern Client_Charset utf8;
29 char LogFile[256];
30
31 char *strndup(const char *s, size_t n)
32 {
33 size_t len= MIN(strlen(s), n);
34 char *res= (char*)malloc(len + 1);
35
36 if (res != NULL)
37 {
38 memcpy(res, s, len);
39 res[len]= '\0';
40 }
41
42 return res;
43 }
44
45
46 const char* GetDefaultLogDir()
47 {
48 const char *DefaultLogDir= "c:";
49 char *tmp= getenv("USERPROFILE");
50 if (tmp)
51 {
52 DefaultLogDir= tmp;
53 }
54
55 tmp= getenv("TMP");
56 if (tmp)
57 {
58 DefaultLogDir= tmp;
59 }
60
61 _snprintf(LogFile, sizeof(LogFile), "%s\\MAODBC.LOG", DefaultLogDir);
62
63 return LogFile;
64 }
65
66
67 /* Connection is needed to set custom error */
68 SQLRETURN DSNPrompt_Lookup(MADB_Prompt *prompt, const char * SetupLibName, MADB_Dbc *Dbc)
69 {
70 if (!(prompt->LibraryHandle=(void*) LoadLibrary(SetupLibName)))
71 {
72 return MADB_SetError(&Dbc->Error, MADB_ERR_HY000, "Couldn't load setup library", 0);
73 }
74 if (!(prompt->Call= (PromptDSN)GetProcAddress((HMODULE)prompt->LibraryHandle, "DSNPrompt")))
75 {
76 return MADB_SetError(&Dbc->Error, MADB_ERR_HY000, "Couldn't find DSNPrompt function in setup library", 0);
77 }
78
79 return SQL_SUCCESS;
80 }
81
82
83 int DSNPrompt_Free(MADB_Prompt *prompt)
84 {
85 if (prompt->LibraryHandle != NULL)
86 {
87 FreeLibrary((HMODULE)prompt->LibraryHandle);
88 }
89 prompt->LibraryHandle= NULL;
90 prompt->Call= NULL;
91
92 return 0;
93 }
94
95
96 SQLWCHAR *MADB_ConvertToWchar(const char *Ptr, SQLLEN PtrLength, Client_Charset* cc)
97 {
98 SQLWCHAR *WStr= NULL;
99 int Length;
100
101 if (!Ptr)
102 return WStr;
103
104 if (PtrLength == SQL_NTS)
105 PtrLength= -1;
106
107 if (!cc || !cc->CodePage)
108 cc= &utf8;
109
110 /* TODO: Check this
111 In fact MultiByteToWideChar does not copy terminating character by default
112 Thus +1 does not make sense
113 "If the function succeeds and cchWideChar is 0, the return value is the required size,
114 in characters, for the buffer indicated by lpWideCharStr...
115 MultiByteToWideChar does not null-terminate an output string if the input string length
116 is explicitly specified without a terminating null character. To null-terminate an output
117 string for this function, the application should pass in -1 or explicitly count the
118 terminating null character for the input string." */
119 if ((Length= MultiByteToWideChar(cc->CodePage, 0, Ptr, (int)PtrLength, NULL, 0)))
120 if ((WStr= (SQLWCHAR *)MADB_CALLOC(sizeof(SQLWCHAR) * Length + 1)))
121 MultiByteToWideChar(cc->CodePage, 0, Ptr, (int)PtrLength, WStr, Length);
122 return WStr;
123 }
124
125 /* {{{ MADB_ConvertFromWChar
126 Length gets number of written bytes including TN (if WstrCharLen == -1 or SQL_NTS or if WstrCharLen includes
127 TN in the Wstr) */
128 char *MADB_ConvertFromWChar(const SQLWCHAR *Wstr, SQLINTEGER WstrCharLen, SQLULEN *Length/*Bytes*/, Client_Charset *cc, BOOL *Error)
129 {
130 char *AscStr;
131 int AscLen, AllocLen;
132
133 if (Error)
134 *Error= 0;
135
136 if (cc == NULL || cc->CodePage < 1)
137 {
138 cc= &utf8;
139 }
140
141 if (WstrCharLen == SQL_NTS)
142 WstrCharLen= -1;
143
144 AllocLen= AscLen= WideCharToMultiByte(cc->CodePage, 0, Wstr, WstrCharLen, NULL, 0, NULL, NULL);
145 if (WstrCharLen != -1)
146 ++AllocLen;
147
148 if (!(AscStr = (char *)MADB_CALLOC(AllocLen)))
149 return NULL;
150
151 AscLen= WideCharToMultiByte(cc->CodePage, 0, Wstr, WstrCharLen, AscStr, AscLen, NULL, (cc->CodePage != CP_UTF8) ? Error : NULL);
152 if (AscLen && WstrCharLen == -1)
153 --AscLen;
154
155 if (Length)
156 *Length= (SQLINTEGER)AscLen;
157 return AscStr;
158 }
159 /* }}} */
160
161 /* Required Length without or with TN(if IsNull is TRUE, or AnsiLength == -1 or SQL_NTS) is put to LenghtIndicator*/
162 int MADB_ConvertAnsi2Unicode(Client_Charset *cc, const char *AnsiString, SQLLEN AnsiLength,
163 SQLWCHAR *UnicodeString, SQLLEN UnicodeLength,
164 SQLLEN *LengthIndicator, BOOL IsNull, MADB_Error *Error)
165 {
166 SQLLEN RequiredLength;
167 SQLWCHAR *Tmp= UnicodeString;
168 int rc= 0;
169
170 if (LengthIndicator)
171 *LengthIndicator= 0;
172
173 if (Error)
174 MADB_CLEAR_ERROR(Error);
175
176 if (!AnsiLength || UnicodeLength < 0)
177 {
178 if (Error)
179 MADB_SetError(Error, MADB_ERR_HY090, NULL, 0);
180 return 1;
181 }
182
183 if (AnsiLength == SQL_NTS || AnsiLength == -1)
184 IsNull= 1;
185
186 /* calculate required length */
187 RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, NULL, 0);
188
189 /* Set LengthIndicator */
190 if (LengthIndicator)
191 *LengthIndicator= RequiredLength - IsNull;
192 if (!UnicodeLength)
193 return 0;
194
195 if (RequiredLength > UnicodeLength)
196 Tmp= (SQLWCHAR *)malloc(RequiredLength * sizeof(SQLWCHAR));
197
198 RequiredLength= MultiByteToWideChar(cc->CodePage, 0, AnsiString, IsNull ? -1 : (int)AnsiLength, Tmp, (int)RequiredLength);
199 if (RequiredLength < 1)
200 {
201 if (Error)
202 MADB_SetError(Error, MADB_ERR_HY000, "Ansi to Unicode conversion error occurred", GetLastError());
203 rc= 1;
204 goto end;
205 }
206
207 /* Truncation */
208 if (Tmp != UnicodeString)
209 {
210 wcsncpy(UnicodeString, L"", 1);
211 wcsncat(UnicodeString, Tmp, UnicodeLength- 1);
212 if (Error)
213 MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
214 }
215 end:
216 if (Tmp != UnicodeString)
217 free(Tmp);
218 return rc;
219 }
220
221 /* Returns required length for result string with(if dest and dest length are provided)
222 or without terminating NULL(otherwise). If cc is NULL, or not initialized(CodePage is 0),
223 then simply SrcLength is returned.
224 If Dest is not NULL, and DestLenth is 0, then error */
225 SQLLEN MADB_SetString(Client_Charset* cc, void *Dest, SQLULEN DestLength,
226 const char *Src, SQLLEN SrcLength/*bytes*/, MADB_Error *Error)
227 {
228 char *p= (char *)Dest;
229 SQLLEN Length= 0;
230
231 if (SrcLength == SQL_NTS)
232 {
233 if (Src != NULL)
234 {
235 SrcLength= strlen(Src);
236 }
237 else
238 {
239 SrcLength= 0;
240 }
241 }
242
243 /* Not enough space */
244 if (!DestLength || !Dest)
245 {
246 if (Dest)
247 MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
248 if (!cc || !cc->CodePage)
249 return SrcLength;
250 else
251 {
252 Length= MultiByteToWideChar(cc->CodePage, 0, Src, (int)SrcLength, NULL, 0);
253 return Length;
254 }
255 }
256
257 if (!Src || !strlen(Src) || !SrcLength)
258 {
259 memset(p, 0, cc && cc->CodePage ? sizeof(SQLWCHAR) : sizeof(SQLCHAR));
260 return 0;
261 }
262
263 if (!cc || !cc->CodePage)
264 {
265 strncpy_s((char *)Dest, DestLength, Src ? Src : "", _TRUNCATE);
266 if (Error && (SQLULEN)SrcLength >= DestLength)
267 MADB_SetError(Error, MADB_ERR_01004, NULL, 0);
268 return SrcLength;
269 }
270 else
271 {
272 MADB_ConvertAnsi2Unicode(cc, Src, -1, (SQLWCHAR *)Dest, DestLength, &Length, 1, Error);
273 return Length;
274 }
275 }
276
277
278 int GetSourceAnsiCs(Client_Charset *cc)
279 {
280 cc->CodePage= GetACP();
281
282 /* We don't need cs_info for this */
283 return cc->CodePage;
284 }
285
286 BOOL MADB_DirectoryExists(const char *Path)
287 {
288 DWORD FileAttributes = GetFileAttributes(Path);
289
290 return (FileAttributes != INVALID_FILE_ATTRIBUTES) && (FileAttributes & FILE_ATTRIBUTE_DIRECTORY);
291 }
292
293 void MADB_SetDefaultPluginsDir(MADB_Dbc *Dbc)
294 {
295 HMODULE hModule = GetModuleHandle(MADB_DRIVER_NAME);
296 char OurLocation[_MAX_PATH];
297 const char *PluginsSubDirName= "\\"MADB_DEFAULT_PLUGINS_SUBDIR;
298
299 GetModuleFileName(hModule, OurLocation, _MAX_PATH);
300 PathRemoveFileSpec(OurLocation);
301
302 if (strlen(OurLocation) < _MAX_PATH - strlen(PluginsSubDirName))
303 {
304 strcpy(OurLocation + strlen(OurLocation), PluginsSubDirName);
305
306 if (MADB_DirectoryExists(OurLocation) != FALSE)
307 {
308 mysql_options(Dbc->mariadb, MYSQL_PLUGIN_DIR, OurLocation);
309 }
310 }
311 }
312
313 /* {{{ MADB_DSN_PossibleConnect() */
314 BOOL MADB_DSN_PossibleConnect(MADB_Dsn *Dsn)
315 {
316 return Dsn->ServerName && (Dsn->IsNamedPipe || Dsn->Port > 0);
317 }
318 /* }}} */
319
320 /* {{{ strcasestr() */
321 char* strcasestr(const char* HayStack, const char* Needle)
322 {
323 return StrStrIA(HayStack, Needle);
324 }
325 /* }}} */
0 /************************************************************************************
1 Copyright (C) 2014,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19
20 /* MariaDB ODBC driver platform dependent declarations(win32) */
21
22 /* NOTE If you change something in this program, please consider if other platform's declaration
23 require similar change */
24
25 /* Only one "platform" header is supposed to be included */
26 #ifndef _ma_platform_x_h_
27
28 #define _ma_platform_x_h_
29
30 #define WIN32_LEAN_AND_MEAN
31 #define _WINSOCKAPI_
32 #define DONT_DEFINE_VOID
33 #define HAVE_UNICODE
34
35 #include <windows.h>
36 #include <WinSock2.h>
37 #include <shlwapi.h>
38
39 #if !defined(HAVE_mit_thread) && !defined(HAVE_STRTOK_R)
40 #define strtok_r(A,B,C) strtok((A),(B))
41 #endif
42 #define strcasecmp(A,B) _stricmp((A),(B))
43
44 #define MADB_DRIVER_NAME "maodbc.dll"
45
46 char *strndup(const char *s, size_t n);
47 char* strcasestr(const char* HayStack, const char* Needle);
48
49 #endif /*_ma_platform_x_h_ */
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20
21 /* {{{ MADB_StmtResetResultStructures */
22 void MADB_StmtResetResultStructures(MADB_Stmt *Stmt)
23 {
24 Stmt->CharOffset= (unsigned long *)MADB_REALLOC((char *)Stmt->CharOffset,
25 sizeof(long) * mysql_stmt_field_count(Stmt->stmt));
26 memset(Stmt->CharOffset, 0, sizeof(long) * mysql_stmt_field_count(Stmt->stmt));
27 Stmt->Lengths= (unsigned long *)MADB_REALLOC((char *)Stmt->Lengths,
28 sizeof(long) * mysql_stmt_field_count(Stmt->stmt));
29 memset(Stmt->Lengths, 0, sizeof(long) * mysql_stmt_field_count(Stmt->stmt));
30
31 Stmt->LastRowFetched= 0;
32 MADB_STMT_RESET_CURSOR(Stmt);
33 }
34 /* }}} */
35
36 /* {{{ MADB_StmtDataSeek */
37 SQLRETURN MADB_StmtDataSeek(MADB_Stmt *Stmt, my_ulonglong FetchOffset)
38 {
39 MYSQL_ROWS *tmp= NULL;
40
41 if (!Stmt->stmt->result.data)
42 {
43 return SQL_NO_DATA_FOUND;
44 }
45
46 mysql_stmt_data_seek(Stmt->stmt, FetchOffset);
47
48 return SQL_SUCCESS;
49 }
50 /* }}} */
51
52 /* {{{ MADB_StmtMoreResults */
53 SQLRETURN MADB_StmtMoreResults(MADB_Stmt *Stmt)
54 {
55 SQLRETURN ret= SQL_SUCCESS;
56
57 if (!Stmt->stmt)
58 {
59 return MADB_SetError(&Stmt->Error, MADB_ERR_08S01, NULL, 0);
60 }
61
62 /* We can't have it in MADB_StmtResetResultStructures, as it breaks dyn_cursor functionality.
63 Thus we free-ing bind structs on move to new result only */
64 MADB_FREE(Stmt->result);
65
66 if (Stmt->MultiStmts)
67 {
68 if (Stmt->MultiStmtNr == STMT_COUNT(Stmt->Query) - 1)
69 {
70 return SQL_NO_DATA;
71 }
72
73 ++Stmt->MultiStmtNr;
74
75 MADB_InstallStmt(Stmt, Stmt->MultiStmts[Stmt->MultiStmtNr]);
76
77 return SQL_SUCCESS;
78 }
79
80 /* in case we executed a multi statement, it was done via mysql_query */
81 if (Stmt->State == MADB_SS_EMULATED)
82 {
83 if (!mysql_more_results(Stmt->Connection->mariadb))
84 return SQL_NO_DATA;
85 else
86 {
87 LOCK_MARIADB(Stmt->Connection);
88 mysql_next_result(Stmt->Connection->mariadb);
89 if (mysql_field_count(Stmt->Connection->mariadb) != 0)
90 {
91 ret= MADB_SetError(&Stmt->Error, MADB_ERR_HY000, "Can't process text result", 0);
92 }
93 else
94 {
95 Stmt->AffectedRows= mysql_affected_rows(Stmt->Connection->mariadb);
96 }
97 UNLOCK_MARIADB(Stmt->Connection);
98 }
99 return ret;
100 }
101
102 if (mysql_stmt_more_results(Stmt->stmt))
103 {
104 mysql_stmt_free_result(Stmt->stmt);
105 }
106 else
107 {
108 return SQL_NO_DATA;
109 }
110
111 LOCK_MARIADB(Stmt->Connection);
112 if (mysql_stmt_next_result(Stmt->stmt) > 0)
113 {
114 UNLOCK_MARIADB(Stmt->Connection);
115 return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
116 }
117
118 MADB_StmtResetResultStructures(Stmt);
119
120 if (mysql_stmt_field_count(Stmt->stmt) == 0)
121 {
122 MADB_DescFree(Stmt->Ird, TRUE);
123 Stmt->AffectedRows= mysql_stmt_affected_rows(Stmt->stmt);
124 }
125 else
126 {
127 MADB_DescSetIrdMetadata(Stmt, mysql_fetch_fields(FetchMetadata(Stmt)), mysql_stmt_field_count(Stmt->stmt));
128 Stmt->AffectedRows= 0;
129
130 if (Stmt->Connection->mariadb->server_status & SERVER_PS_OUT_PARAMS)
131 {
132 Stmt->State= MADB_SS_OUTPARAMSFETCHED;
133 ret= Stmt->Methods->GetOutParams(Stmt, 0);
134 }
135 else
136 {
137 if (Stmt->Options.CursorType != SQL_CURSOR_FORWARD_ONLY)
138 {
139 mysql_stmt_store_result(Stmt->stmt);
140 mysql_stmt_data_seek(Stmt->stmt, 0);
141 }
142 }
143 UNLOCK_MARIADB(Stmt->Connection);
144 }
145
146 return ret;
147 }
148 /* }}} */
149
150 /* {{{ MADB_RecordsToFetch */
151 SQLULEN MADB_RowsToFetch(MADB_Cursor *Cursor, SQLULEN ArraySize, unsigned long long RowsInResultst)
152 {
153 SQLLEN Position= Cursor->Position >= 0 ? Cursor->Position : 0;
154 SQLULEN result= ArraySize;
155
156 Cursor->RowsetSize= ArraySize;
157
158 if (Position + ArraySize > RowsInResultst)
159 {
160 if (Position >= 0 && RowsInResultst > Position)
161 {
162 result= (SQLULEN)(RowsInResultst - Position);
163 }
164 else
165 {
166 result= 1;
167 }
168 }
169
170 return result;
171 }
172 /* }}} */
173
0 /************************************************************************************
1 Copyright (C) 2013,2018 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_result_h_
19 #define _ma_result_h_
20
21 void MADB_StmtResetResultStructures(MADB_Stmt *Stmt);
22 SQLRETURN MADB_StmtDataSeek (MADB_Stmt *Stmt, my_ulonglong FetchOffset);
23 SQLRETURN MADB_StmtMoreResults(MADB_Stmt *Stmt);
24 SQLULEN MADB_RowsToFetch(MADB_Cursor *Cursor, SQLULEN ArraySize, unsigned long long RowsInResultst);
25
26 #endif /* _ma_result_h_ */
0 /************************************************************************************
1 Copyright (C) 2016, 2017 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 /* Server-dependent functionality and helpers to use that functionality */
20
21 #include <ma_odbc.h>
22
23 unsigned long VersionCapabilityMap[][2]= {{100202, MADB_CAPABLE_EXEC_DIRECT},
24 {100207, MADB_ENCLOSES_COLUMN_DEF_WITH_QUOTES}};
25 unsigned long ExtCapabilitiesMap[][2]= {{MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32, MADB_CAPABLE_PARAM_ARRAYS}};
26
27 /* {{{ */
28 void MADB_SetCapabilities(MADB_Dbc *Dbc, unsigned long ServerVersion)
29 {
30 int i;
31 unsigned long ServerExtCapabilities;
32
33 for (i= 0; i < sizeof(VersionCapabilityMap)/sizeof(VersionCapabilityMap[0]); ++i)
34 {
35 if (ServerVersion >= VersionCapabilityMap[i][0])
36 {
37 Dbc->ServerCapabilities |= VersionCapabilityMap[i][1];
38 }
39 }
40
41 mariadb_get_infov(Dbc->mariadb, MARIADB_CONNECTION_EXTENDED_SERVER_CAPABILITIES, (void*)&ServerExtCapabilities);
42
43 for (i= 0; i < sizeof(ExtCapabilitiesMap)/sizeof(ExtCapabilitiesMap[0]); ++i)
44 {
45 if (!(Dbc->mariadb->server_capabilities & CLIENT_MYSQL)
46 && (ServerExtCapabilities & ExtCapabilitiesMap[i][0]))
47 {
48 Dbc->ServerCapabilities |= ExtCapabilitiesMap[i][1];
49 }
50 }
51 }
52
53 BOOL MADB_ServerSupports(MADB_Dbc *Dbc, char Capability)
54 {
55 return test(Dbc->ServerCapabilities & Capability);
56 }
57 /* }}} */
58
0 /************************************************************************************
1 Copyright (C) 2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 #ifndef _ma_server_h
20 #define _ma_server_h
21
22 #define MADB_CAPABLE_EXEC_DIRECT 1
23 #define MADB_CAPABLE_PARAM_ARRAYS 2
24 #define MADB_ENCLOSES_COLUMN_DEF_WITH_QUOTES 4
25
26 void MADB_SetCapabilities(MADB_Dbc *Dbc, unsigned long ServerVersion);
27 BOOL MADB_ServerSupports (MADB_Dbc *Dbc, char Capability);
28
29 #endif
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 struct st_ma_stmt_methods MADB_StmtMethods; /* declared at the end of file */
21
22 /* {{{ MADB_StmtInit */
23 SQLRETURN MADB_StmtInit(MADB_Dbc *Connection, SQLHANDLE *pHStmt)
24 {
25 MADB_Stmt *Stmt= NULL;
26
27 if (!(Stmt = (MADB_Stmt *)MADB_CALLOC(sizeof(MADB_Stmt))))
28 goto error;
29
30 MADB_PutErrorPrefix(Connection, &Stmt->Error);
31 *pHStmt= Stmt;
32 Stmt->Connection= Connection;
33
34 LOCK_MARIADB(Connection);
35
36 if (!(Stmt->stmt= MADB_NewStmtHandle(Stmt)) ||
37 !(Stmt->IApd= MADB_DescInit(Connection, MADB_DESC_APD, FALSE)) ||
38 !(Stmt->IArd= MADB_DescInit(Connection, MADB_DESC_ARD, FALSE)) ||
39 !(Stmt->IIpd= MADB_DescInit(Connection, MADB_DESC_IPD, FALSE)) ||
40 !(Stmt->IIrd= MADB_DescInit(Connection, MADB_DESC_IRD, FALSE)))
41 {
42 goto error;
43 }
44
45 MDBUG_C_PRINT(Stmt->Connection, "-->inited %0x", Stmt->stmt);
46
47 Stmt->PutParam= -1;
48 Stmt->Methods= &MADB_StmtMethods;
49 /* default behaviour is SQL_CURSOR_STATIC */
50 Stmt->Options.CursorType= SQL_CURSOR_STATIC;
51 Stmt->Options.UseBookmarks= SQL_UB_OFF;
52 Stmt->Options.MetadataId= Connection->MetadataId;
53
54 Stmt->Apd= Stmt->IApd;
55 Stmt->Ard= Stmt->IArd;
56 Stmt->Ipd= Stmt->IIpd;
57 Stmt->Ird= Stmt->IIrd;
58
59 Stmt->ListItem.data= (void *)Stmt;
60 Stmt->Connection->Stmts= MADB_ListAdd(Stmt->Connection->Stmts, &Stmt->ListItem);
61 UNLOCK_MARIADB(Connection);
62 Stmt->Ard->Header.ArraySize= 1;
63
64 return SQL_SUCCESS;
65
66 error:
67 if (Stmt && Stmt->stmt)
68 {
69 MADB_STMT_CLOSE_STMT(Stmt);
70 UNLOCK_MARIADB(Stmt->Connection);
71 }
72 MADB_DescFree(Stmt->IApd, TRUE);
73 MADB_DescFree(Stmt->IArd, TRUE);
74 MADB_DescFree(Stmt->IIpd, TRUE);
75 MADB_DescFree(Stmt->IIrd, TRUE);
76 MADB_FREE(Stmt);
77 return SQL_ERROR;
78 }
79 /* }}} */
80
81 /* {{{ MADB_ExecuteQuery */
82 SQLRETURN MADB_ExecuteQuery(MADB_Stmt * Stmt, char *StatementText, SQLINTEGER TextLength)
83 {
84 SQLRETURN ret= SQL_ERROR;
85
86 LOCK_MARIADB(Stmt->Connection);
87 if (StatementText)
88 {
89 MDBUG_C_PRINT(Stmt->Connection, "mysql_real_query(%0x,%s,%lu)", Stmt->Connection->mariadb, StatementText, TextLength);
90 if(!mysql_real_query(Stmt->Connection->mariadb, StatementText, TextLength))
91 {
92 ret= SQL_SUCCESS;
93 MADB_CLEAR_ERROR(&Stmt->Error);
94
95 Stmt->AffectedRows= mysql_affected_rows(Stmt->Connection->mariadb);
96 }
97 else
98 {
99 MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_DBC, Stmt->Connection->mariadb);
100 }
101 }
102 else
103 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, mysql_error(Stmt->Connection->mariadb),
104 mysql_errno(Stmt->Connection->mariadb));
105 UNLOCK_MARIADB(Stmt->Connection);
106
107 return ret;
108 }
109 /* }}} */
110
111 /* {{{ MADB_StmtBulkOperations */
112 SQLRETURN MADB_StmtBulkOperations(MADB_Stmt *Stmt, SQLSMALLINT Operation)
113 {
114 MADB_CLEAR_ERROR(&Stmt->Error);
115 switch(Operation)
116 {
117 case SQL_ADD:
118 return Stmt->Methods->SetPos(Stmt, 0, SQL_ADD, SQL_LOCK_NO_CHANGE, 0);
119 default:
120 return SQL_ERROR;
121 }
122 }
123 /* }}} */
124
125 /* {{{ RemoveStmtRefFromDesc
126 Helper function removing references to the stmt in the descriptor when explisitly allocated descriptor is substituted
127 by some other descriptor */
128 void RemoveStmtRefFromDesc(MADB_Desc *desc, MADB_Stmt *Stmt, BOOL all)
129 {
130 if (desc->AppType)
131 {
132 unsigned int i;
133 for (i=0; i < desc->Stmts.elements; ++i)
134 {
135 MADB_Stmt **refStmt= ((MADB_Stmt **)desc->Stmts.buffer) + i;
136 if (Stmt == *refStmt)
137 {
138 MADB_DeleteDynamicElement(&desc->Stmts, i);
139
140 if (!all)
141 {
142 return;
143 }
144 }
145 }
146 }
147 }
148 /* }}} */
149
150 /* {{{ ResetMetadata */
151 void ResetMetadata(MYSQL_RES** metadata, MYSQL_RES* new_metadata)
152 {
153 if (*metadata != NULL)
154 {
155 mysql_free_result(*metadata);
156 }
157
158 *metadata= new_metadata;
159 }
160 /* }}} */
161
162 /* {{{ MADB_StmtFree */
163 SQLRETURN MADB_StmtFree(MADB_Stmt *Stmt, SQLUSMALLINT Option)
164 {
165 if (!Stmt)
166 return SQL_INVALID_HANDLE;
167
168 switch (Option) {
169 case SQL_CLOSE:
170 if (Stmt->stmt)
171 {
172 if (Stmt->Ird)
173 MADB_DescFree(Stmt->Ird, TRUE);
174 if (Stmt->State > MADB_SS_PREPARED && !QUERY_IS_MULTISTMT(Stmt->Query))
175 {
176 MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_free_result(%0x)", Stmt->stmt);
177 mysql_stmt_free_result(Stmt->stmt);
178 LOCK_MARIADB(Stmt->Connection);
179 MDBUG_C_PRINT(Stmt->Connection, "-->resetting %0x", Stmt->stmt);
180 mysql_stmt_reset(Stmt->stmt);
181 UNLOCK_MARIADB(Stmt->Connection);
182 }
183 if (QUERY_IS_MULTISTMT(Stmt->Query) && Stmt->MultiStmts)
184 {
185 unsigned int i;
186 LOCK_MARIADB(Stmt->Connection);
187 for (i=0; i < STMT_COUNT(Stmt->Query); ++i)
188 {
189 if (Stmt->MultiStmts[i] != NULL)
190 {
191 MDBUG_C_PRINT(Stmt->Connection, "-->resetting %0x(%u)", Stmt->MultiStmts[i], i);
192 mysql_stmt_reset(Stmt->MultiStmts[i]);
193 }
194 }
195 UNLOCK_MARIADB(Stmt->Connection);
196 }
197
198 ResetMetadata(&Stmt->metadata, NULL);
199
200 MADB_FREE(Stmt->result);
201 MADB_FREE(Stmt->CharOffset);
202 MADB_FREE(Stmt->Lengths);
203
204 RESET_STMT_STATE(Stmt);
205 RESET_DAE_STATUS(Stmt);
206 }
207 break;
208 case SQL_UNBIND:
209 MADB_FREE(Stmt->result);
210 MADB_DescFree(Stmt->Ard, TRUE);
211 break;
212 case SQL_RESET_PARAMS:
213 MADB_FREE(Stmt->params);
214 MADB_DescFree(Stmt->Apd, TRUE);
215 RESET_DAE_STATUS(Stmt);
216 break;
217 case SQL_DROP:
218 MADB_FREE(Stmt->params);
219 MADB_FREE(Stmt->result);
220 MADB_FREE(Stmt->Cursor.Name);
221 MADB_FREE(Stmt->CatalogName);
222 MADB_FREE(Stmt->TableName);
223 ResetMetadata(&Stmt->metadata, NULL);
224
225 /* For explicit descriptors we only remove reference to the stmt*/
226 if (Stmt->Apd->AppType)
227 {
228 RemoveStmtRefFromDesc(Stmt->Apd, Stmt, TRUE);
229 MADB_DescFree(Stmt->IApd, FALSE);
230 }
231 else
232 {
233 MADB_DescFree( Stmt->Apd, FALSE);
234 }
235 if (Stmt->Ard->AppType)
236 {
237 RemoveStmtRefFromDesc(Stmt->Ard, Stmt, TRUE);
238 MADB_DescFree(Stmt->IArd, FALSE);
239 }
240 else
241 {
242 MADB_DescFree(Stmt->Ard, FALSE);
243 }
244 MADB_DescFree(Stmt->Ipd, FALSE);
245 MADB_DescFree(Stmt->Ird, FALSE);
246
247 MADB_FREE(Stmt->CharOffset);
248 MADB_FREE(Stmt->Lengths);
249 ResetMetadata(&Stmt->DefaultsResult, NULL);
250
251 if (Stmt->DaeStmt != NULL)
252 {
253 Stmt->DaeStmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
254 Stmt->DaeStmt= NULL;
255 }
256 EnterCriticalSection(&Stmt->Connection->cs);
257 /* TODO: if multistatement was prepared, but not executed, we would get here Stmt->stmt leaked. Unlikely that is very probable scenario,
258 thus leaving this for new version */
259 if (QUERY_IS_MULTISTMT(Stmt->Query) && Stmt->MultiStmts)
260 {
261 unsigned int i;
262 for (i= 0; i < STMT_COUNT(Stmt->Query); ++i)
263 {
264 /* This dirty hack allows to avoid crash in case stmt object was not allocated
265 TODO: The better place for this check would be where MultiStmts was not allocated
266 to avoid inconsistency(MultiStmtCount > 0 and MultiStmts is NULL */
267 if (Stmt->MultiStmts!= NULL && Stmt->MultiStmts[i] != NULL)
268 {
269 MDBUG_C_PRINT(Stmt->Connection, "-->closing %0x(%u)", Stmt->MultiStmts[i], i);
270 mysql_stmt_close(Stmt->MultiStmts[i]);
271 }
272 }
273 MADB_FREE(Stmt->MultiStmts);
274 Stmt->MultiStmtNr= 0;
275 }
276 else if (Stmt->stmt != NULL)
277 {
278 MDBUG_C_PRINT(Stmt->Connection, "-->closing %0x", Stmt->stmt);
279 MADB_STMT_CLOSE_STMT(Stmt);
280 }
281 /* Query has to be deleted after multistmt handles are closed, since the depends on info in the Query */
282 MADB_DeleteQuery(&Stmt->Query);
283 Stmt->Connection->Stmts= MADB_ListDelete(Stmt->Connection->Stmts, &Stmt->ListItem);
284
285 LeaveCriticalSection(&Stmt->Connection->cs);
286 MADB_FREE(Stmt);
287 } /* End of switch (Option) */
288 return SQL_SUCCESS;
289 }
290 /* }}} */
291
292 /* {{{ MADB_CheckIfExecDirectPossible
293 Checking if we can deploy mariadb_stmt_execute_direct */
294 BOOL MADB_CheckIfExecDirectPossible(MADB_Stmt *Stmt)
295 {
296 return MADB_ServerSupports(Stmt->Connection, MADB_CAPABLE_EXEC_DIRECT)
297 && !(Stmt->Apd->Header.ArraySize > 1) /* With array of parameters exec_direct will be not optimal */
298 && MADB_FindNextDaeParam(Stmt->Apd, -1, 1) == MADB_NOPARAM;
299 }
300 /* }}} */
301
302 /* {{{ MADB_CheckIfExecDirectPossible
303 Checking if we can deploy mariadb_stmt_execute_direct */
304 BOOL MADB_BulkInsertPossible(MADB_Stmt *Stmt)
305 {
306 return MADB_ServerSupports(Stmt->Connection, MADB_CAPABLE_PARAM_ARRAYS)
307 && (Stmt->Apd->Header.ArraySize > 1)
308 && (Stmt->Apd->Header.BindType == SQL_PARAM_BIND_BY_COLUMN) /* First we support column-wise binding */
309 && (Stmt->Query.QueryType == MADB_QUERY_INSERT || Stmt->Query.QueryType == MADB_QUERY_UPDATE)
310 && MADB_FindNextDaeParam(Stmt->Apd, -1, 1) == MADB_NOPARAM; /* TODO: should be not very hard ot optimize to use bulk in this
311 case for chunks of the array, delimitered by param rows with DAE
312 In particular, MADB_FindNextDaeParam should consider Stmt->ArrayOffset */
313 }
314 /* }}} */
315 /* {{{ MADB_StmtExecDirect */
316 SQLRETURN MADB_StmtExecDirect(MADB_Stmt *Stmt, char *StatementText, SQLINTEGER TextLength)
317 {
318 SQLRETURN ret;
319 BOOL ExecDirect= TRUE;
320
321 ret= Stmt->Methods->Prepare(Stmt, StatementText, TextLength, ExecDirect);
322 /* In case statement is not supported, we use mysql_query instead */
323 if (!SQL_SUCCEEDED(ret))
324 {
325 /* This is not quite good - 1064 may simply mean that syntax is wrong. we are screwed then */
326 if ((Stmt->Error.NativeError == 1295/*ER_UNSUPPORTED_PS*/ ||
327 Stmt->Error.NativeError == 1064/*ER_PARSE_ERROR*/))
328 {
329 Stmt->State= MADB_SS_EMULATED;
330 }
331 else
332 {
333 return ret;
334 }
335 }
336
337 /* For multistmt we don't use mariadb_stmt_execute_direct so far */
338 if (QUERY_IS_MULTISTMT(Stmt->Query))
339 {
340 ExecDirect= FALSE;
341 }
342
343 return Stmt->Methods->Execute(Stmt, ExecDirect);
344 }
345 /* }}} */
346
347 /* {{{ MADB_FindCursor */
348 MADB_Stmt *MADB_FindCursor(MADB_Stmt *Stmt, const char *CursorName)
349 {
350 MADB_Dbc *Dbc= Stmt->Connection;
351 MADB_List *LStmt, *LStmtNext;
352
353 for (LStmt= Dbc->Stmts; LStmt; LStmt= LStmtNext)
354 {
355 MADB_Cursor *Cursor= &((MADB_Stmt *)LStmt->data)->Cursor;
356 LStmtNext= LStmt->next;
357
358 if (Stmt != (MADB_Stmt *)LStmt->data &&
359 Cursor->Name && _stricmp(Cursor->Name, CursorName) == 0)
360 {
361 return (MADB_Stmt *)LStmt->data;
362 }
363 }
364 MADB_SetError(&Stmt->Error, MADB_ERR_34000, NULL, 0);
365 return NULL;
366 }
367 /* }}} */
368
369 /* {{{ FetchMetadata */
370 MYSQL_RES* FetchMetadata(MADB_Stmt *Stmt)
371 {
372 ResetMetadata(&Stmt->metadata, mysql_stmt_result_metadata(Stmt->stmt));
373 return Stmt->metadata;
374 }
375 /* }}} */
376
377 /* {{{ MADB_StmtReset - reseting Stmt handler for new use. Has to be called inside a lock */
378 void MADB_StmtReset(MADB_Stmt *Stmt)
379 {
380 if (!QUERY_IS_MULTISTMT(Stmt->Query) || Stmt->MultiStmts == NULL)
381 {
382 if (Stmt->State > MADB_SS_PREPARED)
383 {
384 MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_free_result(%0x)", Stmt->stmt);
385 mysql_stmt_free_result(Stmt->stmt);
386 }
387
388 if (Stmt->State >= MADB_SS_PREPARED)
389 {
390 MDBUG_C_PRINT(Stmt->Connection, "-->closing %0x", Stmt->stmt);
391 MADB_STMT_CLOSE_STMT(Stmt);
392 Stmt->stmt= MADB_NewStmtHandle(Stmt);
393
394 MDBUG_C_PRINT(Stmt->Connection, "-->inited %0x", Stmt->stmt);
395 }
396 }
397 else
398 {
399 CloseMultiStatements(Stmt);
400 Stmt->stmt= MADB_NewStmtHandle(Stmt);
401
402 MDBUG_C_PRINT(Stmt->Connection, "-->inited %0x", Stmt->stmt);
403 }
404
405 switch (Stmt->State)
406 {
407 case MADB_SS_EXECUTED:
408 case MADB_SS_OUTPARAMSFETCHED:
409
410 MADB_FREE(Stmt->result);
411 MADB_FREE(Stmt->CharOffset);
412 MADB_FREE(Stmt->Lengths);
413 RESET_DAE_STATUS(Stmt);
414
415 case MADB_SS_PREPARED:
416 ResetMetadata(&Stmt->metadata, NULL);
417
418 Stmt->PositionedCursor= NULL;
419 Stmt->Ird->Header.Count= 0;
420
421 case MADB_SS_EMULATED:
422 /* We can have the case, then query did not succeed, and in case of direct execution we wouldn't
423 have ane state set, but some of stuff still needs to be cleaned. Perhaps we could introduce a state
424 for such case, smth like DIREXEC_PREPARED. Would be more proper, but yet overkill */
425
426 if (QUERY_IS_MULTISTMT(Stmt->Query))
427 {
428 while (mysql_more_results(Stmt->Connection->mariadb))
429 {
430 mysql_next_result(Stmt->Connection->mariadb);
431 }
432 }
433 default:
434 Stmt->PositionedCommand= 0;
435 Stmt->State= MADB_SS_INITED;
436 MADB_CLEAR_ERROR(&Stmt->Error);
437 }
438 }
439 /* }}} */
440
441 /* {{{ MADB_EDPrepare - Method called from SQLPrepare in case it is SQLExecDirect and if server >= 10.2
442 (i.e. we gonna do mariadb_stmt_exec_direct) */
443 SQLRETURN MADB_EDPrepare(MADB_Stmt *Stmt)
444 {
445 /* TODO: In case of positioned command it shouldn't be always*/
446 if ((Stmt->ParamCount= Stmt->Apd->Header.Count + (MADB_POSITIONED_COMMAND(Stmt) ? MADB_POS_COMM_IDX_FIELD_COUNT(Stmt) : 0)) != 0)
447 {
448 if (Stmt->params)
449 {
450 MADB_FREE(Stmt->params);
451 }
452 /* If we have "WHERE CURRENT OF", we will need bind additionaly parameters for each field in the index */
453 Stmt->params= (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * Stmt->ParamCount);
454 }
455 return SQL_SUCCESS;
456 }
457 /* }}} */
458
459 /* {{{ MADB_RegularPrepare - Method called from SQLPrepare in case it is SQLExecDirect and if !(server > 10.2)
460 (i.e. we aren't going to do mariadb_stmt_exec_direct) */
461 SQLRETURN MADB_RegularPrepare(MADB_Stmt *Stmt)
462 {
463 LOCK_MARIADB(Stmt->Connection);
464
465 MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_prepare(%0x,%s)", Stmt->stmt, STMT_STRING(Stmt));
466 if (mysql_stmt_prepare(Stmt->stmt, STMT_STRING(Stmt), (unsigned long)strlen(STMT_STRING(Stmt))))
467 {
468 /* Need to save error first */
469 MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
470 /* We need to close the stmt here, or it becomes unusable like in ODBC-21 */
471 MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_close(%0x)", Stmt->stmt);
472 MADB_STMT_CLOSE_STMT(Stmt);
473 Stmt->stmt= MADB_NewStmtHandle(Stmt);
474
475 UNLOCK_MARIADB(Stmt->Connection);
476
477 MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_init(%0x)->%0x", Stmt->Connection->mariadb, Stmt->stmt);
478
479 return Stmt->Error.ReturnValue;
480 }
481 UNLOCK_MARIADB(Stmt->Connection);
482
483 Stmt->State= MADB_SS_PREPARED;
484
485 /* If we have result returning query - fill descriptor records with metadata */
486 if (mysql_stmt_field_count(Stmt->stmt) > 0)
487 {
488 MADB_DescSetIrdMetadata(Stmt, mysql_fetch_fields(FetchMetadata(Stmt)), mysql_stmt_field_count(Stmt->stmt));
489 }
490
491 if ((Stmt->ParamCount= (SQLSMALLINT)mysql_stmt_param_count(Stmt->stmt)))
492 {
493 if (Stmt->params)
494 {
495 MADB_FREE(Stmt->params);
496 }
497 Stmt->params= (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * Stmt->ParamCount);
498 }
499
500 return SQL_SUCCESS;
501 }
502 /* }}} */
503
504 /* {{{ MADB_StmtPrepare */
505 SQLRETURN MADB_StmtPrepare(MADB_Stmt *Stmt, char *StatementText, SQLINTEGER TextLength, BOOL ExecDirect)
506 {
507 char *CursorName= NULL;
508 unsigned int WhereOffset;
509 BOOL HasParameters= 0;
510
511 MDBUG_C_PRINT(Stmt->Connection, "%sMADB_StmtPrepare", "\t->");
512
513 LOCK_MARIADB(Stmt->Connection);
514
515 MADB_StmtReset(Stmt);
516
517 /* After this point we can't have SQL_NTS*/
518 ADJUST_LENGTH(StatementText, TextLength);
519
520 MADB_ResetParser(Stmt, StatementText, TextLength);
521 MADB_ParseQuery(&Stmt->Query);
522
523 /* if we have multiple statements we save single statements in Stmt->StrMultiStmt
524 and store the number in Stmt->MultiStmts */
525 if (QueryIsPossiblyMultistmt(&Stmt->Query) && QUERY_IS_MULTISTMT(Stmt->Query) &&
526 (Stmt->Query.ReturnsResult || Stmt->Query.HasParameters) && Stmt->Query.BatchAllowed) /* If neither of statements returns result,
527 and does not have parameters, we will run them
528 using text protocol */
529 {
530 if (ExecDirect != FALSE)
531 {
532 return MADB_EDPrepare(Stmt);
533 }
534 /* We had error preparing any of statements */
535 else if (GetMultiStatements(Stmt, ExecDirect))
536 {
537 return Stmt->Error.ReturnValue;
538 }
539
540 /* all statemtens successfully prepared */
541 UNLOCK_MARIADB(Stmt->Connection);
542 return SQL_SUCCESS;
543 }
544
545 UNLOCK_MARIADB(Stmt->Connection);
546
547 if (!MADB_ValidateStmt(&Stmt->Query))
548 {
549 MADB_SetError(&Stmt->Error, MADB_ERR_HY000, "SQL command SET NAMES is not allowed", 0);
550 return Stmt->Error.ReturnValue;
551 }
552
553 /* Transform WHERE CURRENT OF [cursorname]:
554 Append WHERE with Parameter Markers
555 In StmtExecute we will call SQLSetPos with update or delete:
556 */
557
558 if ((CursorName = MADB_ParseCursorName(&Stmt->Query, &WhereOffset)))
559 {
560 MADB_DynString StmtStr;
561 char *TableName;
562
563 /* Make sure we have a delete or update statement
564 MADB_QUERY_DELETE and MADB_QUERY_UPDATE defined in the enum to have the same value
565 as SQL_UPDATE and SQL_DELETE, respectively */
566 if (Stmt->Query.QueryType == MADB_QUERY_DELETE || Stmt->Query.QueryType == MADB_QUERY_UPDATE)
567 {
568 Stmt->PositionedCommand= 1;
569 }
570 else
571 {
572 MADB_SetError(&Stmt->Error, MADB_ERR_42000, "Invalid SQL Syntax: DELETE or UPDATE expected for positioned update", 0);
573 return Stmt->Error.ReturnValue;
574 }
575
576 if (!(Stmt->PositionedCursor= MADB_FindCursor(Stmt, CursorName)))
577 return Stmt->Error.ReturnValue;
578
579 TableName= MADB_GetTableName(Stmt->PositionedCursor);
580 MADB_InitDynamicString(&StmtStr, "", 8192, 1024);
581 MADB_DynstrAppendMem(&StmtStr, Stmt->Query.RefinedText, WhereOffset);
582 MADB_DynStrGetWhere(Stmt->PositionedCursor, &StmtStr, TableName, TRUE);
583
584 MADB_RESET(STMT_STRING(Stmt), StmtStr.str);
585 /* Constructed query we've copied for execution has parameters */
586 Stmt->Query.HasParameters= 1;
587 MADB_DynstrFree(&StmtStr);
588 }
589
590 if (Stmt->Options.MaxRows)
591 {
592 /* TODO: LIMIT is not always the last clause. And not applicable to each query type.
593 Thus we need to check query type and last tokens, and possibly put limit before them */
594 char *p;
595 STMT_STRING(Stmt)= realloc((char *)STMT_STRING(Stmt), strlen(STMT_STRING(Stmt)) + 40);
596 p= STMT_STRING(Stmt) + strlen(STMT_STRING(Stmt));
597 _snprintf(p, 40, " LIMIT %zd", Stmt->Options.MaxRows);
598 }
599
600 if (!Stmt->Query.ReturnsResult && !Stmt->Query.HasParameters &&
601 /* If have multistatement query, and this is not allowed, we want to do normal prepare.
602 To give it last chance. And to return correct error otherwise */
603 ! (QUERY_IS_MULTISTMT(Stmt->Query) && !Stmt->Query.BatchAllowed))
604 {
605 Stmt->State= MADB_SS_EMULATED;
606 return SQL_SUCCESS;
607 }
608
609 if (ExecDirect && MADB_CheckIfExecDirectPossible(Stmt))
610 {
611 return MADB_EDPrepare(Stmt);
612 }
613 else
614 {
615 return MADB_RegularPrepare(Stmt);
616 }
617 }
618 /* }}} */
619
620 /* {{{ MADB_StmtParamData */
621 SQLRETURN MADB_StmtParamData(MADB_Stmt *Stmt, SQLPOINTER *ValuePtrPtr)
622 {
623 MADB_Desc *Desc;
624 MADB_DescRecord *Record;
625 int ParamCount;
626 int i;
627 SQLRETURN ret;
628
629 if (Stmt->DataExecutionType == MADB_DAE_NORMAL)
630 {
631 if (!Stmt->Apd || !(ParamCount= Stmt->ParamCount))
632 {
633 MADB_SetError(&Stmt->Error, MADB_ERR_HY010, NULL, 0);
634 return Stmt->Error.ReturnValue;
635 }
636 Desc= Stmt->Apd;
637 }
638 else
639 {
640 if (!Stmt->Ard || !(ParamCount= Stmt->DaeStmt->ParamCount))
641 {
642 MADB_SetError(&Stmt->Error, MADB_ERR_HY010, NULL, 0);
643 return Stmt->Error.ReturnValue;
644 }
645 Desc= Stmt->DaeStmt->Apd;
646 }
647
648 /* If we have last DAE param(Stmt->PutParam), we are starting from the next one. Otherwise from first */
649 for (i= Stmt->PutParam > -1 ? Stmt->PutParam + 1 : 0; i < ParamCount; i++)
650 {
651 if ((Record= MADB_DescGetInternalRecord(Desc, i, MADB_DESC_READ)))
652 {
653 if (Record->OctetLengthPtr)
654 {
655 /* Stmt->DaeRowNumber is 1 based */
656 SQLLEN *OctetLength = (SQLLEN *)GetBindOffset(Desc, Record, Record->OctetLengthPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber - 1 : 0, sizeof(SQLLEN));
657 if (PARAM_IS_DAE(OctetLength))
658 {
659 Stmt->PutDataRec= Record;
660 *ValuePtrPtr = GetBindOffset(Desc, Record, Record->DataPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber - 1 : 0, Record->OctetLength);
661 Stmt->PutParam= i;
662 Stmt->Status= SQL_NEED_DATA;
663
664 return SQL_NEED_DATA;
665 }
666 }
667 }
668 }
669
670 /* reset status, otherwise SQLSetPos and SQLExecute will fail */
671 MARK_DAE_DONE(Stmt);
672 if (Stmt->DataExecutionType == MADB_DAE_ADD || Stmt->DataExecutionType == MADB_DAE_UPDATE)
673 {
674 MARK_DAE_DONE(Stmt->DaeStmt);
675 }
676
677 switch (Stmt->DataExecutionType) {
678 case MADB_DAE_NORMAL:
679 ret= Stmt->Methods->Execute(Stmt, FALSE);
680 RESET_DAE_STATUS(Stmt);
681 break;
682 case MADB_DAE_UPDATE:
683 ret= Stmt->Methods->SetPos(Stmt, Stmt->DaeRowNumber, SQL_UPDATE, SQL_LOCK_NO_CHANGE, 1);
684 RESET_DAE_STATUS(Stmt);
685 break;
686 case MADB_DAE_ADD:
687 ret= Stmt->DaeStmt->Methods->Execute(Stmt->DaeStmt, FALSE);
688 MADB_CopyError(&Stmt->Error, &Stmt->DaeStmt->Error);
689 RESET_DAE_STATUS(Stmt->DaeStmt);
690 break;
691 default:
692 ret= SQL_ERROR;
693 }
694 /* Interesting should we reset if execution failed? */
695
696 return ret;
697 }
698 /* }}} */
699
700 /* {{{ MADB_StmtPutData */
701 SQLRETURN MADB_StmtPutData(MADB_Stmt *Stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or_Ind)
702 {
703 MADB_DescRecord *Record;
704 MADB_Stmt *MyStmt= Stmt;
705 SQLPOINTER ConvertedDataPtr= NULL;
706 SQLULEN Length= 0;
707
708 MADB_CLEAR_ERROR(&Stmt->Error);
709
710 if (DataPtr != NULL && StrLen_or_Ind < 0 && StrLen_or_Ind != SQL_NTS && StrLen_or_Ind != SQL_NULL_DATA)
711 {
712 MADB_SetError(&Stmt->Error, MADB_ERR_HY090, NULL, 0);
713 return Stmt->Error.ReturnValue;
714 }
715
716 if (Stmt->DataExecutionType != MADB_DAE_NORMAL)
717 {
718 MyStmt= Stmt->DaeStmt;
719 }
720 Record= MADB_DescGetInternalRecord(MyStmt->Apd, Stmt->PutParam, MADB_DESC_READ);
721 assert(Record);
722
723 if (StrLen_or_Ind == SQL_NULL_DATA)
724 {
725 /* Check if we've already sent any data */
726 if (MyStmt->stmt->params[Stmt->PutParam].long_data_used)
727 {
728 MADB_SetError(&Stmt->Error, MADB_ERR_HY011, NULL, 0);
729 return Stmt->Error.ReturnValue;
730 }
731 Record->Type= SQL_TYPE_NULL;
732 return SQL_SUCCESS;
733 }
734
735 /* This normally should be enforced by DM */
736 if (DataPtr == NULL && StrLen_or_Ind != 0)
737 {
738 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, NULL, 0);
739 return Stmt->Error.ReturnValue;
740 }
741 /*
742 if (StrLen_or_Ind == SQL_NTS)
743 {
744 if (Record->ConciseType == SQL_C_WCHAR)
745 StrLen_or_Ind= wcslen((SQLWCHAR *)DataPtr);
746 else
747 StrLen_or_Ind= strlen((char *)DataPtr);
748 }
749 */
750 if (Record->ConciseType == SQL_C_WCHAR)
751 {
752 /* Conn cs */
753 ConvertedDataPtr= MADB_ConvertFromWChar((SQLWCHAR *)DataPtr, (SQLINTEGER)(StrLen_or_Ind/sizeof(SQLWCHAR)), &Length, &Stmt->Connection->Charset, NULL);
754
755 if ((ConvertedDataPtr == NULL || Length == 0) && StrLen_or_Ind > 0)
756 {
757 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
758 return Stmt->Error.ReturnValue;
759 }
760 }
761 else
762 {
763 if (StrLen_or_Ind == SQL_NTS)
764 {
765 Length= strlen((char *)DataPtr);
766 }
767 else
768 {
769 Length= StrLen_or_Ind;
770 }
771 }
772
773 /* To make sure that we will not consume the doble amount of memory, we need to send
774 data via mysql_send_long_data directly to the server instead of allocating a separate
775 buffer. This means we need to process Update and Insert statements row by row. */
776 if (mysql_stmt_send_long_data(MyStmt->stmt, Stmt->PutParam, (ConvertedDataPtr ? (char *)ConvertedDataPtr : DataPtr), (unsigned long)Length))
777 {
778 MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, MyStmt->stmt);
779 }
780 else
781 {
782 Record->InternalLength+= (unsigned long)Length;
783 }
784
785 MADB_FREE(ConvertedDataPtr);
786 return Stmt->Error.ReturnValue;
787 }
788 /* }}} */
789
790 /* {{{ MADB_ExecutePositionedUpdate */
791 SQLRETURN MADB_ExecutePositionedUpdate(MADB_Stmt *Stmt, BOOL ExecDirect)
792 {
793 SQLSMALLINT j;
794 SQLRETURN ret;
795 MADB_DynArray DynData;
796 MADB_Stmt *SaveCursor;
797
798 char *p;
799
800 MADB_CLEAR_ERROR(&Stmt->Error);
801 if (!Stmt->PositionedCursor->result)
802 {
803 MADB_SetError(&Stmt->Error, MADB_ERR_34000, "Cursor has no result set or is not open", 0);
804 return Stmt->Error.ReturnValue;
805 }
806 MADB_StmtDataSeek(Stmt->PositionedCursor, Stmt->PositionedCursor->Cursor.Position);
807 Stmt->Methods->RefreshRowPtrs(Stmt->PositionedCursor);
808
809 memcpy(&Stmt->Apd->Header, &Stmt->Ard->Header, sizeof(MADB_Header));
810
811 Stmt->AffectedRows= 0;
812
813 MADB_InitDynamicArray(&DynData, sizeof(char *), 8, 8);
814
815 for (j= 1; j < MADB_POS_COMM_IDX_FIELD_COUNT(Stmt) + 1; ++j)
816 {
817 SQLLEN Length;
818 MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Stmt->PositionedCursor->Ard, j, MADB_DESC_READ);
819 Length= Rec->OctetLength;
820 /* if (Rec->inUse)
821 MA_SQLBindParameter(Stmt, j+1, SQL_PARAM_INPUT, Rec->ConciseType, Rec->Type, Rec->DisplaySize, Rec->Scale, Rec->DataPtr, Length, Rec->OctetLengthPtr);
822 else */
823 {
824 Stmt->Methods->GetData(Stmt->PositionedCursor, j, SQL_CHAR, NULL, 0, &Length, TRUE);
825 p= (char *)MADB_CALLOC(Length + 2);
826 MADB_InsertDynamic(&DynData, (char *)&p);
827 Stmt->Methods->GetData(Stmt->PositionedCursor, j, SQL_CHAR, p, Length + 1, NULL, TRUE);
828 Stmt->Methods->BindParam(Stmt, j + (Stmt->ParamCount - MADB_POS_COMM_IDX_FIELD_COUNT(Stmt)), SQL_PARAM_INPUT, SQL_CHAR, SQL_CHAR, 0, 0, p, Length, NULL);
829
830 }
831 }
832
833 SaveCursor= Stmt->PositionedCursor;
834 Stmt->PositionedCursor= NULL;
835
836 ret= Stmt->Methods->Execute(Stmt, ExecDirect);
837
838 Stmt->PositionedCursor= SaveCursor;
839
840 /* For the case of direct execution we need to restore number of parameters bound by application, for the case when application
841 re-uses handle with same parameters for another query. Otherwise we won't know that number (of application's parameters) */
842 if (ExecDirect)
843 {
844 Stmt->Apd->Header.Count-= MADB_POS_COMM_IDX_FIELD_COUNT(Stmt);
845 }
846
847 for (j=0; j < (int)DynData.elements; j++)
848 {
849 MADB_GetDynamic(&DynData, (char *)&p, j);
850 MADB_FREE(p);
851 }
852 MADB_DeleteDynamic(&DynData);
853
854 if (Stmt->PositionedCursor->Options.CursorType == SQL_CURSOR_DYNAMIC &&
855 (ret == SQL_SUCCESS || ret == SQL_SUCCESS_WITH_INFO))
856 {
857 SQLRETURN rc;
858 rc= Stmt->Methods->RefreshDynamicCursor(Stmt->PositionedCursor);
859 if (!SQL_SUCCEEDED(rc))
860 {
861 MADB_CopyError(&Stmt->Error, &Stmt->PositionedCursor->Error);
862 return Stmt->Error.ReturnValue;
863 }
864 if (Stmt->Query.QueryType == SQL_DELETE)
865 MADB_STMT_RESET_CURSOR(Stmt->PositionedCursor);
866
867 }
868 //MADB_FREE(DataPtr);
869 return ret;
870 }
871 /* }}} */
872
873 /* {{{ MADB_GetOutParams */
874 SQLRETURN MADB_GetOutParams(MADB_Stmt *Stmt, int CurrentOffset)
875 {
876 MYSQL_BIND *Bind;
877 unsigned int i=0, ParameterNr= 0;
878
879 /* Since Outparams are only one row, we use store result */
880 if (mysql_stmt_store_result(Stmt->stmt))
881 {
882 return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt);
883 }
884
885 Bind= (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * mysql_stmt_field_count(Stmt->stmt));
886
887 for (i=0; i < (unsigned int)Stmt->ParamCount && ParameterNr < mysql_stmt_field_count(Stmt->stmt); i++)
888 {
889 MADB_DescRecord *IpdRecord, *ApdRecord;
890 if ((IpdRecord= MADB_DescGetInternalRecord(Stmt->Ipd, i, MADB_DESC_READ))!= NULL)
891 {
892 if (IpdRecord->ParameterType == SQL_PARAM_INPUT_OUTPUT ||
893 IpdRecord->ParameterType == SQL_PARAM_OUTPUT)
894 {
895 ApdRecord= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ);
896 Bind[ParameterNr].buffer= GetBindOffset(Stmt->Apd, ApdRecord, ApdRecord->DataPtr, CurrentOffset, ApdRecord->OctetLength);
897 if (ApdRecord->OctetLengthPtr)
898 {
899 Bind[ParameterNr].length= (unsigned long *)GetBindOffset(Stmt->Apd, ApdRecord, ApdRecord->OctetLengthPtr,
900 CurrentOffset, sizeof(SQLLEN));
901 }
902 Bind[ParameterNr].buffer_length= (unsigned long)ApdRecord->OctetLength;
903 Bind[ParameterNr].buffer_type= Stmt->stmt->params[i].buffer_type;
904 ParameterNr++;
905 }
906 }
907 }
908 mysql_stmt_bind_result(Stmt->stmt, Bind);
909 mysql_stmt_fetch(Stmt->stmt);
910
911 mysql_stmt_data_seek(Stmt->stmt, 0);
912 MADB_FREE(Bind);
913
914 return SQL_SUCCESS;
915 }
916 /* }}} */
917
918 /* {{{ ResetInternalLength */
919 static void ResetInternalLength(MADB_Stmt *Stmt, unsigned int ParamOffset)
920 {
921 unsigned int i;
922 MADB_DescRecord *ApdRecord;
923
924 for (i= ParamOffset; i < ParamOffset + Stmt->ParamCount; ++i)
925 {
926 if ((ApdRecord= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ)))
927 {
928 ApdRecord->InternalLength= 0;
929 }
930 }
931 }
932 /* }}} */
933
934 /* {{{ MADB_DoExecute */
935 /* Actually executing on the server, doing required actions with C API, and processing execution result */
936 SQLRETURN MADB_DoExecute(MADB_Stmt *Stmt, BOOL ExecDirect)
937 {
938 SQLRETURN ret= SQL_SUCCESS;
939
940 /**************************** mysql_stmt_bind_param **********************************/
941 if (ExecDirect)
942 {
943 mysql_stmt_attr_set(Stmt->stmt, STMT_ATTR_PREBIND_PARAMS, &Stmt->ParamCount);
944 }
945
946 mysql_stmt_attr_set(Stmt->stmt, STMT_ATTR_ARRAY_SIZE, (void*)&Stmt->Bulk.ArraySize);
947
948 if (Stmt->ParamCount)
949 {
950 mysql_stmt_bind_param(Stmt->stmt, Stmt->params);
951 }
952 ret= SQL_SUCCESS;
953
954 /**************************** mysql_stmt_execute *************************************/
955
956 MDBUG_C_PRINT(Stmt->Connection, ExecDirect ? "mariadb_stmt_execute_direct(%0x,%s)"
957 : "mariadb_stmt_execute(%0x)(%s)", Stmt->stmt, STMT_STRING(Stmt));
958
959 if ((ExecDirect && mariadb_stmt_execute_direct(Stmt->stmt, STMT_STRING(Stmt), strlen(STMT_STRING(Stmt))))
960 || (!ExecDirect && mysql_stmt_execute(Stmt->stmt)))
961 {
962 ret= MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
963 MDBUG_C_PRINT(Stmt->Connection, "mysql_stmt_execute:ERROR%s", "");
964 }
965 else
966 {
967 Stmt->State= MADB_SS_EXECUTED;
968
969 if (Stmt->stmt->mysql->server_status & SERVER_PS_OUT_PARAMS)
970 {
971 Stmt->State= MADB_SS_OUTPARAMSFETCHED;
972 ret= Stmt->Methods->GetOutParams(Stmt, 0);
973 }
974 }
975 return ret;
976 }
977 /* }}} */
978
979 void MADB_SetStatusArray(MADB_Stmt *Stmt, SQLUSMALLINT Status)
980 {
981 if (Stmt->Ipd->Header.ArrayStatusPtr != NULL)
982 {
983 memset(Stmt->Ipd->Header.ArrayStatusPtr, 0x00ff & Status, Stmt->Apd->Header.ArraySize*sizeof(SQLUSMALLINT));
984 if (Stmt->Apd->Header.ArrayStatusPtr != NULL)
985 {
986 unsigned int i;
987 for (i= 0; i < Stmt->Apd->Header.ArraySize; ++i)
988 {
989 if (Stmt->Apd->Header.ArrayStatusPtr[i] == SQL_PARAM_IGNORE)
990 {
991 Stmt->Ipd->Header.ArrayStatusPtr[i]= SQL_PARAM_UNUSED;
992 }
993 }
994 }
995 }
996 }
997 /* {{{ MADB_StmtExecute */
998 SQLRETURN MADB_StmtExecute(MADB_Stmt *Stmt, BOOL ExecDirect)
999 {
1000 unsigned int i;
1001 MYSQL_RES *DefaultResult= NULL;
1002 SQLRETURN ret= SQL_SUCCESS;
1003 unsigned int ErrorCount= 0;
1004 unsigned int StatementNr;
1005 unsigned int ParamOffset= 0; /* for multi statements */
1006 /* Will use it for STMT_ATTR_ARRAY_SIZE and as indicator if we are deploying MariaDB bulk insert feature */
1007 unsigned int MariadbArrSize= MADB_BulkInsertPossible(Stmt) != FALSE ? (unsigned int)Stmt->Apd->Header.ArraySize : 0;
1008 SQLULEN j, Start= 0;
1009 /* For multistatement direct execution */
1010 char *CurQuery= Stmt->Query.RefinedText, *QueriesEnd= Stmt->Query.RefinedText + Stmt->Query.RefinedLength;
1011
1012 MDBUG_C_PRINT(Stmt->Connection, "%sMADB_StmtExecute", "\t->");
1013
1014 MADB_CLEAR_ERROR(&Stmt->Error);
1015
1016 if (Stmt->State == MADB_SS_EMULATED)
1017 {
1018 return MADB_ExecuteQuery(Stmt, STMT_STRING(Stmt), (SQLINTEGER)strlen(STMT_STRING(Stmt)));
1019 }
1020
1021 if (MADB_POSITIONED_COMMAND(Stmt))
1022 {
1023 return MADB_ExecutePositionedUpdate(Stmt, ExecDirect);
1024 }
1025
1026 /* Stmt->params was allocated during prepare, but could be cleared
1027 by SQLResetStmt. In latter case we need to allocate it again */
1028 if (!Stmt->params &&
1029 !(Stmt->params = (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * MADB_STMT_PARAM_COUNT(Stmt))))
1030 {
1031 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
1032 return Stmt->Error.ReturnValue;
1033 }
1034
1035 /* Normally this check is done by a DM. We are doing that too, keeping in mind direct linking.
1036 If exectution routine called from the SQLParamData, DataExecutionType has been reset */
1037 if (Stmt->Status == SQL_NEED_DATA && !DAE_DONE(Stmt))
1038 {
1039 MADB_SetError(&Stmt->Error, MADB_ERR_HY010, NULL, 0);
1040 }
1041
1042 LOCK_MARIADB(Stmt->Connection);
1043 Stmt->AffectedRows= 0;
1044 Start+= Stmt->ArrayOffset;
1045
1046 if (Stmt->Ipd->Header.RowsProcessedPtr)
1047 {
1048 *Stmt->Ipd->Header.RowsProcessedPtr= 0;
1049 }
1050
1051 if (MariadbArrSize > 1)
1052 {
1053 if (MADB_DOING_BULK_OPER(Stmt))
1054 {
1055 //MADB_CleanBulkOperationData(Stmt);
1056 }
1057 Stmt->Bulk.ArraySize= MariadbArrSize;
1058 Stmt->Bulk.HasRowsToSkip= 0;
1059 }
1060
1061 for (StatementNr= 0; StatementNr < STMT_COUNT(Stmt->Query); ++StatementNr)
1062 {
1063 if (QUERY_IS_MULTISTMT(Stmt->Query))
1064 {
1065 if (Stmt->MultiStmts && Stmt->MultiStmts[StatementNr] != NULL)
1066 {
1067 Stmt->stmt= Stmt->MultiStmts[StatementNr];
1068 }
1069 else
1070 {
1071 /* We have direct execution, since otherwise it'd already prepared, and thus Stmt->MultiStmts would be set */
1072 if (CurQuery >= QueriesEnd)
1073 {
1074 /* Something went wrong(with parsing). But we've got here, and everything worked. Giving it chance to fail later.
1075 This shouldn't really happen */
1076 MDBUG_C_PRINT(Stmt->Connection, "Got past end of query direct-executing %s on stmt #%u", Stmt->Query.RefinedText, StatementNr);
1077 continue;
1078 }
1079 if (StatementNr > 0)
1080 {
1081 Stmt->stmt= MADB_NewStmtHandle(Stmt);
1082 }
1083 else
1084 {
1085 Stmt->MultiStmts= (MYSQL_STMT **)MADB_CALLOC(sizeof(MYSQL_STMT) * STMT_COUNT(Stmt->Query));
1086 }
1087
1088 Stmt->MultiStmts[StatementNr]= Stmt->stmt;
1089
1090 if (mysql_stmt_prepare(Stmt->stmt, CurQuery, (unsigned long)strlen(CurQuery)))
1091 {
1092 return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
1093 }
1094 CurQuery+= strlen(CurQuery) + 1;
1095 }
1096
1097 Stmt->RebindParams= TRUE;
1098
1099 if (Stmt->ParamCount != mysql_stmt_param_count(Stmt->stmt))
1100 {
1101 Stmt->ParamCount= (SQLSMALLINT)mysql_stmt_param_count(Stmt->stmt);
1102 Stmt->params= (MYSQL_BIND*)MADB_REALLOC(Stmt->params, sizeof(MYSQL_BIND) * MADB_STMT_PARAM_COUNT(Stmt));
1103 }
1104
1105 memset(Stmt->params, 0, sizeof(MYSQL_BIND) * MADB_STMT_PARAM_COUNT(Stmt));
1106
1107 }
1108
1109 if (MADB_DOING_BULK_OPER(Stmt))
1110 {
1111 if (!SQL_SUCCEEDED(MADB_ExecuteBulk(Stmt, ParamOffset)))
1112 {
1113 /* Doing just the same thing as we would do in general case */
1114 MADB_CleanBulkOperData(Stmt, ParamOffset);
1115 ErrorCount= (unsigned int)Stmt->Apd->Header.ArraySize;
1116 MADB_SetStatusArray(Stmt, SQL_PARAM_DIAG_UNAVAILABLE);
1117 goto end;
1118 }
1119 else if (!mysql_stmt_field_count(Stmt->stmt) && !Stmt->MultiStmts)
1120 {
1121 Stmt->AffectedRows+= mysql_stmt_affected_rows(Stmt->stmt);
1122 }
1123 /* Suboptimal, but more reliable and simple */
1124 MADB_CleanBulkOperData(Stmt, ParamOffset);
1125 Stmt->ArrayOffset+= (int)Stmt->Apd->Header.ArraySize;
1126 if (Stmt->Ipd->Header.RowsProcessedPtr)
1127 {
1128 *Stmt->Ipd->Header.RowsProcessedPtr= *Stmt->Ipd->Header.RowsProcessedPtr + Stmt->Apd->Header.ArraySize;
1129 }
1130 MADB_SetStatusArray(Stmt, SQL_PARAM_SUCCESS);
1131 }
1132 else
1133 {
1134 /* Convert and bind parameters */
1135 for (j= Start; j < Start + Stmt->Apd->Header.ArraySize; ++j)
1136 {
1137 /* "... In an IPD, this SQLUINTEGER * header field points to a buffer containing the number
1138 of sets of parameters that have been processed, including error sets. ..." */
1139 if (Stmt->Ipd->Header.RowsProcessedPtr)
1140 {
1141 *Stmt->Ipd->Header.RowsProcessedPtr= *Stmt->Ipd->Header.RowsProcessedPtr + 1;
1142 }
1143
1144 if (Stmt->Apd->Header.ArrayStatusPtr &&
1145 Stmt->Apd->Header.ArrayStatusPtr[j-Start] == SQL_PARAM_IGNORE)
1146 {
1147 if (Stmt->Ipd->Header.ArrayStatusPtr)
1148 {
1149 Stmt->Ipd->Header.ArrayStatusPtr[j-Start]= SQL_PARAM_UNUSED;
1150 }
1151 continue;
1152 }
1153
1154 for (i= ParamOffset; i < ParamOffset + MADB_STMT_PARAM_COUNT(Stmt); ++i)
1155 {
1156 MADB_DescRecord *ApdRecord, *IpdRecord;
1157
1158 if ((ApdRecord= MADB_DescGetInternalRecord(Stmt->Apd, i, MADB_DESC_READ)) &&
1159 (IpdRecord= MADB_DescGetInternalRecord(Stmt->Ipd, i, MADB_DESC_READ)))
1160 {
1161 /* check if parameter was bound */
1162 if (!ApdRecord->inUse)
1163 {
1164 ret= MADB_SetError(&Stmt->Error, MADB_ERR_07002, NULL, 0);
1165 goto end;
1166 }
1167
1168 if (MADB_ConversionSupported(ApdRecord, IpdRecord) == FALSE)
1169 {
1170 ret= MADB_SetError(&Stmt->Error, MADB_ERR_07006, NULL, 0);
1171 goto end;
1172 }
1173
1174 Stmt->params[i-ParamOffset].length= NULL;
1175
1176 ret= MADB_C2SQL(Stmt, ApdRecord, IpdRecord, j - Start, &Stmt->params[i-ParamOffset]);
1177 if (!SQL_SUCCEEDED(ret))
1178 {
1179 goto end;
1180 }
1181 }
1182 } /* End of for() on parameters */
1183
1184 if (Stmt->RebindParams && MADB_STMT_PARAM_COUNT(Stmt))
1185 {
1186 Stmt->stmt->bind_param_done= 1;
1187 Stmt->RebindParams= FALSE;
1188 }
1189
1190 ret= MADB_DoExecute(Stmt, ExecDirect);
1191
1192 if (!SQL_SUCCEEDED(ret))
1193 {
1194 ++ErrorCount;
1195 }
1196 /* We need to unset InternalLength, i.e. reset dae length counters for next stmt.
1197 However that length is not used anywhere, and is not clear what is it needed for */
1198 ResetInternalLength(Stmt, ParamOffset);
1199
1200 if (Stmt->Ipd->Header.ArrayStatusPtr)
1201 {
1202 Stmt->Ipd->Header.ArrayStatusPtr[j-Start]= SQL_SUCCEEDED(ret) ? SQL_PARAM_SUCCESS :
1203 (j == Stmt->Apd->Header.ArraySize - 1) ? SQL_PARAM_ERROR : SQL_PARAM_DIAG_UNAVAILABLE;
1204 }
1205 if (!mysql_stmt_field_count(Stmt->stmt) && SQL_SUCCEEDED(ret) && !Stmt->MultiStmts)
1206 {
1207 Stmt->AffectedRows+= mysql_stmt_affected_rows(Stmt->stmt);
1208 }
1209 ++Stmt->ArrayOffset;
1210 if (!SQL_SUCCEEDED(ret) && j == Start + Stmt->Apd->Header.ArraySize)
1211 {
1212 goto end;
1213 }
1214 } /* End of for() thru paramsets(parameters array) */
1215 } /* End of if (bulk/not bulk) execution */
1216
1217 if (QUERY_IS_MULTISTMT(Stmt->Query))
1218 {
1219 /* If we optimize memory allocation, then we will need to free bulk operation data here(among other places) */
1220 /* MADB_CleanBulkOperData(Stmt, ParamOffset); */
1221 ParamOffset+= MADB_STMT_PARAM_COUNT(Stmt);
1222
1223 if (mysql_stmt_field_count(Stmt->stmt))
1224 {
1225 mysql_stmt_store_result(Stmt->stmt);
1226 }
1227 }
1228 } /* End of for() on statements(Multistatmt) */
1229
1230 /* All rows processed, so we can unset ArrayOffset */
1231 Stmt->ArrayOffset= 0;
1232
1233 if (Stmt->MultiStmts)
1234 {
1235 Stmt->MultiStmtNr= 0;
1236 MADB_InstallStmt(Stmt, Stmt->MultiStmts[Stmt->MultiStmtNr]);
1237 }
1238 else if (mysql_stmt_field_count(Stmt->stmt) > 0)
1239 {
1240 MADB_StmtResetResultStructures(Stmt);
1241
1242 /* Todo: for SQL_CURSOR_FORWARD_ONLY we should use cursor and prefetch rows */
1243 /*************************** mysql_stmt_store_result ******************************/
1244 /*If we did OUT params already, we should not store */
1245 if (Stmt->State == MADB_SS_EXECUTED && mysql_stmt_store_result(Stmt->stmt) != 0)
1246 {
1247 UNLOCK_MARIADB(Stmt->Connection);
1248 if (DefaultResult)
1249 {
1250 mysql_free_result(DefaultResult);
1251 }
1252
1253 return MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
1254 }
1255
1256 /* I don't think we can reliably establish the fact that we do not need to re-fetch the metadata, thus we are re-fetching always
1257 The fact that we have resultset has been established above in "if" condition(fields count is > 0) */
1258 MADB_DescSetIrdMetadata(Stmt, mysql_fetch_fields(FetchMetadata(Stmt)), mysql_stmt_field_count(Stmt->stmt));
1259
1260 Stmt->AffectedRows= -1;
1261 }
1262 end:
1263 UNLOCK_MARIADB(Stmt->Connection);
1264 Stmt->LastRowFetched= 0;
1265
1266 if (DefaultResult)
1267 mysql_free_result(DefaultResult);
1268
1269 if (ErrorCount)
1270 {
1271 if (ErrorCount < Stmt->Apd->Header.ArraySize)
1272 ret= SQL_SUCCESS_WITH_INFO;
1273 else
1274 ret= SQL_ERROR;
1275 }
1276
1277 return ret;
1278 }
1279 /* }}} */
1280
1281 /* {{{ MADB_StmtBindCol */
1282 SQLRETURN MADB_StmtBindCol(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
1283 SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind)
1284 {
1285 MADB_Desc *Ard= Stmt->Ard;
1286 MADB_DescRecord *Record;
1287
1288 if ((ColumnNumber < 1 && Stmt->Options.UseBookmarks == SQL_UB_OFF) ||
1289 (mysql_stmt_field_count(Stmt->stmt) &&
1290 Stmt->stmt->state > MYSQL_STMT_PREPARED &&
1291 ColumnNumber > mysql_stmt_field_count(Stmt->stmt)))
1292 {
1293 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
1294 return SQL_ERROR;
1295 }
1296
1297 /* Bookmark */
1298 if (ColumnNumber == 0)
1299 {
1300 if (TargetType == SQL_C_BOOKMARK || TargetType == SQL_C_VARBOOKMARK)
1301 {
1302 Stmt->Options.BookmarkPtr= TargetValuePtr;
1303 Stmt->Options.BookmarkLength = BufferLength;
1304 Stmt->Options.BookmarkType= TargetType;
1305 return SQL_SUCCESS;
1306 }
1307 MADB_SetError(&Stmt->Error, MADB_ERR_07006, NULL, 0);
1308 return Stmt->Error.ReturnValue;
1309 }
1310
1311 if (!(Record= MADB_DescGetInternalRecord(Ard, ColumnNumber - 1, MADB_DESC_WRITE)))
1312 {
1313 MADB_CopyError(&Stmt->Error, &Ard->Error);
1314 return Stmt->Error.ReturnValue;
1315 }
1316
1317 /* check if we need to unbind and delete a record */
1318 if (!TargetValuePtr && !StrLen_or_Ind)
1319 {
1320 int i;
1321 Record->inUse= 0;
1322 /* Update counter */
1323 for (i= Ard->Records.elements; i > 0; i--)
1324 {
1325 MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Ard, i-1, MADB_DESC_READ);
1326 if (Rec && Rec->inUse)
1327 {
1328 Ard->Header.Count= i;
1329 return SQL_SUCCESS;
1330 }
1331 }
1332 Ard->Header.Count= 0;
1333 return SQL_SUCCESS;
1334 }
1335
1336 if (!SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_TYPE, (SQLPOINTER)(SQLLEN)TargetType, SQL_IS_SMALLINT, 0)) ||
1337 !SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_OCTET_LENGTH_PTR, (SQLPOINTER)StrLen_or_Ind, SQL_IS_POINTER, 0)) ||
1338 !SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_INDICATOR_PTR, (SQLPOINTER)StrLen_or_Ind, SQL_IS_POINTER, 0)) ||
1339 !SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_OCTET_LENGTH, (SQLPOINTER)MADB_GetTypeLength(TargetType, BufferLength), SQL_IS_INTEGER, 0)) ||
1340 !SQL_SUCCEEDED(MADB_DescSetField(Ard, ColumnNumber, SQL_DESC_DATA_PTR, TargetValuePtr, SQL_IS_POINTER, 0)))
1341 {
1342 MADB_CopyError(&Stmt->Error, &Ard->Error);
1343 return Stmt->Error.ReturnValue;
1344 }
1345
1346 return SQL_SUCCESS;
1347 }
1348 /* }}} */
1349
1350 /* {{{ MADB_StmtBindParam */
1351 SQLRETURN MADB_StmtBindParam(MADB_Stmt *Stmt, SQLUSMALLINT ParameterNumber,
1352 SQLSMALLINT InputOutputType, SQLSMALLINT ValueType,
1353 SQLSMALLINT ParameterType, SQLULEN ColumnSize,
1354 SQLSMALLINT DecimalDigits, SQLPOINTER ParameterValuePtr,
1355 SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr)
1356 {
1357 MADB_Desc *Apd= Stmt->Apd,
1358 *Ipd= Stmt->Ipd;
1359 MADB_DescRecord *ApdRecord, *IpdRecord;
1360 SQLRETURN ret= SQL_SUCCESS;
1361
1362 MADB_CLEAR_ERROR(&Stmt->Error);
1363 if (!(ApdRecord= MADB_DescGetInternalRecord(Apd, ParameterNumber - 1, MADB_DESC_WRITE)))
1364 {
1365 MADB_CopyError(&Stmt->Error, &Apd->Error);
1366 return Stmt->Error.ReturnValue;
1367 }
1368 if (!(IpdRecord= MADB_DescGetInternalRecord(Ipd, ParameterNumber - 1, MADB_DESC_WRITE)))
1369 {
1370 MADB_CopyError(&Stmt->Error, &Ipd->Error);
1371 return Stmt->Error.ReturnValue;
1372 }
1373
1374 /* Map to the correspoinding type */
1375 if (ValueType == SQL_C_DEFAULT)
1376 {
1377 ValueType= MADB_GetDefaultType(ParameterType);
1378 }
1379
1380 if (!(SQL_SUCCEEDED(MADB_DescSetField(Apd, ParameterNumber, SQL_DESC_CONCISE_TYPE, (SQLPOINTER)(SQLLEN)ValueType, SQL_IS_SMALLINT, 0))) ||
1381 !(SQL_SUCCEEDED(MADB_DescSetField(Apd, ParameterNumber, SQL_DESC_OCTET_LENGTH_PTR, (SQLPOINTER)StrLen_or_IndPtr, SQL_IS_POINTER, 0))) ||
1382 !(SQL_SUCCEEDED(MADB_DescSetField(Apd, ParameterNumber, SQL_DESC_OCTET_LENGTH, (SQLPOINTER)MADB_GetTypeLength(ValueType, BufferLength), SQL_IS_INTEGER, 0))) ||
1383 !(SQL_SUCCEEDED(MADB_DescSetField(Apd, ParameterNumber, SQL_DESC_INDICATOR_PTR, (SQLPOINTER)StrLen_or_IndPtr, SQL_IS_POINTER, 0))) ||
1384 !(SQL_SUCCEEDED(MADB_DescSetField(Apd, ParameterNumber, SQL_DESC_DATA_PTR, ParameterValuePtr, SQL_IS_POINTER, 0))))
1385 {
1386 MADB_CopyError(&Stmt->Error, &Apd->Error);
1387 return Stmt->Error.ReturnValue;
1388 }
1389
1390 if (!(SQL_SUCCEEDED(MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_CONCISE_TYPE, (SQLPOINTER)(SQLLEN)ParameterType, SQL_IS_SMALLINT, 0))) ||
1391 !(SQL_SUCCEEDED(MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_PARAMETER_TYPE, (SQLPOINTER)(SQLLEN)InputOutputType, SQL_IS_SMALLINT, 0))))
1392 {
1393 MADB_CopyError(&Stmt->Error, &Ipd->Error);
1394 return Stmt->Error.ReturnValue;
1395 }
1396
1397 switch(ParameterType) {
1398 case SQL_BINARY:
1399 case SQL_VARBINARY:
1400 case SQL_LONGVARBINARY:
1401 case SQL_CHAR:
1402 case SQL_VARCHAR:
1403 case SQL_LONGVARCHAR:
1404 case SQL_WCHAR:
1405 case SQL_WLONGVARCHAR:
1406 case SQL_WVARCHAR:
1407 ret= MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_LENGTH, (SQLPOINTER)ColumnSize, SQL_IS_INTEGER, 0);
1408 break;
1409 case SQL_FLOAT:
1410 case SQL_REAL:
1411 case SQL_DOUBLE:
1412 ret= MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_PRECISION, (SQLPOINTER)ColumnSize, SQL_IS_INTEGER, 0);
1413 break;
1414 case SQL_DECIMAL:
1415 case SQL_NUMERIC:
1416 ret= MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_PRECISION, (SQLPOINTER)ColumnSize, SQL_IS_SMALLINT, 0);
1417 if (SQL_SUCCEEDED(ret))
1418 ret= MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_SCALE, (SQLPOINTER)(SQLLEN)DecimalDigits, SQL_IS_SMALLINT, 0);
1419 break;
1420 case SQL_INTERVAL_MINUTE_TO_SECOND:
1421 case SQL_INTERVAL_HOUR_TO_SECOND:
1422 case SQL_INTERVAL_DAY_TO_SECOND:
1423 case SQL_INTERVAL_SECOND:
1424 case SQL_TYPE_TIMESTAMP:
1425 case SQL_TYPE_TIME:
1426 ret= MADB_DescSetField(Ipd, ParameterNumber, SQL_DESC_PRECISION, (SQLPOINTER)(SQLLEN)DecimalDigits, SQL_IS_SMALLINT, 0);
1427 break;
1428 }
1429
1430 if(!SQL_SUCCEEDED(ret))
1431 MADB_CopyError(&Stmt->Error, &Ipd->Error);
1432 Stmt->RebindParams= TRUE;
1433
1434 return ret;
1435 }
1436 /* }}} */
1437
1438 void MADB_InitStatusPtr(SQLUSMALLINT *Ptr, SQLULEN Size, SQLSMALLINT InitialValue)
1439 {
1440 SQLULEN i;
1441
1442 for (i=0; i < Size; i++)
1443 Ptr[i]= InitialValue;
1444 }
1445
1446 /* Not used for now, but leaving it so far here - it may be useful */
1447 /* BOOL MADB_NumericBufferType(SQLSMALLINT BufferType)
1448 {
1449 switch (BufferType)
1450 {
1451 case SQL_C_TINYINT:
1452 case SQL_C_UTINYINT:
1453 case SQL_C_STINYINT:
1454 case SQL_C_SHORT:
1455 case SQL_C_SSHORT:
1456 case SQL_C_USHORT:
1457 case SQL_C_FLOAT:
1458 case SQL_C_LONG:
1459 case SQL_C_ULONG:
1460 case SQL_C_SLONG:
1461 case SQL_C_DOUBLE:
1462 return TRUE;
1463 default:
1464 return FALSE;
1465 }
1466 }*/
1467
1468 /* {{{ MADB_BinaryFieldType */
1469 BOOL MADB_BinaryFieldType(SQLSMALLINT FieldType)
1470 {
1471 return FieldType == SQL_BINARY || FieldType == SQL_BIT;
1472 }
1473 /* }}} */
1474
1475 /* {{{ MADB_PrepareBind
1476 Filling bind structures in */
1477 SQLRETURN MADB_PrepareBind(MADB_Stmt *Stmt, int RowNumber)
1478 {
1479 MADB_DescRecord *IrdRec, *ArdRec;
1480 int i;
1481 void *DataPtr= NULL;
1482
1483 for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); ++i)
1484 {
1485 ArdRec= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ);
1486 if (ArdRec == NULL || !ArdRec->inUse)
1487 {
1488 Stmt->result[i].flags|= MADB_BIND_DUMMY;
1489 continue;
1490 }
1491
1492 DataPtr= (SQLLEN *)GetBindOffset(Stmt->Ard, ArdRec, ArdRec->DataPtr, RowNumber, ArdRec->OctetLength);
1493
1494 MADB_FREE(ArdRec->InternalBuffer);
1495 if (!DataPtr)
1496 {
1497 Stmt->result[i].flags|= MADB_BIND_DUMMY;
1498 continue;
1499 }
1500 else
1501 {
1502 Stmt->result[i].flags&= ~MADB_BIND_DUMMY;
1503 }
1504
1505 IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, i, MADB_DESC_READ);
1506 /* assert(IrdRec != NULL) */
1507
1508 /* We can't use application's buffer directly, as it has/can have different size, than C/C needs */
1509 Stmt->result[i].length= &Stmt->result[i].length_value;
1510
1511 switch(ArdRec->ConciseType) {
1512 case SQL_C_WCHAR:
1513 /* In worst case for 2 bytes of UTF16 in result, we need 3 bytes of utf8.
1514 For ASCII we need 2 times less(for 2 bytes of UTF16 - 1 byte UTF8,
1515 in other cases we need same 2 of 4 bytes. */
1516 ArdRec->InternalBuffer= (char *)MADB_CALLOC((size_t)((ArdRec->OctetLength)*1.5));
1517 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1518 Stmt->result[i].buffer_length= (unsigned long)(ArdRec->OctetLength*1.5);
1519 Stmt->result[i].buffer_type= MYSQL_TYPE_STRING;
1520 break;
1521 case SQL_C_CHAR:
1522 Stmt->result[i].buffer= DataPtr;
1523 Stmt->result[i].buffer_length= (unsigned long)ArdRec->OctetLength;
1524 Stmt->result[i].buffer_type= MYSQL_TYPE_STRING;
1525 break;
1526 case SQL_C_NUMERIC:
1527 MADB_FREE(ArdRec->InternalBuffer);
1528 Stmt->result[i].buffer_length= MADB_DEFAULT_PRECISION + 1/*-*/ + 1/*.*/;
1529 ArdRec->InternalBuffer= (char *)MADB_CALLOC(Stmt->result[i].buffer_length);
1530 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1531
1532 Stmt->result[i].buffer_type= MYSQL_TYPE_STRING;
1533 break;
1534 case SQL_TYPE_TIMESTAMP:
1535 case SQL_TYPE_DATE:
1536 case SQL_TYPE_TIME:
1537 case SQL_C_TIMESTAMP:
1538 case SQL_C_TIME:
1539 case SQL_C_DATE:
1540 MADB_FREE(ArdRec->InternalBuffer);
1541 if (IrdRec->ConciseType == SQL_CHAR || IrdRec->ConciseType == SQL_VARCHAR)
1542 {
1543 ArdRec->InternalBuffer= (char *)MADB_CALLOC(Stmt->stmt->fields[i].max_length + 1);
1544 if (ArdRec->InternalBuffer == NULL)
1545 {
1546 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
1547 }
1548 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1549 Stmt->result[i].buffer_type= MYSQL_TYPE_STRING;
1550 Stmt->result[i].buffer_length= Stmt->stmt->fields[i].max_length + 1;
1551 }
1552 else
1553 {
1554 ArdRec->InternalBuffer= (char *)MADB_CALLOC(sizeof(MYSQL_TIME));
1555 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1556 Stmt->result[i].buffer_length= sizeof(MYSQL_TIME);
1557 Stmt->result[i].buffer_type= MYSQL_TYPE_TIMESTAMP;
1558 }
1559 break;
1560 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
1561 case SQL_C_INTERVAL_HOUR_TO_SECOND:
1562 {
1563 MYSQL_FIELD *Field= mysql_fetch_field_direct(Stmt->metadata, i);
1564 MADB_FREE(ArdRec->InternalBuffer);
1565 if (IrdRec->ConciseType == SQL_CHAR || IrdRec->ConciseType == SQL_VARCHAR)
1566 {
1567 ArdRec->InternalBuffer= (char *)MADB_CALLOC(Stmt->stmt->fields[i].max_length + 1);
1568 if (ArdRec->InternalBuffer == NULL)
1569 {
1570 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
1571 }
1572 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1573 Stmt->result[i].buffer_type= MYSQL_TYPE_STRING;
1574 Stmt->result[i].buffer_length= Stmt->stmt->fields[i].max_length + 1;
1575 }
1576 else
1577 {
1578 ArdRec->InternalBuffer= (char *)MADB_CALLOC(sizeof(MYSQL_TIME));
1579 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1580 Stmt->result[i].buffer_length= sizeof(MYSQL_TIME);
1581 Stmt->result[i].buffer_type= Field && Field->type == MYSQL_TYPE_TIME ? MYSQL_TYPE_TIME : MYSQL_TYPE_TIMESTAMP;
1582 }
1583 }
1584 break;
1585 case SQL_C_TINYINT:
1586 case SQL_C_UTINYINT:
1587 case SQL_C_STINYINT:
1588 case SQL_C_SHORT:
1589 case SQL_C_SSHORT:
1590 case SQL_C_USHORT:
1591 case SQL_C_FLOAT:
1592 case SQL_C_LONG:
1593 case SQL_C_ULONG:
1594 case SQL_C_SLONG:
1595 case SQL_C_DOUBLE:
1596 if (MADB_BinaryFieldType(IrdRec->ConciseType))
1597 {
1598 /* To keep things simple - we will use internal buffer of the column size, and later(in the MADB_FixFetchedValues) will copy (correct part of)
1599 it to the application's buffer taking care of endianness. Perhaps it'd be better just not to support this type of conversion */
1600 MADB_FREE(ArdRec->InternalBuffer);
1601 ArdRec->InternalBuffer= (char *)MADB_CALLOC(IrdRec->OctetLength);
1602 Stmt->result[i].buffer= ArdRec->InternalBuffer;
1603 Stmt->result[i].buffer_length= (unsigned long)IrdRec->OctetLength;
1604 Stmt->result[i].buffer_type= MYSQL_TYPE_BLOB;
1605 break;
1606 }
1607 /* else {we are falling through below} */
1608 default:
1609 if (!MADB_CheckODBCType(ArdRec->ConciseType))
1610 {
1611 return MADB_SetError(&Stmt->Error, MADB_ERR_07006, NULL, 0);
1612 }
1613 Stmt->result[i].buffer_length= (unsigned long)ArdRec->OctetLength;
1614 Stmt->result[i].buffer= DataPtr;
1615 Stmt->result[i].buffer_type= MADB_GetMaDBTypeAndLength(ArdRec->ConciseType,
1616 &Stmt->result[i].is_unsigned,
1617 &Stmt->result[i].buffer_length);
1618 break;
1619 }
1620 }
1621
1622 return SQL_SUCCESS;
1623 }
1624 /* }}} */
1625
1626 /* {{{ LittleEndian */
1627 char LittleEndian()
1628 {
1629 int x= 1;
1630 char *c= (char*)&x;
1631
1632 return *c;
1633 }
1634 /* }}} */
1635
1636 /* {{{ SwitchEndianness */
1637 void SwitchEndianness(char *Src, SQLLEN SrcBytes, char *Dst, SQLLEN DstBytes)
1638 {
1639 /* SrcBytes can only be less or equal DstBytes */
1640 while (SrcBytes--)
1641 {
1642 *Dst++= *(Src + SrcBytes);
1643 }
1644 }
1645 /* }}} */
1646
1647 #define CALC_ALL_FLDS_RC(_agg_rc, _field_rc) if (_field_rc != SQL_SUCCESS && _agg_rc != SQL_ERROR) _agg_rc= _field_rc
1648
1649 /* {{{ MADB_FixFetchedValues
1650 Converting and/or fixing fetched values if needed */
1651 SQLRETURN MADB_FixFetchedValues(MADB_Stmt *Stmt, int RowNumber, MYSQL_ROW_OFFSET SaveCursor)
1652 {
1653 MADB_DescRecord *IrdRec, *ArdRec;
1654 int i;
1655 SQLLEN *IndicatorPtr= NULL, *LengthPtr= NULL, Dummy= 0;
1656 void *DataPtr= NULL;
1657 SQLRETURN rc= SQL_SUCCESS, FieldRc;
1658
1659 for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); ++i)
1660 {
1661 if ((ArdRec= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ)) && ArdRec->inUse)
1662 {
1663 /* set indicator and dataptr */
1664 LengthPtr= (SQLLEN *)GetBindOffset(Stmt->Ard, ArdRec, ArdRec->OctetLengthPtr, RowNumber, sizeof(SQLLEN));
1665 IndicatorPtr= (SQLLEN *)GetBindOffset(Stmt->Ard, ArdRec, ArdRec->IndicatorPtr, RowNumber, sizeof(SQLLEN));
1666 DataPtr= (SQLLEN *)GetBindOffset(Stmt->Ard, ArdRec, ArdRec->DataPtr, RowNumber, ArdRec->OctetLength);
1667
1668 if (LengthPtr == NULL)
1669 {
1670 LengthPtr= &Dummy;
1671 }
1672 /* clear IndicatorPtr */
1673 if (IndicatorPtr != NULL && IndicatorPtr != LengthPtr && *IndicatorPtr < 0)
1674 {
1675 *IndicatorPtr= 0;
1676 }
1677
1678 IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, i, MADB_DESC_READ);
1679 /* assert(IrdRec != NULL) */
1680
1681 if (*Stmt->stmt->bind[i].is_null)
1682 {
1683 if (IndicatorPtr)
1684 {
1685 *IndicatorPtr= SQL_NULL_DATA;
1686 }
1687 else
1688 {
1689 if (SaveCursor)
1690 {
1691 mysql_stmt_row_seek(Stmt->stmt, SaveCursor);
1692 }
1693 rc= MADB_SetError(&Stmt->Error, MADB_ERR_22002, NULL, 0);
1694 continue;
1695 }
1696 }
1697 else
1698 {
1699 switch (ArdRec->ConciseType)
1700 {
1701 case SQL_C_BIT:
1702 {
1703 char *p= (char *)Stmt->result[i].buffer;
1704 if (p)
1705 {
1706 *p= test(*p != '\0');
1707 }
1708 }
1709 break;
1710 case SQL_C_TYPE_TIMESTAMP:
1711 case SQL_C_TYPE_DATE:
1712 case SQL_C_TYPE_TIME:
1713 case SQL_C_TIMESTAMP:
1714 case SQL_C_TIME:
1715 case SQL_C_DATE:
1716 {
1717 MYSQL_TIME tm, *Intermidiate;
1718
1719 if (IrdRec->ConciseType == SQL_CHAR || IrdRec->ConciseType == SQL_VARCHAR)
1720 {
1721 BOOL isTime;
1722
1723 FieldRc= MADB_Str2Ts(ArdRec->InternalBuffer, *Stmt->stmt->bind[i].length, &tm, FALSE, &Stmt->Error, &isTime);
1724 if (SQL_SUCCEEDED(FieldRc))
1725 {
1726 Intermidiate= &tm;
1727 }
1728 else
1729 {
1730 CALC_ALL_FLDS_RC(rc, FieldRc);
1731 break;
1732 }
1733 }
1734 else
1735 {
1736 Intermidiate= (MYSQL_TIME *)ArdRec->InternalBuffer;
1737 }
1738
1739 FieldRc= MADB_CopyMadbTimestamp(Stmt, Intermidiate, DataPtr, LengthPtr, IndicatorPtr, ArdRec->Type, IrdRec->ConciseType);
1740 CALC_ALL_FLDS_RC(rc, FieldRc);
1741 }
1742 break;
1743 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
1744 case SQL_C_INTERVAL_HOUR_TO_SECOND:
1745 {
1746 MYSQL_TIME *tm= (MYSQL_TIME*)ArdRec->InternalBuffer, ForConversion;
1747 SQL_INTERVAL_STRUCT *ts= (SQL_INTERVAL_STRUCT *)DataPtr;
1748
1749 if (IrdRec->ConciseType == SQL_CHAR || IrdRec->ConciseType == SQL_VARCHAR)
1750 {
1751 BOOL isTime;
1752
1753 FieldRc= MADB_Str2Ts(ArdRec->InternalBuffer, *Stmt->stmt->bind[i].length, &ForConversion, FALSE, &Stmt->Error, &isTime);
1754 if (SQL_SUCCEEDED(FieldRc))
1755 {
1756 tm= &ForConversion;
1757 }
1758 else
1759 {
1760 CALC_ALL_FLDS_RC(rc, FieldRc);
1761 break;
1762 }
1763 }
1764
1765 /* If we have ts == NULL we (may) have tm also NULL, since we didn't really bind this column */
1766 if (ts != NULL)
1767 {
1768 if (tm->hour > 99999)
1769 {
1770 FieldRc= MADB_SetError(&Stmt->Error, MADB_ERR_22015, NULL, 0);
1771 CALC_ALL_FLDS_RC(rc, FieldRc);
1772 break;
1773 }
1774
1775 ts->intval.day_second.hour= tm->hour;
1776 ts->intval.day_second.minute= tm->minute;
1777 ts->interval_sign= tm->neg ? SQL_TRUE : SQL_FALSE;
1778
1779 if (ArdRec->Type == SQL_C_INTERVAL_HOUR_TO_MINUTE)
1780 {
1781 ts->intval.day_second.second= 0;
1782 ts->interval_type= SQL_INTERVAL_HOUR_TO_MINUTE;
1783 if (tm->second)
1784 {
1785 FieldRc= MADB_SetError(&Stmt->Error, MADB_ERR_01S07, NULL, 0);
1786 CALC_ALL_FLDS_RC(rc, FieldRc);
1787 break;
1788 }
1789 }
1790 else
1791 {
1792 ts->interval_type= SQL_INTERVAL_HOUR_TO_SECOND;
1793 ts->intval.day_second.second= tm->second;
1794 }
1795 }
1796
1797 *LengthPtr= sizeof(SQL_INTERVAL_STRUCT);
1798 }
1799 break;
1800 case SQL_C_NUMERIC:
1801 {
1802 int rc= 0;
1803 MADB_CLEAR_ERROR(&Stmt->Error);
1804 if (DataPtr != NULL && Stmt->result[i].buffer_length < Stmt->stmt->fields[i].max_length)
1805 {
1806 MADB_SetError(&Stmt->Error, MADB_ERR_22003, NULL, 0);
1807 ArdRec->InternalBuffer[Stmt->result[i].buffer_length - 1]= 0;
1808 return Stmt->Error.ReturnValue;
1809 }
1810
1811 if ((rc= MADB_CharToSQLNumeric(ArdRec->InternalBuffer, Stmt->Ard, ArdRec, NULL, RowNumber)))
1812 {
1813 MADB_SetError(&Stmt->Error, rc, NULL, 0);
1814 }
1815 /* TODO: why is it here individually for Numeric type?! */
1816 if (Stmt->Ard->Header.ArrayStatusPtr)
1817 {
1818 Stmt->Ard->Header.ArrayStatusPtr[RowNumber]= Stmt->Error.ReturnValue;
1819 }
1820 *LengthPtr= sizeof(SQL_NUMERIC_STRUCT);
1821 }
1822 break;
1823 case SQL_C_WCHAR:
1824 {
1825 SQLLEN CharLen= MADB_SetString(&Stmt->Connection->Charset, DataPtr, ArdRec->OctetLength, (char *)Stmt->result[i].buffer,
1826 *Stmt->stmt->bind[i].length, &Stmt->Error);
1827
1828
1829 /*MADB_ConvertAnsi2Unicode(&Stmt->Connection->Charset, (char *)Stmt->result[i].buffer, *Stmt->stmt->bind[i].length,
1830 (SQLWCHAR *)DataPtr, ArdRec->OctetLength, &CharLen, 1, &Stmt->Error);*/
1831 /* Not quite right */
1832 *LengthPtr= CharLen * sizeof(SQLWCHAR);
1833 }
1834 break;
1835
1836 case SQL_C_TINYINT:
1837 case SQL_C_UTINYINT:
1838 case SQL_C_STINYINT:
1839 case SQL_C_SHORT:
1840 case SQL_C_SSHORT:
1841 case SQL_C_USHORT:
1842 case SQL_C_FLOAT:
1843 case SQL_C_LONG:
1844 case SQL_C_ULONG:
1845 case SQL_C_SLONG:
1846 case SQL_C_DOUBLE:
1847 if (MADB_BinaryFieldType(IrdRec->ConciseType))
1848 {
1849 if (DataPtr != NULL)
1850 {
1851 if (Stmt->result[i].buffer_length >= (unsigned long)ArdRec->OctetLength)
1852 {
1853 if (LittleEndian())
1854 {
1855 /* We currently got the bigendian number. If we or littleendian machine, we need to switch bytes */
1856 SwitchEndianness((char*)Stmt->result[i].buffer + Stmt->result[i].buffer_length - ArdRec->OctetLength,
1857 ArdRec->OctetLength,
1858 (char*)DataPtr,
1859 ArdRec->OctetLength);
1860 }
1861 else
1862 {
1863 memcpy(DataPtr, (void*)((char*)Stmt->result[i].buffer + Stmt->result[i].buffer_length - ArdRec->OctetLength), ArdRec->OctetLength);
1864 }
1865 }
1866 else
1867 {
1868 /* We won't write to the whole memory pointed by DataPtr, thus to need to zerofill prior to that */
1869 memset(DataPtr, 0, ArdRec->OctetLength);
1870 if (LittleEndian())
1871 {
1872 SwitchEndianness((char*)Stmt->result[i].buffer,
1873 Stmt->result[i].buffer_length,
1874 (char*)DataPtr,
1875 ArdRec->OctetLength);
1876 }
1877 else
1878 {
1879 memcpy((void*)((char*)DataPtr + ArdRec->OctetLength - Stmt->result[i].buffer_length),
1880 Stmt->result[i].buffer, Stmt->result[i].buffer_length);
1881 }
1882 }
1883 *LengthPtr= *Stmt->stmt->bind[i].length;
1884 }
1885 break;
1886 }
1887 /* else {we are falling through below} */
1888 default:
1889 if (DataPtr != NULL)
1890 {
1891 if (Stmt->Ard->Header.ArraySize > 1)
1892 {
1893 if (Stmt->Ard->Header.BindType)
1894 {
1895 Stmt->result[i].buffer= (char *)Stmt->result[i].buffer + Stmt->Ard->Header.BindType;
1896 }
1897 else
1898 {
1899 Stmt->result[i].buffer = (char *)ArdRec->DataPtr + (RowNumber + 1) * ArdRec->OctetLength;
1900 }
1901 }
1902 *LengthPtr= *Stmt->stmt->bind[i].length;
1903 }
1904 break;
1905 }
1906 }
1907 }
1908 }
1909
1910 return rc;
1911 }
1912 /* }}} */
1913 #undef CALC_ALL_FLDS_RC
1914
1915
1916 SQLUSMALLINT MADB_MapToRowStatus(SQLRETURN rc)
1917 {
1918 switch (rc)
1919 {
1920 case SQL_SUCCESS_WITH_INFO: return SQL_ROW_SUCCESS_WITH_INFO;
1921 case SQL_ERROR: return SQL_ROW_ERROR;
1922 /* Assuming is that status array pre-filled with SQL_ROW_NOROW,
1923 and it never needs to be mapped to */
1924 }
1925
1926 return SQL_ROW_SUCCESS;
1927 }
1928
1929
1930 void ResetDescIntBuffers(MADB_Desc *Desc)
1931 {
1932 MADB_DescRecord *Rec;
1933 SQLSMALLINT i;
1934
1935 for (i= 0; i < Desc->Header.Count; ++i)
1936 {
1937 Rec= MADB_DescGetInternalRecord(Desc, i, MADB_DESC_READ);
1938 if (Rec)
1939 {
1940 MADB_FREE(Rec->InternalBuffer);
1941 }
1942 }
1943 }
1944
1945 /* For first row we just take its result as initial.
1946 For the rest, if all rows SQL_SUCCESS or SQL_ERROR - aggregated result is SQL_SUCCESS or SQL_ERROR, respectively
1947 Otherwise - SQL_SUCCESS_WITH_INFO */
1948 #define CALC_ALL_ROWS_RC(_accumulated_rc, _cur_row_rc, _row_num)\
1949 if (_row_num == 0) _accumulated_rc= _cur_row_rc;\
1950 else if (_cur_row_rc != _accumulated_rc) _accumulated_rc= SQL_SUCCESS_WITH_INFO
1951
1952 /* {{{ MADB_StmtFetch */
1953 SQLRETURN MADB_StmtFetch(MADB_Stmt *Stmt)
1954 {
1955 unsigned int row_num, j, rc;
1956 SQLULEN Rows2Fetch= Stmt->Ard->Header.ArraySize, Processed, *ProcessedPtr= &Processed;
1957 MYSQL_ROW_OFFSET SaveCursor= NULL;
1958 SQLRETURN Result= SQL_SUCCESS, RowResult;
1959
1960 MADB_CLEAR_ERROR(&Stmt->Error);
1961
1962 if (!(MADB_STMT_COLUMN_COUNT(Stmt) > 0))
1963 {
1964 return MADB_SetError(&Stmt->Error, MADB_ERR_24000, NULL, 0);
1965 }
1966
1967 if ((Stmt->Options.UseBookmarks == SQL_UB_VARIABLE && Stmt->Options.BookmarkType == SQL_C_BOOKMARK) ||
1968 (Stmt->Options.UseBookmarks != SQL_UB_VARIABLE && Stmt->Options.BookmarkType == SQL_C_VARBOOKMARK))
1969 {
1970 MADB_SetError(&Stmt->Error, MADB_ERR_07006, NULL, 0);
1971 return Stmt->Error.ReturnValue;
1972 }
1973
1974 /* We don't know if any of the ARD parameter changed, so we need to rebind */
1975 //MADB_FREE(Stmt->result);
1976
1977 /* We don't have much to do if ArraySize == 0 */
1978 if (Stmt->Ard->Header.ArraySize == 0)
1979 {
1980 return SQL_SUCCESS;
1981 }
1982
1983 Stmt->LastRowFetched= 0;
1984
1985 if (Stmt->result == NULL && !(Stmt->result= (MYSQL_BIND *)MADB_CALLOC(sizeof(MYSQL_BIND) * mysql_stmt_field_count(Stmt->stmt))))
1986 {
1987 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
1988 return Stmt->Error.ReturnValue;
1989 }
1990
1991 Rows2Fetch= MADB_RowsToFetch(&Stmt->Cursor, Stmt->Ard->Header.ArraySize, mysql_stmt_num_rows(Stmt->stmt));
1992 if (Rows2Fetch == 0)
1993 {
1994 return SQL_NO_DATA;
1995 }
1996
1997 if (Stmt->Ard->Header.ArrayStatusPtr)
1998 {
1999 MADB_InitStatusPtr(Stmt->Ard->Header.ArrayStatusPtr, Stmt->Ard->Header.ArraySize, SQL_NO_DATA);
2000 }
2001
2002 if (Stmt->Ird->Header.RowsProcessedPtr)
2003 {
2004 ProcessedPtr= Stmt->Ird->Header.RowsProcessedPtr;
2005 }
2006 if (Stmt->Ird->Header.ArrayStatusPtr)
2007 {
2008 MADB_InitStatusPtr(Stmt->Ird->Header.ArrayStatusPtr, Stmt->Ard->Header.ArraySize, SQL_ROW_NOROW);
2009 }
2010
2011 *ProcessedPtr= 0;
2012
2013 /* We need to return to 1st row in the rowset only if there are >1 rows in it. Otherwise we stay on it anyway */
2014 if (Rows2Fetch > 1 && Stmt->Options.CursorType != SQL_CURSOR_FORWARD_ONLY)
2015 {
2016 SaveCursor= mysql_stmt_row_tell(Stmt->stmt);
2017 /* Skipping current row for for reading now, it will be read when the Cursor is returned to it */
2018 MADB_StmtDataSeek(Stmt, Stmt->Cursor.Position > 0 ? Stmt->Cursor.Position + 1 : 1);
2019 }
2020
2021 for (j= 0; j < Rows2Fetch; ++j)
2022 {
2023 RowResult= SQL_SUCCESS;
2024 /* If we need to return to cursor to 1st row in the rowset, we start to read it from 2nd, and 1st row we read the last */
2025 if (SaveCursor != NULL)
2026 {
2027 row_num= j + 1;
2028 if (row_num == Rows2Fetch)
2029 {
2030 row_num= 0;
2031 mysql_stmt_row_seek(Stmt->stmt, SaveCursor);
2032 }
2033 }
2034 else
2035 {
2036 row_num= j;
2037 }
2038 /*************** Setting up BIND structures ********************/
2039 /* Basically, nothing should happen here, but if happens, then it will happen on each row.
2040 Thus it's ok to stop */
2041 RETURN_ERROR_OR_CONTINUE(MADB_PrepareBind(Stmt, row_num));
2042
2043 /************************ Bind! ********************************/
2044 mysql_stmt_bind_result(Stmt->stmt, Stmt->result);
2045
2046 if (Stmt->Options.UseBookmarks && Stmt->Options.BookmarkPtr != NULL)
2047 {
2048 /* TODO: Bookmark can be not only "unsigned long*", but also "unsigned char*". Can be determined by examining Stmt->Options.BookmarkType */
2049 long *p= (long *)Stmt->Options.BookmarkPtr;
2050 p+= row_num * Stmt->Options.BookmarkLength;
2051 *p= (long)Stmt->Cursor.Position;
2052 }
2053 /************************ Fetch! ********************************/
2054 rc= mysql_stmt_fetch(Stmt->stmt);
2055
2056 *ProcessedPtr += 1;
2057
2058 if (Stmt->Cursor.Position < 0)
2059 {
2060 Stmt->Cursor.Position= 0;
2061 }
2062
2063 switch(rc) {
2064 case 1:
2065 RowResult= MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
2066 /* If mysql_stmt_fetch returned error, there is no sense to continue */
2067 if (Stmt->Ird->Header.ArrayStatusPtr)
2068 {
2069 Stmt->Ird->Header.ArrayStatusPtr[row_num]= MADB_MapToRowStatus(RowResult);
2070 }
2071 CALC_ALL_ROWS_RC(Result, RowResult, row_num);
2072 return Result;
2073
2074 case MYSQL_DATA_TRUNCATED:
2075 {
2076 /* We will not report truncation if a dummy buffer was bound */
2077 int col;
2078
2079 for (col= 0; col < MADB_STMT_COLUMN_COUNT(Stmt); ++col)
2080 {
2081 if (Stmt->stmt->bind[col].error && *Stmt->stmt->bind[col].error > 0 &&
2082 !(Stmt->stmt->bind[col].flags & MADB_BIND_DUMMY))
2083 {
2084 MADB_DescRecord *ArdRec= MADB_DescGetInternalRecord(Stmt->Ard, col, MADB_DESC_READ),
2085 *IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, col, MADB_DESC_READ);
2086 /* If (numeric) field value and buffer are of the same size - ignoring truncation.
2087 In some cases specs are not clear enough if certain column signed or not(think of catalog functions for example), and
2088 some apps bind signed buffer where we return unsigdned value. And in general - if application want to fetch unsigned as
2089 signed, or vice versa, why we should prevent that. Plus it seems there is the bug in C/C atm */
2090 if (ArdRec->OctetLength == IrdRec->OctetLength
2091 && MADB_IsIntType(IrdRec->ConciseType) && MADB_IsIntType(ArdRec->ConciseType))
2092 {
2093 continue;
2094 }
2095 /* For numeric types we return either 22003 or 01S07, 01004 for the rest.
2096 if ird type is not fractional - we return 22003. But as a matter of fact, it's possible that we have 22003 if converting
2097 from fractional types */
2098 RowResult= MADB_SetError(&Stmt->Error, ArdRec != NULL && MADB_IsNumericType(ArdRec->ConciseType) ?
2099 (MADB_IsIntType(IrdRec->ConciseType) ? MADB_ERR_22003 : MADB_ERR_01S07) : MADB_ERR_01004, NULL, 0);
2100 /* One found such column is enough */
2101 break;
2102 }
2103 }
2104 break;
2105 }
2106 case MYSQL_NO_DATA:
2107 /* We have already incremented this counter, since there was no more rows, need to decrement */
2108 --*ProcessedPtr;
2109 /* SQL_NO_DATA should be only returned if first fetched row is already beyond end of the resultset */
2110 if (row_num > 0)
2111 {
2112 continue;
2113 }
2114 return SQL_NO_DATA;
2115 } /* End of switch on fetch result */
2116
2117 ++Stmt->LastRowFetched;
2118 ++Stmt->PositionedCursor;
2119
2120 /*Conversion etc. At this point, after fetch we can have RowResult either SQL_SUCCESS or SQL_SUCCESS_WITH_INFO */
2121 switch (MADB_FixFetchedValues(Stmt, row_num, SaveCursor))
2122 {
2123 case SQL_ERROR:
2124 RowResult= SQL_ERROR;
2125 break;
2126 case SQL_SUCCESS_WITH_INFO:
2127 RowResult= SQL_SUCCESS_WITH_INFO;
2128 /* And if result of conversions - success, just leaving that we had before */
2129 }
2130
2131 CALC_ALL_ROWS_RC(Result, RowResult, row_num);
2132
2133 if (Stmt->Ird->Header.ArrayStatusPtr)
2134 {
2135 Stmt->Ird->Header.ArrayStatusPtr[row_num]= MADB_MapToRowStatus(RowResult);
2136 }
2137 }
2138
2139 memset(Stmt->CharOffset, 0, sizeof(long) * mysql_stmt_field_count(Stmt->stmt));
2140 memset(Stmt->Lengths, 0, sizeof(long) * mysql_stmt_field_count(Stmt->stmt));
2141
2142 ResetDescIntBuffers(Stmt->Ird);
2143
2144 return Result;
2145 }
2146 /* }}} */
2147
2148 #undef CALC_ALL_ROWS_RC
2149
2150 /* {{{ MADB_StmtGetAttr */
2151 SQLRETURN MADB_StmtGetAttr(MADB_Stmt *Stmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER BufferLength,
2152 SQLINTEGER *StringLengthPtr)
2153 {
2154 SQLINTEGER StringLength;
2155 SQLRETURN ret= SQL_SUCCESS;
2156
2157 if (!StringLengthPtr)
2158 StringLengthPtr= &StringLength;
2159
2160 if (!Stmt)
2161 return SQL_INVALID_HANDLE;
2162
2163 switch(Attribute) {
2164 case SQL_ATTR_APP_PARAM_DESC:
2165 *(SQLPOINTER *)ValuePtr= Stmt->Apd;
2166 *StringLengthPtr= sizeof(SQLPOINTER *);
2167 break;
2168 case SQL_ATTR_APP_ROW_DESC:
2169 *(SQLPOINTER *)ValuePtr= Stmt->Ard;
2170 *StringLengthPtr= sizeof(SQLPOINTER *);
2171 break;
2172 case SQL_ATTR_IMP_PARAM_DESC:
2173 *(SQLPOINTER *)ValuePtr= Stmt->Ipd;
2174 *StringLengthPtr= sizeof(SQLPOINTER *);
2175 break;
2176 case SQL_ATTR_IMP_ROW_DESC:
2177 *(SQLPOINTER *)ValuePtr= Stmt->Ird;
2178 *StringLengthPtr= sizeof(SQLPOINTER *);
2179 break;
2180 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
2181 *(SQLPOINTER *)ValuePtr= Stmt->Apd->Header.BindOffsetPtr;
2182 break;
2183 case SQL_ATTR_PARAM_BIND_TYPE:
2184 *(SQLULEN *)ValuePtr= Stmt->Apd->Header.BindType;
2185 break;
2186 case SQL_ATTR_PARAM_OPERATION_PTR:
2187 *(SQLPOINTER *)ValuePtr= (SQLPOINTER)Stmt->Apd->Header.ArrayStatusPtr;
2188 break;
2189 case SQL_ATTR_PARAM_STATUS_PTR:
2190 *(SQLPOINTER *)ValuePtr= (SQLPOINTER)Stmt->Ipd->Header.ArrayStatusPtr;
2191 break;
2192 case SQL_ATTR_PARAMS_PROCESSED_PTR:
2193 *(SQLPOINTER *)ValuePtr= (SQLPOINTER)(SQLULEN)Stmt->Ipd->Header.BindType;
2194 break;
2195 case SQL_ATTR_PARAMSET_SIZE:
2196 *(SQLULEN *)ValuePtr= Stmt->Apd->Header.ArraySize;
2197 break;
2198 case SQL_ATTR_ASYNC_ENABLE:
2199 *(SQLPOINTER *)ValuePtr= SQL_ASYNC_ENABLE_OFF;
2200 break;
2201 case SQL_ATTR_ROW_ARRAY_SIZE:
2202 case SQL_ROWSET_SIZE:
2203 *(SQLULEN *)ValuePtr= Stmt->Ard->Header.ArraySize;
2204 break;
2205 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
2206 *(SQLPOINTER *)ValuePtr= (SQLPOINTER)Stmt->Ard->Header.BindOffsetPtr;
2207 break;
2208 case SQL_ATTR_ROW_BIND_TYPE:
2209 *(SQLULEN *)ValuePtr= Stmt->Ard->Header.BindType;
2210 break;
2211 case SQL_ATTR_ROW_OPERATION_PTR:
2212 *(SQLPOINTER *)ValuePtr= (SQLPOINTER)Stmt->Ard->Header.ArrayStatusPtr;
2213 break;
2214 case SQL_ATTR_ROW_STATUS_PTR:
2215 *(SQLPOINTER *)ValuePtr= (SQLPOINTER)Stmt->Ird->Header.ArrayStatusPtr;
2216 break;
2217 case SQL_ATTR_ROWS_FETCHED_PTR:
2218 *(SQLULEN **)ValuePtr= Stmt->Ird->Header.RowsProcessedPtr;
2219 break;
2220 case SQL_ATTR_USE_BOOKMARKS:
2221 *(SQLUINTEGER *)ValuePtr= Stmt->Options.UseBookmarks;
2222 case SQL_ATTR_SIMULATE_CURSOR:
2223 *(SQLULEN *)ValuePtr= Stmt->Options.SimulateCursor;
2224 break;
2225 case SQL_ATTR_CURSOR_SCROLLABLE:
2226 *(SQLULEN *)ValuePtr= Stmt->Options.CursorType;
2227 break;
2228 case SQL_ATTR_CURSOR_SENSITIVITY:
2229 *(SQLULEN *)ValuePtr= SQL_UNSPECIFIED;
2230 break;
2231 case SQL_ATTR_CURSOR_TYPE:
2232 *(SQLULEN *)ValuePtr= Stmt->Options.CursorType;
2233 break;
2234 case SQL_ATTR_CONCURRENCY:
2235 *(SQLULEN *)ValuePtr= SQL_CONCUR_READ_ONLY;
2236 break;
2237 case SQL_ATTR_ENABLE_AUTO_IPD:
2238 *(SQLULEN *)ValuePtr= SQL_FALSE;
2239 break;
2240 case SQL_ATTR_MAX_LENGTH:
2241 *(SQLULEN *)ValuePtr= Stmt->Options.MaxLength;
2242 break;
2243 case SQL_ATTR_MAX_ROWS:
2244 *(SQLULEN *)ValuePtr= Stmt->Options.MaxRows;
2245 break;
2246 case SQL_ATTR_METADATA_ID:
2247 *(SQLULEN *)ValuePtr= Stmt->Options.MetadataId;
2248 break;
2249 case SQL_ATTR_NOSCAN:
2250 *(SQLULEN *)ValuePtr= SQL_NOSCAN_ON;
2251 break;
2252 case SQL_ATTR_QUERY_TIMEOUT:
2253 *(SQLULEN *)ValuePtr= 0;
2254 break;
2255 case SQL_ATTR_RETRIEVE_DATA:
2256 *(SQLULEN *)ValuePtr= SQL_RD_ON;
2257 break;
2258 }
2259 return ret;
2260 }
2261 /* }}} */
2262
2263
2264 /* {{{ MADB_StmtSetAttr */
2265 SQLRETURN MADB_StmtSetAttr(MADB_Stmt *Stmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength)
2266 {
2267 SQLRETURN ret= SQL_SUCCESS;
2268
2269 if (!Stmt)
2270 return SQL_INVALID_HANDLE;
2271
2272 switch(Attribute) {
2273 case SQL_ATTR_APP_PARAM_DESC:
2274 if (ValuePtr)
2275 {
2276 MADB_Desc *Desc= (MADB_Desc *)ValuePtr;
2277 if (!Desc->AppType && Desc != Stmt->IApd)
2278 {
2279 MADB_SetError(&Stmt->Error, MADB_ERR_HY017, NULL, 0);
2280 return Stmt->Error.ReturnValue;
2281 }
2282 if (Desc->DescType != MADB_DESC_APD && Desc->DescType != MADB_DESC_UNKNOWN)
2283 {
2284 MADB_SetError(&Stmt->Error, MADB_ERR_HY024, NULL, 0);
2285 return Stmt->Error.ReturnValue;
2286 }
2287 RemoveStmtRefFromDesc(Stmt->Apd, Stmt, FALSE);
2288 Stmt->Apd= (MADB_Desc *)ValuePtr;
2289 Stmt->Apd->DescType= MADB_DESC_APD;
2290 if (Stmt->Apd != Stmt->IApd)
2291 {
2292 MADB_Stmt **IntStmt;
2293 IntStmt = (MADB_Stmt **)MADB_AllocDynamic(&Stmt->Apd->Stmts);
2294 *IntStmt= Stmt;
2295 }
2296 }
2297 else
2298 {
2299 RemoveStmtRefFromDesc(Stmt->Apd, Stmt, FALSE);
2300 Stmt->Apd= Stmt->IApd;
2301 }
2302 break;
2303 case SQL_ATTR_APP_ROW_DESC:
2304 if (ValuePtr)
2305 {
2306 MADB_Desc *Desc= (MADB_Desc *)ValuePtr;
2307
2308 if (!Desc->AppType && Desc != Stmt->IArd)
2309 {
2310 MADB_SetError(&Stmt->Error, MADB_ERR_HY017, NULL, 0);
2311 return Stmt->Error.ReturnValue;
2312 }
2313 if (Desc->DescType != MADB_DESC_ARD && Desc->DescType != MADB_DESC_UNKNOWN)
2314 {
2315 MADB_SetError(&Stmt->Error, MADB_ERR_HY024, NULL, 0);
2316 return Stmt->Error.ReturnValue;
2317 }
2318 RemoveStmtRefFromDesc(Stmt->Ard, Stmt, FALSE);
2319 Stmt->Ard= Desc;
2320 Stmt->Ard->DescType= MADB_DESC_ARD;
2321 if (Stmt->Ard != Stmt->IArd)
2322 {
2323 MADB_Stmt **IntStmt;
2324 IntStmt = (MADB_Stmt **)MADB_AllocDynamic(&Stmt->Ard->Stmts);
2325 *IntStmt= Stmt;
2326 }
2327 }
2328 else
2329 {
2330 RemoveStmtRefFromDesc(Stmt->Ard, Stmt, FALSE);
2331 Stmt->Ard= Stmt->IArd;
2332 }
2333 break;
2334
2335 case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
2336 Stmt->Apd->Header.BindOffsetPtr= (SQLULEN*)ValuePtr;
2337 break;
2338 case SQL_ATTR_PARAM_BIND_TYPE:
2339 Stmt->Apd->Header.BindType= (SQLINTEGER)(SQLLEN)ValuePtr;
2340 break;
2341 case SQL_ATTR_PARAM_OPERATION_PTR:
2342 Stmt->Apd->Header.ArrayStatusPtr= (SQLUSMALLINT *)ValuePtr;
2343 break;
2344 case SQL_ATTR_PARAM_STATUS_PTR:
2345 Stmt->Ipd->Header.ArrayStatusPtr= (SQLUSMALLINT *)ValuePtr;
2346 break;
2347 case SQL_ATTR_PARAMS_PROCESSED_PTR:
2348 Stmt->Ipd->Header.RowsProcessedPtr = (SQLULEN *)ValuePtr;
2349 break;
2350 case SQL_ATTR_PARAMSET_SIZE:
2351 Stmt->Apd->Header.ArraySize= (SQLULEN)ValuePtr;
2352 break;
2353 case SQL_ATTR_ROW_ARRAY_SIZE:
2354 case SQL_ROWSET_SIZE:
2355 Stmt->Ard->Header.ArraySize= (SQLULEN)ValuePtr;
2356 break;
2357 case SQL_ATTR_ROW_BIND_OFFSET_PTR:
2358 Stmt->Ard->Header.BindOffsetPtr= (SQLULEN*)ValuePtr;
2359 break;
2360 case SQL_ATTR_ROW_BIND_TYPE:
2361 Stmt->Ard->Header.BindType= (SQLINTEGER)(SQLLEN)ValuePtr;
2362 break;
2363 case SQL_ATTR_ROW_OPERATION_PTR:
2364 Stmt->Ard->Header.ArrayStatusPtr= (SQLUSMALLINT *)ValuePtr;
2365 break;
2366 case SQL_ATTR_ROW_STATUS_PTR:
2367 Stmt->Ird->Header.ArrayStatusPtr= (SQLUSMALLINT *)ValuePtr;
2368 break;
2369 case SQL_ATTR_ROWS_FETCHED_PTR:
2370 Stmt->Ird->Header.RowsProcessedPtr= (SQLULEN*)ValuePtr;
2371 break;
2372 case SQL_ATTR_ASYNC_ENABLE:
2373 if ((SQLULEN)ValuePtr != SQL_ASYNC_ENABLE_OFF)
2374 {
2375 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_ATTR_ASYNC_ENABLE)", 0);
2376 ret= SQL_SUCCESS_WITH_INFO;
2377 }
2378 break;
2379 case SQL_ATTR_SIMULATE_CURSOR:
2380 Stmt->Options.SimulateCursor= (SQLULEN) ValuePtr;
2381 break;
2382 case SQL_ATTR_CURSOR_SCROLLABLE:
2383 Stmt->Options.CursorType= ((SQLULEN)ValuePtr == SQL_NONSCROLLABLE) ?
2384 SQL_CURSOR_FORWARD_ONLY : SQL_CURSOR_STATIC;
2385 break;
2386 case SQL_ATTR_CURSOR_SENSITIVITY:
2387 /* we only support default value = SQL_UNSPECIFIED */
2388 if ((SQLULEN)ValuePtr != SQL_UNSPECIFIED)
2389 {
2390 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default cursor sensitivity", 0);
2391 ret= SQL_SUCCESS_WITH_INFO;
2392 }
2393 break;
2394 case SQL_ATTR_CURSOR_TYPE:
2395 /* We need to check global DSN/Connection settings */
2396 if (MA_ODBC_CURSOR_FORWARD_ONLY(Stmt->Connection) && (SQLULEN)ValuePtr != SQL_CURSOR_FORWARD_ONLY)
2397 {
2398 Stmt->Options.CursorType= SQL_CURSOR_FORWARD_ONLY;
2399 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_CURSOR_FORWARD_ONLY)", 0);
2400 return Stmt->Error.ReturnValue;
2401 }
2402 else if (MA_ODBC_CURSOR_DYNAMIC(Stmt->Connection))
2403 {
2404 if ((SQLULEN)ValuePtr == SQL_CURSOR_KEYSET_DRIVEN)
2405 {
2406 Stmt->Options.CursorType= SQL_CURSOR_STATIC;
2407 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_CURSOR_STATIC)", 0);
2408 return Stmt->Error.ReturnValue;
2409 }
2410 Stmt->Options.CursorType= (SQLUINTEGER)(SQLULEN)ValuePtr;
2411 }
2412 /* only FORWARD or Static is allowed */
2413 else
2414 {
2415 if ((SQLULEN)ValuePtr != SQL_CURSOR_FORWARD_ONLY &&
2416 (SQLULEN)ValuePtr != SQL_CURSOR_STATIC)
2417 {
2418 Stmt->Options.CursorType= SQL_CURSOR_STATIC;
2419 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_CURSOR_STATIC)", 0);
2420 return Stmt->Error.ReturnValue;
2421 }
2422 Stmt->Options.CursorType= (SQLUINTEGER)(SQLULEN)ValuePtr;
2423 }
2424 break;
2425 case SQL_ATTR_CONCURRENCY:
2426 if ((SQLULEN)ValuePtr != SQL_CONCUR_READ_ONLY)
2427 {
2428 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_CONCUR_READ_ONLY). ", 0);
2429 ret= SQL_SUCCESS_WITH_INFO;
2430 }
2431 break;
2432 case SQL_ATTR_ENABLE_AUTO_IPD:
2433 /* MariaDB doesn't deliver param metadata after prepare, so we can't autopopulate ird */
2434 MADB_SetError(&Stmt->Error, MADB_ERR_HYC00, NULL, 0);
2435 return Stmt->Error.ReturnValue;
2436 break;
2437 case SQL_ATTR_MAX_LENGTH:
2438 Stmt->Options.MaxLength= (SQLULEN)ValuePtr;
2439 break;
2440 case SQL_ATTR_MAX_ROWS:
2441 Stmt->Options.MaxRows= (SQLULEN)ValuePtr;
2442 break;
2443 case SQL_ATTR_METADATA_ID:
2444 Stmt->Options.MetadataId= (SQLULEN)ValuePtr;
2445 break;
2446 case SQL_ATTR_NOSCAN:
2447 if ((SQLULEN)ValuePtr != SQL_NOSCAN_ON)
2448 {
2449 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_NOSCAN_ON)", 0);
2450 ret= SQL_SUCCESS_WITH_INFO;
2451 }
2452 break;
2453 case SQL_ATTR_QUERY_TIMEOUT:
2454 if ((SQLULEN)ValuePtr != 0)
2455 {
2456 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (no timeout)", 0);
2457 ret= SQL_SUCCESS_WITH_INFO;
2458 }
2459 break;
2460 case SQL_ATTR_RETRIEVE_DATA:
2461 if ((SQLULEN)ValuePtr != SQL_RD_ON)
2462 {
2463 MADB_SetError(&Stmt->Error, MADB_ERR_01S02, "Option value changed to default (SQL_RD_ON)", 0);
2464 ret= SQL_SUCCESS_WITH_INFO;
2465 }
2466 break;
2467 case SQL_ATTR_USE_BOOKMARKS:
2468 Stmt->Options.UseBookmarks= (SQLUINTEGER)(SQLULEN)ValuePtr;
2469 break;
2470 case SQL_ATTR_FETCH_BOOKMARK_PTR:
2471 MADB_SetError(&Stmt->Error, MADB_ERR_HYC00, NULL, 0);
2472 return Stmt->Error.ReturnValue;
2473 break;
2474 default:
2475 MADB_SetError(&Stmt->Error, MADB_ERR_HY024, NULL, 0);
2476 return Stmt->Error.ReturnValue;
2477 break;
2478 }
2479 return ret;
2480 }
2481 /* }}} */
2482
2483 SQLRETURN MADB_GetBookmark(MADB_Stmt *Stmt,
2484 SQLSMALLINT TargetType,
2485 SQLPOINTER TargetValuePtr,
2486 SQLLEN BufferLength,
2487 SQLLEN *StrLen_or_IndPtr)
2488 {
2489 if (Stmt->Options.UseBookmarks == SQL_UB_OFF)
2490 {
2491 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
2492 return Stmt->Error.ReturnValue;
2493 }
2494
2495 if ((Stmt->Options.UseBookmarks == SQL_UB_VARIABLE && TargetType != SQL_C_VARBOOKMARK) ||
2496 (Stmt->Options.UseBookmarks != SQL_UB_VARIABLE && TargetType == SQL_C_VARBOOKMARK))
2497 {
2498 MADB_SetError(&Stmt->Error, MADB_ERR_HY003, NULL, 0);
2499 return Stmt->Error.ReturnValue;
2500 }
2501
2502 if (TargetValuePtr && TargetType == SQL_C_BOOKMARK && BufferLength <= sizeof(SQLULEN))
2503 {
2504 *(SQLULEN *)TargetValuePtr= Stmt->Cursor.Position;
2505 if (StrLen_or_IndPtr)
2506 {
2507 *StrLen_or_IndPtr= sizeof(SQLULEN);
2508 }
2509 return SQL_SUCCESS;
2510 }
2511
2512 /* Keeping compiler happy */
2513 return SQL_SUCCESS;
2514 }
2515
2516 /* {{{ MADB_StmtGetData */
2517 SQLRETURN MADB_StmtGetData(SQLHSTMT StatementHandle,
2518 SQLUSMALLINT Col_or_Param_Num,
2519 SQLSMALLINT TargetType,
2520 SQLPOINTER TargetValuePtr,
2521 SQLLEN BufferLength,
2522 SQLLEN * StrLen_or_IndPtr,
2523 BOOL InternalUse /* Currently this is respected for SQL_CHAR type only,
2524 since all "internal" calls of the function need string representation of datat */)
2525 {
2526 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2527 SQLUSMALLINT Offset= Col_or_Param_Num - 1;
2528 SQLSMALLINT OdbcType= 0, MadbType= 0;
2529 MYSQL_BIND Bind;
2530 my_bool IsNull= FALSE;
2531 my_bool ZeroTerminated= 0;
2532 unsigned long CurrentOffset= InternalUse == TRUE ? 0 : Stmt->CharOffset[Offset]; /* We are supposed not get bookmark column here */
2533 my_bool Error;
2534 MADB_DescRecord *IrdRec= NULL;
2535 MYSQL_FIELD *Field= mysql_fetch_field_direct(Stmt->metadata, Offset);
2536
2537 MADB_CLEAR_ERROR(&Stmt->Error);
2538
2539 /* Should not really happen, and is evidence of that something wrong happened in some previous call(SQLFetch?) */
2540 if (Stmt->stmt->bind == NULL)
2541 {
2542 MADB_SetError(&Stmt->Error, MADB_ERR_HY109, NULL, 0);
2543 return Stmt->Error.ReturnValue;
2544 }
2545
2546 if (Stmt->stmt->bind[Offset].is_null != NULL && *Stmt->stmt->bind[Offset].is_null != '\0')
2547 {
2548 if (!StrLen_or_IndPtr)
2549 {
2550 MADB_SetError(&Stmt->Error, MADB_ERR_22002, NULL, 0);
2551 return Stmt->Error.ReturnValue;
2552 }
2553 *StrLen_or_IndPtr= SQL_NULL_DATA;
2554 return SQL_SUCCESS;
2555 }
2556
2557 memset(&Bind, 0, sizeof(MYSQL_BIND));
2558
2559 /* We might need it for SQL_C_DEFAULT type, or to obtain length of fixed length types(Access likes to have it) */
2560 IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, Offset, MADB_DESC_READ);
2561 if (!IrdRec)
2562 {
2563 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
2564 return Stmt->Error.ReturnValue;
2565 }
2566
2567 switch (TargetType) {
2568 case SQL_ARD_TYPE:
2569 {
2570 MADB_DescRecord *Ard= MADB_DescGetInternalRecord(Stmt->Ard, Offset, MADB_DESC_READ);
2571
2572 if (!Ard)
2573 {
2574 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
2575 return Stmt->Error.ReturnValue;
2576 }
2577 OdbcType= Ard->ConciseType;
2578 }
2579 break;
2580 case SQL_C_DEFAULT:
2581 {
2582 /* Taking type from IRD record. This way, if mysql type was fixed(currently that is mainly for catalog functions, we don't lose it.
2583 (Access uses default types on getting catalog functions results, and not quite happy when it gets something unexpected. Seemingly it cares about returned data lenghts even for types,
2584 for which standard says application should not care about */
2585 OdbcType= IrdRec->ConciseType;
2586 }
2587 break;
2588 default:
2589 OdbcType= TargetType;
2590 break;
2591 }
2592 /* Restoring mariadb/mysql type from odbc type */
2593 MadbType= MADB_GetMaDBTypeAndLength(OdbcType, &Bind.is_unsigned, &Bind.buffer_length);
2594
2595 /* set global values for Bind */
2596 Bind.error= &Error;
2597 Bind.length= &Bind.length_value;
2598 Bind.is_null= &IsNull;
2599
2600 switch(OdbcType)
2601 {
2602 case SQL_DATE:
2603 case SQL_C_TYPE_DATE:
2604 case SQL_TIMESTAMP:
2605 case SQL_C_TYPE_TIMESTAMP:
2606 case SQL_TIME:
2607 case SQL_C_TYPE_TIME:
2608 {
2609 MYSQL_TIME tm;
2610
2611 if (IrdRec->ConciseType == SQL_CHAR || IrdRec->ConciseType == SQL_VARCHAR)
2612 {
2613 char *ClientValue= NULL;
2614 BOOL isTime;
2615
2616 if (!(ClientValue = (char *)MADB_CALLOC(Stmt->stmt->fields[Offset].max_length + 1)))
2617 {
2618 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
2619 }
2620 Bind.buffer= ClientValue;
2621 Bind.buffer_type= MYSQL_TYPE_STRING;
2622 Bind.buffer_length= Stmt->stmt->fields[Offset].max_length + 1;
2623 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, 0);
2624 RETURN_ERROR_OR_CONTINUE(MADB_Str2Ts(ClientValue, Bind.length_value, &tm, FALSE, &Stmt->Error, &isTime));
2625 }
2626 else
2627 {
2628
2629
2630 Bind.buffer_length= sizeof(MYSQL_TIME);
2631 Bind.buffer= (void *)&tm;
2632 /* c/c is too smart to convert hours to days and days to hours, we don't need that */
2633 if ((OdbcType == SQL_C_TIME || OdbcType == SQL_C_TYPE_TIME)
2634 && (IrdRec->ConciseType == SQL_TIME || IrdRec->ConciseType == SQL_TYPE_TIME))
2635 {
2636 Bind.buffer_type= MYSQL_TYPE_TIME;
2637 }
2638 else
2639 {
2640 Bind.buffer_type= MYSQL_TYPE_TIMESTAMP;
2641
2642 }
2643 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, 0);
2644 }
2645 RETURN_ERROR_OR_CONTINUE(MADB_CopyMadbTimestamp(Stmt, &tm, TargetValuePtr, StrLen_or_IndPtr, StrLen_or_IndPtr, OdbcType, IrdRec->ConciseType));
2646 break;
2647 }
2648 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
2649 case SQL_C_INTERVAL_HOUR_TO_SECOND:
2650 {
2651 MYSQL_TIME tm;
2652 SQL_INTERVAL_STRUCT *ts= (SQL_INTERVAL_STRUCT *)TargetValuePtr;
2653
2654 if (IrdRec->ConciseType == SQL_CHAR || IrdRec->ConciseType == SQL_VARCHAR)
2655 {
2656 char *ClientValue= NULL;
2657 BOOL isTime;
2658
2659 if (!(ClientValue = (char *)MADB_CALLOC(Stmt->stmt->fields[Offset].max_length + 1)))
2660 {
2661 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
2662 }
2663 Bind.buffer= ClientValue;
2664 Bind.buffer_type= MYSQL_TYPE_STRING;
2665 Bind.buffer_length= Stmt->stmt->fields[Offset].max_length + 1;
2666 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, 0);
2667 RETURN_ERROR_OR_CONTINUE(MADB_Str2Ts(ClientValue, Bind.length_value, &tm, TRUE, &Stmt->Error, &isTime));
2668 }
2669 else
2670 {
2671 Bind.buffer_length= sizeof(MYSQL_TIME);
2672 Bind.buffer= (void *)&tm;
2673 /* c/c is too smart to convert hours to days and days to hours, we don't need that */
2674 Bind.buffer_type= Field && Field->type == MYSQL_TYPE_TIME ? MYSQL_TYPE_TIME : MYSQL_TYPE_TIMESTAMP;
2675 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, 0);
2676 }
2677
2678 if (tm.hour > 99999)
2679 {
2680 return MADB_SetError(&Stmt->Error, MADB_ERR_22015, NULL, 0);
2681 }
2682
2683 ts->intval.day_second.hour= tm.hour;
2684 ts->intval.day_second.minute= tm.minute;
2685 ts->interval_sign= tm.neg ? SQL_TRUE : SQL_FALSE;
2686
2687 if (TargetType == SQL_C_INTERVAL_HOUR_TO_MINUTE)
2688 {
2689 ts->intval.day_second.second= 0;
2690 ts->interval_type= SQL_INTERVAL_HOUR_TO_MINUTE;
2691 if (tm.second)
2692 {
2693 return MADB_SetError(&Stmt->Error, MADB_ERR_01S07, NULL, 0);
2694 }
2695 }
2696 else
2697 {
2698 ts->interval_type= SQL_INTERVAL_HOUR_TO_SECOND;
2699 ts->intval.day_second.second= tm.second;
2700 }
2701 if (StrLen_or_IndPtr)
2702 {
2703 *StrLen_or_IndPtr= sizeof(SQL_INTERVAL_STRUCT);
2704 }
2705 }
2706 break;
2707 case SQL_WCHAR:
2708 case SQL_WVARCHAR:
2709 case SQL_WLONGVARCHAR:
2710 {
2711 char *ClientValue= NULL;
2712 size_t CharLength= 0;
2713
2714 /* Kinda this it not 1st call for this value, and we have it nice and recoded */
2715 if (IrdRec->InternalBuffer == NULL/* && Stmt->Lengths[Offset] == 0*/)
2716 {
2717 if (!(ClientValue = (char *)MADB_CALLOC(Stmt->stmt->fields[Offset].max_length + 1)))
2718 {
2719 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
2720 return Stmt->Error.ReturnValue;
2721 }
2722 Bind.buffer= ClientValue;
2723 Bind.buffer_type= MYSQL_TYPE_STRING;
2724 Bind.buffer_length= Stmt->stmt->fields[Offset].max_length + 1;
2725
2726 if (mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, Stmt->CharOffset[Offset]))
2727 {
2728 MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
2729 return Stmt->Error.ReturnValue;
2730 }
2731
2732 /* check total length: if not enough space, we need to calculate new CharOffset for next fetch */
2733 if (Stmt->stmt->fields[Offset].max_length)
2734 {
2735 size_t ReqBuffOctetLen;
2736 /* Size in chars */
2737 CharLength= MbstrCharLen(ClientValue, Stmt->stmt->fields[Offset].max_length - Stmt->CharOffset[Offset],
2738 Stmt->Connection->Charset.cs_info);
2739 /* MbstrCharLen gave us length in characters. For encoding of each character we might need
2740 2 SQLWCHARs in case of UTF16, or 1 SQLWCHAR in case of UTF32. Probably we need calcualate better
2741 number of required SQLWCHARs */
2742 ReqBuffOctetLen= (CharLength + 1)*(4/sizeof(SQLWCHAR))*sizeof(SQLWCHAR);
2743
2744 if (BufferLength)
2745 {
2746 /* Buffer is not big enough. Alocating InternalBuffer.
2747 MADB_SetString would do that anyway if - allocate buffer fitting the whole wide string,
2748 and then copied its part to the application's buffer */
2749 if (ReqBuffOctetLen > (size_t)BufferLength)
2750 {
2751 IrdRec->InternalBuffer= (char*)MADB_CALLOC(ReqBuffOctetLen);
2752
2753 if (IrdRec->InternalBuffer == 0)
2754 {
2755 MADB_FREE(ClientValue);
2756 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
2757 }
2758
2759 CharLength= MADB_SetString(&Stmt->Connection->Charset, IrdRec->InternalBuffer, (SQLINTEGER)ReqBuffOctetLen / sizeof(SQLWCHAR),
2760 ClientValue, Stmt->stmt->fields[Offset].max_length - Stmt->CharOffset[Offset], &Stmt->Error);
2761 }
2762 else
2763 {
2764 /* Application's buffer is big enough - writing directly there */
2765 CharLength= MADB_SetString(&Stmt->Connection->Charset, TargetValuePtr, (SQLINTEGER)(BufferLength / sizeof(SQLWCHAR)),
2766 ClientValue, Stmt->stmt->fields[Offset].max_length - Stmt->CharOffset[Offset], &Stmt->Error);
2767 }
2768
2769 if (!SQL_SUCCEEDED(Stmt->Error.ReturnValue))
2770 {
2771 MADB_FREE(ClientValue);
2772 MADB_FREE(IrdRec->InternalBuffer);
2773
2774 return Stmt->Error.ReturnValue;
2775 }
2776 }
2777
2778 if (!Stmt->CharOffset[Offset])
2779 {
2780 Stmt->Lengths[Offset]= (unsigned long)(CharLength*sizeof(SQLWCHAR));
2781 }
2782 }
2783 else if (BufferLength >= sizeof(SQLWCHAR))
2784 {
2785 *(SQLWCHAR*)TargetValuePtr= 0;
2786 }
2787 }
2788 else /* IrdRec->InternalBuffer == NULL && Stmt->Lengths[Offset] == 0 */
2789 {
2790 CharLength= SqlwcsLen((SQLWCHAR*)((char*)IrdRec->InternalBuffer + Stmt->CharOffset[Offset]), -1);
2791 }
2792
2793 if (StrLen_or_IndPtr)
2794 {
2795 *StrLen_or_IndPtr= CharLength * sizeof(SQLWCHAR);
2796 }
2797
2798 if (!BufferLength)
2799 {
2800 MADB_FREE(ClientValue);
2801
2802 return MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
2803 }
2804
2805 if (IrdRec->InternalBuffer)
2806 {
2807 /* If we have more place than only for the TN */
2808 if (BufferLength > sizeof(SQLWCHAR))
2809 {
2810 memcpy(TargetValuePtr, (char*)IrdRec->InternalBuffer + Stmt->CharOffset[Offset],
2811 MIN(BufferLength - sizeof(SQLWCHAR), CharLength*sizeof(SQLWCHAR)));
2812 }
2813 /* Terminating Null */
2814 *(SQLWCHAR*)((char*)TargetValuePtr + MIN(BufferLength - sizeof(SQLWCHAR), CharLength*sizeof(SQLWCHAR)))= 0;
2815 }
2816
2817 if (CharLength >= BufferLength / sizeof(SQLWCHAR))
2818 {
2819 /* Calculate new offset and substract 1 byte for null termination */
2820 Stmt->CharOffset[Offset]+= (unsigned long)BufferLength - sizeof(SQLWCHAR);
2821 MADB_FREE(ClientValue);
2822
2823 return MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
2824 }
2825 else
2826 {
2827 Stmt->CharOffset[Offset]= Stmt->Lengths[Offset];
2828 MADB_FREE(IrdRec->InternalBuffer);
2829 }
2830
2831 MADB_FREE(ClientValue);
2832 }
2833 break;
2834 case SQL_CHAR:
2835 case SQL_VARCHAR:
2836 if (Stmt->stmt->fields[Offset].type == MYSQL_TYPE_BLOB &&
2837 Stmt->stmt->fields[Offset].charsetnr == 63)
2838 {
2839 if (!BufferLength && StrLen_or_IndPtr)
2840 {
2841 *StrLen_or_IndPtr= Stmt->stmt->fields[Offset].max_length * 2;
2842 return SQL_SUCCESS_WITH_INFO;
2843 }
2844
2845 #ifdef CONVERSION_TO_HEX_IMPLEMENTED
2846 {
2847 /*TODO: */
2848 char *TmpBuffer;
2849 if (!(TmpBuffer= (char *)MADB_CALLOC(BufferLength)))
2850 {
2851
2852 }
2853 }
2854 #endif
2855 }
2856 ZeroTerminated= 1;
2857
2858 case SQL_LONGVARCHAR:
2859 case SQL_BINARY:
2860 case SQL_VARBINARY:
2861 case SQL_LONGVARBINARY:
2862 {
2863 Bind.buffer= TargetValuePtr;
2864 Bind.buffer_length= (unsigned long)BufferLength;
2865 Bind.buffer_type= MadbType;
2866
2867 if (!(BufferLength) && StrLen_or_IndPtr)
2868 {
2869 /* Paranoid - before StrLen_or_IndPtr was used as length directly. so leaving same value in Bind.length. Unlikely needed */
2870 Bind.length_value= (unsigned long)*StrLen_or_IndPtr;
2871 Bind.length= &Bind.length_value;
2872
2873 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, Stmt->CharOffset[Offset]);
2874
2875 if (InternalUse)
2876 {
2877 *StrLen_or_IndPtr= MIN(*Bind.length, Stmt->stmt->fields[Offset].max_length);
2878 }
2879 else
2880 {
2881 if (!Stmt->CharOffset[Offset])
2882 {
2883 Stmt->Lengths[Offset]= MIN(*Bind.length, Stmt->stmt->fields[Offset].max_length);
2884 }
2885 *StrLen_or_IndPtr= Stmt->Lengths[Offset] - Stmt->CharOffset[Offset];
2886 }
2887
2888 MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
2889
2890 return SQL_SUCCESS_WITH_INFO;
2891 }
2892
2893 if (mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, CurrentOffset))
2894 {
2895 MADB_SetNativeError(&Stmt->Error, SQL_HANDLE_STMT, Stmt->stmt);
2896 return Stmt->Error.ReturnValue;
2897 }
2898 /* Dirty temporary hack before we know what is going on. Yes, there is nothing more eternal, than temporary
2899 It's not that bad, after all */
2900 if ((long)*Bind.length == -1)
2901 {
2902 *Bind.length= 0;
2903 }
2904 /* end of dirty hack */
2905
2906 if (!InternalUse && !Stmt->CharOffset[Offset])
2907 {
2908 Stmt->Lengths[Offset]= MIN(*Bind.length, Stmt->stmt->fields[Offset].max_length);
2909 }
2910 if (ZeroTerminated)
2911 {
2912 char *p= (char *)Bind.buffer;
2913 if (BufferLength > (SQLLEN)*Bind.length)
2914 {
2915 p[*Bind.length]= 0;
2916 }
2917 else
2918 {
2919 p[BufferLength-1]= 0;
2920 }
2921 }
2922
2923 if (StrLen_or_IndPtr)
2924 {
2925 *StrLen_or_IndPtr= *Bind.length - CurrentOffset;
2926 }
2927 if (InternalUse == FALSE)
2928 {
2929 /* Recording new offset only if that is API call, and not getting data for internal use */
2930 Stmt->CharOffset[Offset]+= MIN((unsigned long)BufferLength - ZeroTerminated, *Bind.length);
2931 if ((BufferLength - ZeroTerminated) && Stmt->Lengths[Offset] > Stmt->CharOffset[Offset])
2932 {
2933 MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
2934 return Stmt->Error.ReturnValue;
2935 }
2936 }
2937
2938 if (StrLen_or_IndPtr && BufferLength - ZeroTerminated < *StrLen_or_IndPtr)
2939 {
2940 MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
2941 return SQL_SUCCESS_WITH_INFO;
2942 }
2943 }
2944 break;
2945 case SQL_NUMERIC:
2946 {
2947 SQLRETURN rc;
2948 char *tmp;
2949 MADB_DescRecord *Ard= MADB_DescGetInternalRecord(Stmt->Ard, Offset, MADB_DESC_READ);
2950
2951 Bind.buffer_length= MADB_DEFAULT_PRECISION + 1/*-*/ + 1/*.*/;
2952 tmp= (char *)MADB_CALLOC(Bind.buffer_length);
2953 Bind.buffer= tmp;
2954
2955 Bind.buffer_type= MadbType;
2956
2957 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, 0);
2958
2959 MADB_CLEAR_ERROR(&Stmt->Error);
2960
2961 if (Bind.buffer_length < Stmt->stmt->fields[Offset].max_length)
2962 {
2963 MADB_SetError(&Stmt->Error, MADB_ERR_22003, NULL, 0);
2964 MADB_FREE(tmp);
2965 return Stmt->Error.ReturnValue;
2966 }
2967
2968 rc= MADB_CharToSQLNumeric(tmp, Stmt->Ard, Ard, TargetValuePtr, 0);
2969
2970 /* Ugly */
2971 if (rc != SQL_SUCCESS)
2972 {
2973 MADB_SetError(&Stmt->Error, rc, NULL, 0);
2974 if (rc == SQL_ERROR)
2975 {
2976 return SQL_ERROR;
2977 }
2978 }
2979
2980 if (StrLen_or_IndPtr != NULL)
2981 {
2982 *StrLen_or_IndPtr= sizeof(SQL_NUMERIC_STRUCT);
2983 }
2984 break;
2985 }
2986 default:
2987 {
2988 /* Set the conversion function */
2989 Bind.buffer_type= MadbType;
2990 Bind.buffer= TargetValuePtr;
2991 if (Bind.buffer_length == 0 && BufferLength > 0)
2992 {
2993 Bind.buffer_length= (unsigned long)BufferLength;
2994 }
2995 mysql_stmt_fetch_column(Stmt->stmt, &Bind, Offset, 0);
2996
2997 if (StrLen_or_IndPtr != NULL)
2998 {
2999 /* We get here only for fixed data types. Thus, according to the specs
3000 "this is the length of the data after conversion; that is, it is the size of the type to which the data was converted".
3001 For us that is the size of the buffer in bind structure. Not the size of the field */
3002
3003 *StrLen_or_IndPtr= Bind.buffer_length;
3004
3005 /* Paranoid - it was here, so leaving it in place */
3006 if ((long)Bind.length_value == -1)
3007 {
3008 Bind.length_value= 0;
3009 }
3010 /* We do this for catalog functions and MS Access in first turn. The thing is that for some columns in catalog functions result,
3011 we fix column type manually, since we can't make field of desired type in the query to I_S. Mostly that is for SQLSMALLINT
3012 fields, and we can cast only to int, not to short. MSAccess in its turn like to to get length for fixed length types, and
3013 throws error if the length is not what it expected (ODBC-131)
3014 Probably it makes sense to do this only for SQL_C_DEFAULT type, which MS Access uses. But atm it looks like this should
3015 not hurt if done for other types, too */
3016 if (*StrLen_or_IndPtr == 0 || (Bind.length_value > (unsigned long)IrdRec->OctetLength && *StrLen_or_IndPtr > IrdRec->OctetLength))
3017 {
3018 *StrLen_or_IndPtr= IrdRec->OctetLength;
3019 }
3020 }
3021 }
3022 } /* End of switch(OdbcType) */
3023
3024 /* Marking fixed length fields to be able to return SQL_NO_DATA on subsequent calls, as standard prescribes
3025 "SQLGetData cannot be used to return fixed-length data in parts. If SQLGetData is called more than one time
3026 in a row for a column containing fixed-length data, it returns SQL_NO_DATA for all calls after the first."
3027 Stmt->Lengths[Offset] would be set for variable length types */
3028 if (!InternalUse && Stmt->Lengths[Offset] == 0)
3029 {
3030 Stmt->CharOffset[Offset]= MAX((unsigned long)Bind.buffer_length, Bind.length_value);
3031 }
3032
3033 if (IsNull)
3034 {
3035 if (!StrLen_or_IndPtr)
3036 {
3037 return MADB_SetError(&Stmt->Error, MADB_ERR_22002, NULL, 0);
3038 }
3039 *StrLen_or_IndPtr= SQL_NULL_DATA;
3040 }
3041
3042 return Stmt->Error.ReturnValue;
3043 }
3044 /* }}} */
3045
3046 /* {{{ MADB_StmtRowCount */
3047 SQLRETURN MADB_StmtRowCount(MADB_Stmt *Stmt, SQLLEN *RowCountPtr)
3048 {
3049 if (Stmt->AffectedRows != -1)
3050 *RowCountPtr= (SQLLEN)Stmt->AffectedRows;
3051 else if (Stmt->stmt && Stmt->stmt->result.rows && mysql_stmt_field_count(Stmt->stmt))
3052 *RowCountPtr= (SQLLEN)mysql_stmt_num_rows(Stmt->stmt);
3053 else
3054 *RowCountPtr= 0;
3055 return SQL_SUCCESS;
3056 }
3057 /* }}} */
3058
3059 /* {{{ MapColAttributesDescType */
3060 SQLUSMALLINT MapColAttributeDescType(SQLUSMALLINT FieldIdentifier)
3061 {
3062 /* we need to map the old field identifiers, see bug ODBC-8 */
3063 switch (FieldIdentifier)
3064 {
3065 case SQL_COLUMN_SCALE:
3066 return SQL_DESC_SCALE;
3067 case SQL_COLUMN_PRECISION:
3068 return SQL_DESC_PRECISION;
3069 case SQL_COLUMN_NULLABLE:
3070 return SQL_DESC_NULLABLE;
3071 case SQL_COLUMN_LENGTH:
3072 return SQL_DESC_OCTET_LENGTH;
3073 case SQL_COLUMN_NAME:
3074 return SQL_DESC_NAME;
3075 default:
3076 return FieldIdentifier;
3077 }
3078 }
3079 /* }}} */
3080
3081 /* {{{ MADB_StmtRowCount */
3082 SQLRETURN MADB_StmtParamCount(MADB_Stmt *Stmt, SQLSMALLINT *ParamCountPtr)
3083 {
3084 *ParamCountPtr= (SQLSMALLINT)mysql_stmt_param_count(Stmt->stmt);
3085 return SQL_SUCCESS;
3086 }
3087 /* }}} */
3088
3089 /* {{{ MADB_StmtColumnCount */
3090 SQLRETURN MADB_StmtColumnCount(MADB_Stmt *Stmt, SQLSMALLINT *ColumnCountPtr)
3091 {
3092 /* We supposed to have that data in the descriptor by now. No sense to ask C/C API one more time for that */
3093 *ColumnCountPtr= (SQLSMALLINT)MADB_STMT_COLUMN_COUNT(Stmt);
3094 return SQL_SUCCESS;
3095 }
3096 /* }}} */
3097
3098 /* {{{ MADB_StmtColAttr */
3099 SQLRETURN MADB_StmtColAttr(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr,
3100 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, SQLLEN *NumericAttributePtr, my_bool IsWchar)
3101 {
3102 MADB_DescRecord *Record;
3103 SQLSMALLINT StringLength= 0;
3104 SQLLEN NumericAttribute;
3105 BOOL IsNumericAttr= TRUE;
3106
3107 if (!Stmt)
3108 return SQL_INVALID_HANDLE;
3109
3110 MADB_CLEAR_ERROR(&Stmt->Error);
3111
3112 if (StringLengthPtr)
3113 *StringLengthPtr= 0;
3114
3115 if (!Stmt->stmt || !mysql_stmt_field_count(Stmt->stmt))
3116 {
3117 MADB_SetError(&Stmt->Error, MADB_ERR_07005, NULL, 0);
3118 return Stmt->Error.ReturnValue;
3119 }
3120
3121 if (ColumnNumber < 1 || ColumnNumber > mysql_stmt_field_count(Stmt->stmt))
3122 {
3123 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
3124 return Stmt->Error.ReturnValue;
3125 }
3126
3127 /* We start at offset zero */
3128 --ColumnNumber;
3129
3130 if (!(Record= MADB_DescGetInternalRecord(Stmt->Ird, ColumnNumber, MADB_DESC_READ)))
3131 {
3132 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
3133 return Stmt->Error.ReturnValue;
3134 }
3135
3136 /* Mapping ODBC2 attributes to ODBC3
3137 TODO: it looks like it takes more than that
3138 "In ODBC 3.x driver must support SQL_COLUMN_PRECISION and SQL_DESC_PRECISION, SQL_COLUMN_SCALE and SQL_DESC_SCALE,
3139 and SQL_COLUMN_LENGTH and SQL_DESC_LENGTH. These values are different because precision, scale, and length are defined
3140 differently in ODBC 3.x than they were in ODBC 2.x."
3141 */
3142 FieldIdentifier= MapColAttributeDescType(FieldIdentifier);
3143
3144 switch(FieldIdentifier) {
3145 case SQL_DESC_AUTO_UNIQUE_VALUE:
3146 NumericAttribute= (SQLLEN)Record->AutoUniqueValue;
3147 break;
3148 case SQL_DESC_BASE_COLUMN_NAME:
3149 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : NULL,
3150 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3151 Record->BaseColumnName, strlen(Record->BaseColumnName), &Stmt->Error);
3152 IsNumericAttr= FALSE;
3153 break;
3154 case SQL_DESC_BASE_TABLE_NAME:
3155 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : NULL,
3156 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3157 Record->BaseTableName, strlen(Record->BaseTableName), &Stmt->Error);
3158 IsNumericAttr= FALSE;
3159 break;
3160 case SQL_DESC_CASE_SENSITIVE:
3161 NumericAttribute= (SQLLEN)Record->CaseSensitive;
3162 break;
3163 case SQL_DESC_CATALOG_NAME:
3164 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3165 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3166 Record->CatalogName, strlen(Record->CatalogName), &Stmt->Error);
3167 IsNumericAttr= FALSE;
3168 break;
3169 case SQL_DESC_SCHEMA_NAME:
3170 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3171 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3172 "", 0, &Stmt->Error);
3173 IsNumericAttr= FALSE;
3174 case SQL_DESC_CONCISE_TYPE:
3175 NumericAttribute= (SQLLEN)Record->ConciseType;
3176 break;
3177 case SQL_DESC_SEARCHABLE:
3178 NumericAttribute= (SQLLEN)Record->Searchable;
3179 break;
3180 case SQL_DESC_COUNT:
3181 NumericAttribute= (SQLLEN)Stmt->Ird->Header.Count;
3182 break;
3183 case SQL_DESC_DISPLAY_SIZE:
3184 NumericAttribute= (SQLLEN)Record->DisplaySize;
3185 break;
3186 case SQL_DESC_FIXED_PREC_SCALE:
3187 NumericAttribute= (SQLLEN)Record->FixedPrecScale;
3188 break;
3189 case SQL_DESC_PRECISION:
3190 NumericAttribute= (SQLLEN)Record->Precision;
3191 break;
3192 case SQL_DESC_LENGTH:
3193 NumericAttribute= (SQLLEN)Record->Length;
3194 break;
3195 case SQL_DESC_LITERAL_PREFIX:
3196 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3197 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3198 Record->LiteralPrefix, strlen(Record->LiteralPrefix), &Stmt->Error);
3199 IsNumericAttr= FALSE;
3200 break;
3201 case SQL_DESC_LITERAL_SUFFIX:
3202 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3203 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3204 Record->LiteralSuffix, strlen(Record->LiteralSuffix), &Stmt->Error);
3205 IsNumericAttr= FALSE;
3206 break;
3207 case SQL_DESC_LOCAL_TYPE_NAME:
3208 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3209 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3210 "", 0, &Stmt->Error);
3211 IsNumericAttr= FALSE;
3212 break;
3213 case SQL_DESC_LABEL:
3214 case SQL_DESC_NAME:
3215 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3216 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3217 Record->ColumnName, strlen(Record->ColumnName), &Stmt->Error);
3218 IsNumericAttr= FALSE;
3219 break;
3220 case SQL_DESC_TYPE_NAME:
3221 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3222 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3223 Record->TypeName, strlen(Record->TypeName), &Stmt->Error);
3224 IsNumericAttr= FALSE;
3225 break;
3226 case SQL_DESC_NULLABLE:
3227 NumericAttribute= Record->Nullable;
3228 break;
3229 case SQL_DESC_UNNAMED:
3230 NumericAttribute= Record->Unnamed;
3231 break;
3232 case SQL_DESC_UNSIGNED:
3233 NumericAttribute= Record->Unsigned;
3234 break;
3235 case SQL_DESC_UPDATABLE:
3236 NumericAttribute= Record->Updateable;
3237 break;
3238 case SQL_DESC_OCTET_LENGTH:
3239 NumericAttribute= Record->OctetLength;
3240 break;
3241 case SQL_DESC_SCALE:
3242 NumericAttribute= Record->Scale;
3243 break;
3244 case SQL_DESC_TABLE_NAME:
3245 StringLength= (SQLSMALLINT)MADB_SetString(IsWchar ? &Stmt->Connection->Charset : 0,
3246 CharacterAttributePtr, (IsWchar) ? BufferLength / sizeof(SQLWCHAR) : BufferLength,
3247 Record->TableName, strlen(Record->TableName), &Stmt->Error);
3248 IsNumericAttr= FALSE;
3249 break;
3250 case SQL_DESC_TYPE:
3251 NumericAttribute= Record->Type;
3252 break;
3253 case SQL_COLUMN_COUNT:
3254 NumericAttribute= mysql_stmt_field_count(Stmt->stmt);
3255 break;
3256 default:
3257 MADB_SetError(&Stmt->Error, MADB_ERR_HYC00, NULL, 0);
3258 return Stmt->Error.ReturnValue;
3259 }
3260 /* We need to return the number of bytes, not characters! */
3261 if (StringLength)
3262 {
3263 if (StringLengthPtr)
3264 *StringLengthPtr= (SQLSMALLINT)StringLength;
3265 if (!BufferLength && CharacterAttributePtr)
3266 MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
3267 }
3268 /* We shouldn't touch application memory without purpose, writing garbage there. Thus IsNumericAttr.
3269 Besides .Net was quite disappointed about that */
3270 if (NumericAttributePtr && IsNumericAttr == TRUE)
3271 *NumericAttributePtr= NumericAttribute;
3272 if (StringLengthPtr && IsWchar)
3273 *StringLengthPtr*= sizeof(SQLWCHAR);
3274 return Stmt->Error.ReturnValue;
3275 }
3276 /* }}} */
3277
3278 /* {{{ MADB_StmtColumnPrivileges */
3279 SQLRETURN MADB_StmtColumnPrivileges(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
3280 char *SchemaName, SQLSMALLINT NameLength2, char *TableName,
3281 SQLSMALLINT NameLength3, char *ColumnName, SQLSMALLINT NameLength4)
3282 {
3283 char StmtStr[1024];
3284 char *p;
3285
3286 MADB_CLEAR_ERROR(&Stmt->Error);
3287
3288 /* TableName is mandatory */
3289 if (!TableName || !NameLength3)
3290 {
3291 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "Tablename is required", 0);
3292 return Stmt->Error.ReturnValue;
3293 }
3294
3295 p= StmtStr;
3296 p+= _snprintf(StmtStr, 1024, "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL as TABLE_SCHEM, TABLE_NAME,"
3297 "COLUMN_NAME, NULL AS GRANTOR, GRANTEE, PRIVILEGE_TYPE AS PRIVILEGE,"
3298 "IS_GRANTABLE FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES WHERE ");
3299 if (CatalogName && CatalogName[0])
3300 p+= _snprintf(p, 1024 - strlen(StmtStr), "TABLE_SCHEMA LIKE '%s' ", CatalogName);
3301 else
3302 p+= _snprintf(p, 1024 - strlen(StmtStr), "TABLE_SCHEMA LIKE DATABASE() ");
3303 if (TableName && TableName[0])
3304 p+= _snprintf(p, 1024 - strlen(StmtStr), "AND TABLE_NAME LIKE '%s' ", TableName);
3305 if (ColumnName && ColumnName[0])
3306 p+= _snprintf(p, 1024 - strlen(StmtStr), "AND COLUMN_NAME LIKE '%s' ", ColumnName);
3307
3308 p+= _snprintf(p, 1024 - strlen(StmtStr), "ORDER BY TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, PRIVILEGE");
3309
3310 return Stmt->Methods->ExecDirect(Stmt, StmtStr, (SQLINTEGER)strlen(StmtStr));
3311 }
3312 /* }}} */
3313
3314 /* {{{ MADB_StmtTablePrivileges */
3315 SQLRETURN MADB_StmtTablePrivileges(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
3316 char *SchemaName, SQLSMALLINT NameLength2,
3317 char *TableName, SQLSMALLINT NameLength3)
3318 {
3319 char StmtStr[1024],
3320 *p;
3321
3322 MADB_CLEAR_ERROR(&Stmt->Error);
3323
3324 p= StmtStr;
3325 p += _snprintf(StmtStr, 1024, "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, "
3326 "NULL AS GRANTOR, GRANTEE, PRIVILEGE_TYPE AS PRIVILEGE, IS_GRANTABLE "
3327 "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES WHERE ");
3328 if (CatalogName)
3329 p+= _snprintf(p, 1024 - strlen(StmtStr), "TABLE_SCHEMA LIKE '%s' ", CatalogName);
3330 else
3331 p+= _snprintf(p, 1024 - strlen(StmtStr), "TABLE_SCHEMA LIKE IF(DATABASE(), DATABASE(), '%%') ");
3332 if (TableName)
3333 p+= _snprintf(p, 1024 - strlen(StmtStr), "AND TABLE_NAME LIKE '%s' ", TableName);
3334
3335 p+= _snprintf(p, 1024 - strlen(StmtStr), "ORDER BY TABLE_SCHEM, TABLE_NAME, PRIVILEGE");
3336
3337 return Stmt->Methods->ExecDirect(Stmt, StmtStr, (SQLINTEGER)strlen(StmtStr));
3338 }
3339 /* }}} */
3340
3341 /* {{{ MADB_StmtTables */
3342 SQLRETURN MADB_StmtTables(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT CatalogNameLength,
3343 char *SchemaName, SQLSMALLINT SchemaNameLength, char *TableName,
3344 SQLSMALLINT TableNameLength, char *TableType, SQLSMALLINT TableTypeLength)
3345 {
3346 MADB_DynString StmtStr;
3347 char Quote[2];
3348 SQLRETURN ret;
3349
3350 /*
3351 METADATA_ID CatalogName SchemaName TableName TableType
3352 ---------------------------------------------------------------------------------
3353 ODBC_V3:
3354 SQL_FALSE Pattern Pattern Pattern ValueList
3355 SQL_TRUE Identifier Identifier Identifier ValueList
3356 ODBC_V2:
3357 Identifier Identifier Identifier ValueList
3358 --------------------------------------------------------------------------------
3359 */
3360
3361 MDBUG_C_ENTER(Stmt->Connection, "MADB_StmtTables");
3362
3363 ADJUST_LENGTH(CatalogName, CatalogNameLength);
3364 ADJUST_LENGTH(SchemaName, SchemaNameLength);
3365 ADJUST_LENGTH(TableName, TableNameLength);
3366 ADJUST_LENGTH(TableType, TableTypeLength);
3367
3368 if (CatalogNameLength > 64 || TableNameLength > 64)
3369 {
3370 MADB_SetError(&Stmt->Error, MADB_ERR_HY090, "Table and catalog names are limited to 64 chars", 0);
3371 return Stmt->Error.ReturnValue;
3372 }
3373
3374 /* SQL_ALL_CATALOGS
3375 If CatalogName is SQL_ALL_CATALOGS and SchemaName and TableName are empty strings,
3376 the result set contains a list of valid catalogs for the data source.
3377 (All columns except the TABLE_CAT column contain NULLs
3378 */
3379 if (CatalogName && CatalogNameLength && TableName != NULL && !TableNameLength &&
3380 SchemaName != NULL && SchemaNameLength == 0 && !strcmp(CatalogName, SQL_ALL_CATALOGS))
3381 {
3382 MADB_InitDynamicString(&StmtStr, "SELECT SCHEMA_NAME AS TABLE_CAT, CONVERT(NULL,CHAR(64)) AS TABLE_SCHEM, "
3383 "CONVERT(NULL,CHAR(64)) AS TABLE_NAME, NULL AS TABLE_TYPE, NULL AS REMARKS "
3384 "FROM INFORMATION_SCHEMA.SCHEMATA "
3385 "GROUP BY SCHEMA_NAME ORDER BY SCHEMA_NAME",
3386 8192, 512);
3387 }
3388 /* SQL_ALL_TABLE_TYPES
3389 If TableType is SQL_ALL_TABLE_TYPES and CatalogName, SchemaName, and TableName are empty strings,
3390 the result set contains a list of valid table types for the data source.
3391 (All columns except the TABLE_TYPE column contain NULLs.)
3392 */
3393 else if (CatalogName != NULL && !CatalogNameLength && TableName != NULL && !TableNameLength &&
3394 SchemaName != NULL && SchemaNameLength == 0 && TableType && TableTypeLength &&
3395 !strcmp(TableType, SQL_ALL_TABLE_TYPES))
3396 {
3397 MADB_InitDynamicString(&StmtStr, "SELECT NULL AS TABLE_CAT, NULL AS TABLE_SCHEM, "
3398 "NULL AS TABLE_NAME, 'TABLE' AS TABLE_TYPE, NULL AS REMARKS "
3399 "FROM DUAL "
3400 "UNION "
3401 "SELECT NULL, NULL, NULL, 'VIEW', NULL FROM DUAL "
3402 "UNION "
3403 "SELECT NULL, NULL, NULL, 'SYSTEM VIEW', NULL FROM DUAL",
3404 8192, 512);
3405 }
3406 /* Since we treat our databases as catalogs, the only acceptable value for schema is NULL or "%"
3407 if that is not the special case of call for schemas list. Otherwise we return empty resultset*/
3408 else if (SchemaName &&
3409 (!strcmp(SchemaName,SQL_ALL_SCHEMAS) && CatalogName && CatalogNameLength == 0 && TableName && TableNameLength == 0 ||
3410 strcmp(SchemaName, SQL_ALL_SCHEMAS)))
3411 {
3412 MADB_InitDynamicString(&StmtStr, "SELECT NULL AS TABLE_CAT, NULL AS TABLE_SCHEM, "
3413 "NULL AS TABLE_NAME, NULL AS TABLE_TYPE, NULL AS REMARKS "
3414 "FROM DUAL WHERE 1=0", 8192, 512);
3415 }
3416 else
3417 {
3418 MADB_InitDynamicString(&StmtStr, "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, "
3419 "if(TABLE_TYPE='BASE TABLE','TABLE',TABLE_TYPE) AS TABLE_TYPE ,"
3420 "TABLE_COMMENT AS REMARKS FROM INFORMATION_SCHEMA.TABLES WHERE 1=1 ",
3421 8192, 512);
3422 if (Stmt->Options.MetadataId== SQL_TRUE)
3423 {
3424 strcpy(Quote, "`");
3425 }
3426 else
3427 {
3428 strcpy(Quote, "'");
3429 }
3430
3431 if (CatalogName)
3432 {
3433 MADB_DynstrAppend(&StmtStr, " AND TABLE_SCHEMA ");
3434 MADB_DynstrAppend(&StmtStr, "LIKE ");
3435 MADB_DynstrAppend(&StmtStr, Quote);
3436 MADB_DynstrAppend(&StmtStr, CatalogName);
3437 MADB_DynstrAppend(&StmtStr, Quote);
3438 }
3439
3440 if (TableName && TableNameLength)
3441 {
3442 MADB_DynstrAppend(&StmtStr, " AND TABLE_NAME LIKE ");
3443 MADB_DynstrAppend(&StmtStr, Quote);
3444 MADB_DynstrAppend(&StmtStr, TableName);
3445 MADB_DynstrAppend(&StmtStr, Quote);
3446 }
3447 if (TableType && TableTypeLength && strcmp(TableType, SQL_ALL_TABLE_TYPES) != 0)
3448 {
3449 unsigned int i;
3450 char *myTypes[3]= {"TABLE", "VIEW", "SYNONYM"};
3451 MADB_DynstrAppend(&StmtStr, " AND TABLE_TYPE IN (''");
3452 for (i= 0; i < 3; i++)
3453 {
3454 if (strstr(TableType, myTypes[i]))
3455 {
3456 if (strstr(myTypes[i], "TABLE"))
3457 MADB_DynstrAppend(&StmtStr, ", 'BASE TABLE'");
3458 else
3459 {
3460 MADB_DynstrAppend(&StmtStr, ", '");
3461 MADB_DynstrAppend(&StmtStr, myTypes[i]);
3462 MADB_DynstrAppend(&StmtStr, "'");
3463 }
3464 }
3465 }
3466 MADB_DynstrAppend(&StmtStr, ") ");
3467 }
3468 MADB_DynstrAppend(&StmtStr, " ORDER BY TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE");
3469 }
3470 MDBUG_C_PRINT(Stmt->Connection, "SQL Statement: %s", StmtStr.str);
3471
3472 ret= Stmt->Methods->ExecDirect(Stmt, StmtStr.str, SQL_NTS);
3473
3474 MADB_DynstrFree(&StmtStr);
3475
3476 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
3477 }
3478 /* }}} */
3479
3480 static MADB_ShortTypeInfo SqlStatsColType[13]=
3481 /*1*/ {{SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_VARCHAR, 0, SQL_NO_NULLS, 0}, {SQL_SMALLINT, 0, SQL_NULLABLE, 0},
3482 /*5*/ {SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_SMALLINT, 0, SQL_NO_NULLS, 0}, {SQL_SMALLINT, 0, SQL_NULLABLE, 0},
3483 /*9*/ {SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_CHAR, 0, SQL_NULLABLE, 2}, {SQL_INTEGER, 0, SQL_NULLABLE, 0}, {SQL_INTEGER, 0, SQL_NULLABLE, 0},
3484 /*13*/ {SQL_VARCHAR, 0, SQL_NULLABLE, 0}};
3485
3486 /* {{{ MADB_StmtStatistics */
3487 SQLRETURN MADB_StmtStatistics(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
3488 char *SchemaName, SQLSMALLINT NameLength2,
3489 char *TableName, SQLSMALLINT NameLength3,
3490 SQLUSMALLINT Unique, SQLUSMALLINT Reserved)
3491 {
3492 char StmtStr[1024];
3493 char *p= StmtStr;
3494
3495 SQLRETURN ret;
3496
3497 MADB_CLEAR_ERROR(&Stmt->Error);
3498
3499 /* TableName is mandatory */
3500 if (!TableName || !NameLength3)
3501 {
3502 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "Tablename is required", 0);
3503 return Stmt->Error.ReturnValue;
3504 }
3505
3506 _snprintf(StmtStr, 1024, "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, "
3507 "NON_UNIQUE, NULL AS INDEX_QUALIFIER, INDEX_NAME, "
3508 "%d AS TYPE, "
3509 "SEQ_IN_INDEX AS ORDINAL_POSITION, COLUMN_NAME, COLLATION AS ASC_OR_DESC, "
3510 "CARDINALITY, NULL AS PAGES, NULL AS FILTER_CONDITION "
3511 "FROM INFORMATION_SCHEMA.STATISTICS ",
3512 SQL_INDEX_OTHER);
3513 p+= strlen(StmtStr);
3514 if (CatalogName && CatalogName[0])
3515 p+= _snprintf(p, 1023 - strlen(StmtStr), "WHERE TABLE_SCHEMA LIKE '%s' ", CatalogName);
3516 else
3517 p+= _snprintf(p, 1023 - strlen(StmtStr), "WHERE TABLE_SCHEMA LIKE IF(DATABASE() IS NOT NULL, DATABASE(), '%%') ");
3518
3519 if (TableName)
3520 p+= _snprintf(p, 1023- strlen(StmtStr), "AND TABLE_NAME LIKE '%s' ", TableName);
3521
3522 if (Unique == SQL_INDEX_UNIQUE)
3523 p+= _snprintf(p, 1023 - strlen(StmtStr), "AND NON_UNIQUE=0 ");
3524
3525 _snprintf(p, 1023 - strlen(StmtStr), "ORDER BY NON_UNIQUE, INDEX_NAME, ORDINAL_POSITION");
3526
3527
3528 ret= Stmt->Methods->ExecDirect(Stmt, StmtStr, SQL_NTS);
3529
3530 if (SQL_SUCCEEDED(ret))
3531 {
3532 MADB_FixColumnDataTypes(Stmt, SqlStatsColType);
3533 }
3534 return ret;
3535 }
3536 /* }}} */
3537
3538
3539 static MADB_ShortTypeInfo SqlColumnsColType[18]=
3540 /*1*/ {{SQL_VARCHAR, 0, SQL_NO_NULLS, 0}, {SQL_VARCHAR, 0, SQL_NO_NULLS, 0}, {SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_VARCHAR, 0, SQL_NULLABLE, 0},
3541 /*5*/ {SQL_SMALLINT, 0, SQL_NO_NULLS, 0}, {SQL_VARCHAR, 0, SQL_NO_NULLS, 0}, {SQL_INTEGER, 0, SQL_NULLABLE, 0}, {SQL_INTEGER, 0, SQL_NULLABLE, 0},
3542 /*9*/ {SQL_SMALLINT, 0, SQL_NULLABLE, 0}, {SQL_SMALLINT, 0, SQL_NULLABLE, 0}, {SQL_SMALLINT, 0, SQL_NO_NULLS, 0}, {SQL_VARCHAR, 0, SQL_NULLABLE, 0},
3543 /*13*/ {SQL_VARCHAR, 0, SQL_NULLABLE, 0}, {SQL_SMALLINT, 0, SQL_NO_NULLS, 0}, {SQL_SMALLINT, 0, SQL_NULLABLE, 0},
3544 /*16*/ {SQL_INTEGER, 0, SQL_NULLABLE, 0}, {SQL_INTEGER, 0, SQL_NO_NULLS, 0}, {SQL_VARCHAR, 0, SQL_NULLABLE, 0}};
3545
3546 /* {{{ MADB_StmtColumns */
3547 SQLRETURN MADB_StmtColumns(MADB_Stmt *Stmt,
3548 char *CatalogName, SQLSMALLINT NameLength1,
3549 char *SchemaName, SQLSMALLINT NameLength2,
3550 char *TableName, SQLSMALLINT NameLength3,
3551 char *ColumnName, SQLSMALLINT NameLength4)
3552 {
3553 MADB_DynString StmtStr;
3554 SQLRETURN ret;
3555 size_t Length= strlen(MADB_CATALOG_COLUMNSp3);
3556 char *ColumnsPart= MADB_CALLOC(Length);
3557 unsigned int OctetsPerChar= Stmt->Connection->Charset.cs_info->char_maxlen > 0 && Stmt->Connection->Charset.cs_info->char_maxlen < 10 ? Stmt->Connection->Charset.cs_info->char_maxlen : 1;
3558
3559 MDBUG_C_ENTER(Stmt->Connection, "StmtColumns");
3560
3561 if (ColumnsPart == NULL)
3562 {
3563 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
3564 }
3565
3566 _snprintf(ColumnsPart, Length, MADB_CATALOG_COLUMNSp3, OctetsPerChar);
3567
3568 MADB_InitDynamicString(&StmtStr, "", 8192, 1024);
3569
3570 MADB_CLEAR_ERROR(&Stmt->Error);
3571 if (MADB_DynstrAppend(&StmtStr, MADB_CATALOG_COLUMNSp1))
3572 goto dynerror;
3573 if (MADB_DynstrAppend(&StmtStr, MADB_SQL_DATATYPE(Stmt)))
3574 goto dynerror;
3575 if (MADB_DynstrAppend(&StmtStr, ColumnsPart))
3576 goto dynerror;
3577 if (MADB_DynstrAppend(&StmtStr, MADB_DEFAULT_COLUMN(Stmt->Connection)))
3578 goto dynerror;
3579
3580 if (MADB_DynstrAppend(&StmtStr, MADB_CATALOG_COLUMNSp4))
3581 goto dynerror;
3582
3583 ADJUST_LENGTH(CatalogName, NameLength1);
3584 ADJUST_LENGTH(SchemaName, NameLength2);
3585 ADJUST_LENGTH(TableName, NameLength3);
3586 ADJUST_LENGTH(ColumnName, NameLength4);
3587
3588 if(MADB_DynstrAppend(&StmtStr, "TABLE_SCHEMA = "))
3589 goto dynerror;
3590
3591 if (CatalogName)
3592 {
3593 if (MADB_DynstrAppend(&StmtStr, "'") ||
3594 MADB_DynstrAppendMem(&StmtStr, CatalogName, NameLength1) ||
3595 MADB_DynstrAppend(&StmtStr, "' "))
3596 goto dynerror;
3597 }
3598 else
3599 if (MADB_DynstrAppend(&StmtStr, "DATABASE()"))
3600 goto dynerror;
3601
3602 if (TableName && NameLength3)
3603 if (MADB_DynstrAppend(&StmtStr, "AND TABLE_NAME LIKE '") ||
3604 MADB_DynstrAppendMem(&StmtStr, TableName, NameLength3) ||
3605 MADB_DynstrAppend(&StmtStr, "' "))
3606 goto dynerror;
3607
3608 if (ColumnName && NameLength4)
3609 if (MADB_DynstrAppend(&StmtStr, "AND COLUMN_NAME LIKE '") ||
3610 MADB_DynstrAppendMem(&StmtStr, ColumnName, NameLength4) ||
3611 MADB_DynstrAppend(&StmtStr, "' "))
3612 goto dynerror;
3613
3614 if (MADB_DynstrAppend(&StmtStr, " ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION"))
3615 goto dynerror;
3616
3617 MDBUG_C_DUMP(Stmt->Connection, StmtStr.str, s);
3618
3619 ret= Stmt->Methods->ExecDirect(Stmt, StmtStr.str, SQL_NTS);
3620
3621 if (SQL_SUCCEEDED(ret))
3622 {
3623 MADB_FixColumnDataTypes(Stmt, SqlColumnsColType);
3624 }
3625
3626 MADB_FREE(ColumnsPart);
3627 MADB_DynstrFree(&StmtStr);
3628 MDBUG_C_DUMP(Stmt->Connection, ret, d);
3629
3630 return ret;
3631
3632 dynerror:
3633 MADB_FREE(ColumnsPart);
3634 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
3635 return Stmt->Error.ReturnValue;
3636 }
3637 /* }}} */
3638
3639 /* {{{ MADB_StmtProcedureColumns */
3640 SQLRETURN MADB_StmtProcedureColumns(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
3641 char *SchemaName, SQLSMALLINT NameLength2, char *ProcName,
3642 SQLSMALLINT NameLength3, char *ColumnName, SQLSMALLINT NameLength4)
3643 {
3644 char *StmtStr,
3645 *p;
3646 size_t Length= strlen(MADB_PROCEDURE_COLUMNS(Stmt)) + 1024;
3647 SQLRETURN ret;
3648 unsigned int OctetsPerChar= Stmt->Connection->Charset.cs_info->char_maxlen > 0 ? Stmt->Connection->Charset.cs_info->char_maxlen: 1;
3649
3650 MADB_CLEAR_ERROR(&Stmt->Error);
3651
3652 if (!(StmtStr= MADB_CALLOC(Length)))
3653 {
3654 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
3655 }
3656
3657 p= StmtStr;
3658
3659 p+= _snprintf(p, Length, MADB_PROCEDURE_COLUMNS(Stmt), OctetsPerChar);
3660
3661 if (CatalogName)
3662 p+= _snprintf(p, Length - strlen(StmtStr), "WHERE SPECIFIC_SCHEMA='%s' ", CatalogName);
3663 else
3664 p+= _snprintf(p, Length - strlen(StmtStr), "WHERE SPECIFIC_SCHEMA LIKE DATABASE() ");
3665 if (ProcName && ProcName[0])
3666 p+= _snprintf(p, Length - strlen(StmtStr), "AND SPECIFIC_NAME LIKE '%s' ", ProcName);
3667 if (ColumnName)
3668 {
3669 if (ColumnName[0])
3670 {
3671 p+= _snprintf(p, Length- strlen(StmtStr), "AND PARAMETER_NAME LIKE '%s' ", ColumnName);
3672 }
3673 else
3674 {
3675 p+= _snprintf(p, Length- strlen(StmtStr), "AND PARAMETER_NAME IS NULL ");
3676 }
3677 }
3678
3679 p+= _snprintf(p, Length - strlen(StmtStr), " ORDER BY SPECIFIC_SCHEMA, SPECIFIC_NAME, ORDINAL_POSITION");
3680
3681 ret= Stmt->Methods->ExecDirect(Stmt, StmtStr, SQL_NTS);
3682
3683 MADB_FREE(StmtStr);
3684
3685 return ret;
3686 }
3687 /* }}} */
3688
3689 /* {{{ MADB_StmtPrimaryKeys */
3690 SQLRETURN MADB_StmtPrimaryKeys(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
3691 char *SchemaName, SQLSMALLINT NameLength2, char *TableName,
3692 SQLSMALLINT NameLength3)
3693 {
3694 char StmtStr[2048],
3695 *p;
3696
3697 MADB_CLEAR_ERROR(&Stmt->Error);
3698
3699 /* TableName is mandatory */
3700 if (!TableName || !NameLength3)
3701 {
3702 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "Tablename is required", 0);
3703 return Stmt->Error.ReturnValue;
3704 }
3705
3706 p= StmtStr;
3707 p+= _snprintf(p, 1024, "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, "
3708 "TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION KEY_SEQ, "
3709 "'PRIMARY' PK_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE "
3710 "COLUMN_KEY = 'pri' AND ");
3711 if (CatalogName && CatalogName[0])
3712 {
3713 p+= _snprintf(p, 2048 - strlen(StmtStr), "TABLE_SCHEMA LIKE '%s' ", CatalogName);
3714 }
3715 else
3716 {
3717 p+= _snprintf(p, 2048 - strlen(StmtStr), "TABLE_SCHEMA LIKE IF(DATABASE() IS NOT NULL, DATABASE(), '%%') ");
3718 }
3719 if (TableName)
3720 {
3721 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND TABLE_NAME LIKE '%s' ", TableName);
3722 }
3723 p+= _snprintf(p, 2048 - strlen(StmtStr), " ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION");
3724
3725 return Stmt->Methods->ExecDirect(Stmt, StmtStr, SQL_NTS);
3726 }
3727 /* }}} */
3728
3729 /* {{{ MADB_StmtSpecialColumns */
3730 SQLRETURN MADB_StmtSpecialColumns(MADB_Stmt *Stmt, SQLUSMALLINT IdentifierType,
3731 char *CatalogName, SQLSMALLINT NameLength1,
3732 char *SchemaName, SQLSMALLINT NameLength2,
3733 char *TableName, SQLSMALLINT NameLength3,
3734 SQLUSMALLINT Scope, SQLUSMALLINT Nullable)
3735 {
3736 char StmtStr[2048],
3737 *p= StmtStr;
3738
3739 MADB_CLEAR_ERROR(&Stmt->Error);
3740
3741 /* TableName is mandatory */
3742 if (!TableName || !NameLength3)
3743 {
3744 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "Tablename is required", 0);
3745 return Stmt->Error.ReturnValue;
3746 }
3747
3748 p+= _snprintf(p, 2048, "SELECT NULL AS SCOPE, COLUMN_NAME, %s,"
3749 "DATA_TYPE TYPE_NAME,"
3750 "CASE"
3751 " WHEN DATA_TYPE in ('bit', 'tinyint', 'smallint', 'year', 'mediumint', 'int',"
3752 "'bigint', 'decimal', 'float', 'double') THEN NUMERIC_PRECISION "
3753 " WHEN DATA_TYPE='date' THEN 10"
3754 " WHEN DATA_TYPE='time' THEN 8"
3755 " WHEN DATA_TYPE in ('timestamp', 'datetime') THEN 19 "
3756 "END AS COLUMN_SIZE,"
3757 "CHARACTER_OCTET_LENGTH AS BUFFER_LENGTH,"
3758 "NUMERIC_SCALE DECIMAL_DIGITS, "
3759 XSTR(SQL_PC_UNKNOWN) " PSEUDO_COLUMN "
3760 "FROM INFORMATION_SCHEMA.COLUMNS WHERE 1 ", MADB_SQL_DATATYPE(Stmt));
3761
3762 if (CatalogName && CatalogName[0])
3763 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND TABLE_SCHEMA LIKE '%s' ", CatalogName);
3764 else
3765 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND TABLE_SCHEMA LIKE IF(DATABASE() IS NOT NULL, DATABASE(), '%%') ");
3766 if (TableName && TableName[0])
3767 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND TABLE_NAME LIKE '%s' ", TableName);
3768
3769 if (Nullable == SQL_NO_NULLS)
3770 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND IS_NULLABLE <> 'YES' ");
3771
3772 if (IdentifierType == SQL_BEST_ROWID)
3773 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND COLUMN_KEY IN ('PRI', 'UNI') ");
3774 else if (IdentifierType == SQL_ROWVER)
3775 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND DATA_TYPE='timestamp' AND EXTRA LIKE '%%CURRENT_TIMESTAMP%%' ");
3776 p+= _snprintf(p, 2048 - strlen(StmtStr), "ORDER BY TABLE_SCHEMA, TABLE_NAME, COLUMN_KEY");
3777
3778 return Stmt->Methods->ExecDirect(Stmt, StmtStr, SQL_NTS);
3779 }
3780 /* }}} */
3781
3782 /* {{{ MADB_StmtProcedures */
3783 SQLRETURN MADB_StmtProcedures(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
3784 char *SchemaName, SQLSMALLINT NameLength2, char *ProcName,
3785 SQLSMALLINT NameLength3)
3786 {
3787 char StmtStr[2048],
3788 *p;
3789
3790 MADB_CLEAR_ERROR(&Stmt->Error);
3791
3792 p= StmtStr;
3793
3794 p+= _snprintf(p, 2048, "SELECT ROUTINE_SCHEMA AS PROCEDURE_CAT, NULL AS PROCEDURE_SCHEM, "
3795 "SPECIFIC_NAME PROCEDURE_NAME, NULL NUM_INPUT_PARAMS, "
3796 "NULL NUM_OUTPUT_PARAMS, NULL NUM_RESULT_SETS, "
3797 "ROUTINE_COMMENT REMARKS, "
3798 "CASE ROUTINE_TYPE "
3799 " WHEN 'FUNCTION' THEN " XSTR(SQL_PT_FUNCTION)
3800 " WHEN 'PROCEDURE' THEN " XSTR(SQL_PT_PROCEDURE)
3801 " ELSE " XSTR(SQL_PT_UNKNOWN) " "
3802 "END PROCEDURE_TYPE "
3803 "FROM INFORMATION_SCHEMA.ROUTINES ");
3804 if (CatalogName && CatalogName[0])
3805 p+= _snprintf(p, 2048 - strlen(StmtStr), "WHERE ROUTINE_SCHEMA LIKE '%s' ", CatalogName);
3806 else
3807 p+= _snprintf(p, 2048 - strlen(StmtStr), "WHERE ROUTINE_SCHEMA LIKE DATABASE() ");
3808 if (ProcName && ProcName[0])
3809 p+= _snprintf(p, 2048 - strlen(StmtStr), "AND SPECIFIC_NAME LIKE '%s' ", ProcName);
3810
3811 p+= _snprintf(p, 2048 - strlen(StmtStr), " ORDER BY ROUTINE_SCHEMA, SPECIFIC_NAME");
3812
3813 return Stmt->Methods->ExecDirect(Stmt, StmtStr, SQL_NTS);
3814 }
3815 /* }}} */
3816
3817 /* {{{ SQLForeignKeys */
3818 SQLRETURN MADB_StmtForeignKeys(MADB_Stmt *Stmt, char *PKCatalogName, SQLSMALLINT NameLength1,
3819 char *PKSchemaName, SQLSMALLINT NameLength2, char *PKTableName,
3820 SQLSMALLINT NameLength3, char *FKCatalogName, SQLSMALLINT NameLength4,
3821 char *FKSchemaName, SQLSMALLINT NameLength5, char *FKTableName,
3822 SQLSMALLINT NameLength6)
3823 {
3824 SQLRETURN ret= SQL_ERROR;
3825 MADB_DynString StmtStr;
3826 char EscapeBuf[256];
3827
3828 MADB_CLEAR_ERROR(&Stmt->Error);
3829
3830 ADJUST_LENGTH(PKCatalogName, NameLength1);
3831 ADJUST_LENGTH(PKSchemaName, NameLength2);
3832 ADJUST_LENGTH(PKTableName, NameLength3);
3833 ADJUST_LENGTH(FKCatalogName, NameLength4);
3834 ADJUST_LENGTH(FKSchemaName, NameLength5);
3835 ADJUST_LENGTH(FKTableName, NameLength6);
3836
3837
3838
3839 /* PKTableName and FKTableName are mandatory */
3840 if ((!PKTableName || !NameLength3) && (!FKTableName || !NameLength6))
3841 {
3842 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "PKTableName or FKTableName are required", 0);
3843 return Stmt->Error.ReturnValue;
3844 }
3845
3846 /* modified from JDBC driver */
3847 MADB_InitDynamicString(&StmtStr,
3848 "SELECT A.REFERENCED_TABLE_SCHEMA PKTABLE_CAT, NULL PKTABLE_SCHEM, "
3849 "A.REFERENCED_TABLE_NAME PKTABLE_NAME, "
3850 "A.REFERENCED_COLUMN_NAME PKCOLUMN_NAME, "
3851 "A.TABLE_SCHEMA FKTABLE_CAT, NULL FKTABLE_SCHEM, "
3852 "A.TABLE_NAME FKTABLE_NAME, A.COLUMN_NAME FKCOLUMN_NAME, "
3853 "A.POSITION_IN_UNIQUE_CONSTRAINT KEY_SEQ, "
3854 "CASE update_rule "
3855 " WHEN 'RESTRICT' THEN " XSTR(SQL_RESTRICT)
3856 " WHEN 'NO ACTION' THEN " XSTR(SQL_NO_ACTION)
3857 " WHEN 'CASCADE' THEN " XSTR(SQL_CASCADE)
3858 " WHEN 'SET NULL' THEN " XSTR(SQL_SET_NULL)
3859 " WHEN 'SET DEFAULT' THEN " XSTR(SQL_SET_DEFAULT) " "
3860 "END UPDATE_RULE, "
3861 "CASE DELETE_RULE"
3862 " WHEN 'RESTRICT' THEN " XSTR(SQL_RESTRICT)
3863 " WHEN 'NO ACTION' THEN " XSTR(SQL_NO_ACTION)
3864 " WHEN 'CASCADE' THEN " XSTR(SQL_CASCADE)
3865 " WHEN 'SET NULL' THEN " XSTR(SQL_SET_NULL)
3866 " WHEN 'SET DEFAULT' THEN " XSTR(SQL_SET_DEFAULT) " "
3867 " END DELETE_RULE,"
3868 "A.CONSTRAINT_NAME FK_NAME, "
3869 "'PRIMARY' PK_NAME,"
3870 XSTR(SQL_NOT_DEFERRABLE) " AS DEFERRABILITY "
3871 " FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE A"
3872 " JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE B"
3873 " ON (B.TABLE_SCHEMA = A.REFERENCED_TABLE_SCHEMA"
3874 " AND B.TABLE_NAME = A.REFERENCED_TABLE_NAME"
3875 " AND B.COLUMN_NAME = A.REFERENCED_COLUMN_NAME)"
3876 " JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC"
3877 " ON (RC.CONSTRAINT_NAME = A.CONSTRAINT_NAME"
3878 " AND RC.TABLE_NAME = A.TABLE_NAME"
3879 " AND RC.CONSTRAINT_SCHEMA = A.TABLE_SCHEMA)"
3880 " WHERE B.CONSTRAINT_NAME= 'PRIMARY'",
3881 8192, 128);
3882
3883 if (PKTableName && PKTableName[0])
3884 {
3885 MADB_DynstrAppend(&StmtStr, " AND A.REFERENCED_TABLE_SCHEMA ");
3886
3887 if (PKCatalogName && PKCatalogName[0])
3888 {
3889 MADB_DynstrAppend(&StmtStr, "LIKE '");
3890 mysql_real_escape_string(Stmt->Connection->mariadb, EscapeBuf, PKCatalogName, MIN(NameLength1, 255));
3891 MADB_DynstrAppend(&StmtStr, EscapeBuf);
3892 MADB_DynstrAppend(&StmtStr, "' ");
3893 }
3894 else
3895 MADB_DynstrAppend(&StmtStr, "= DATABASE()");
3896 MADB_DynstrAppend(&StmtStr, " AND A.REFERENCED_TABLE_NAME = '");
3897
3898 mysql_real_escape_string(Stmt->Connection->mariadb, EscapeBuf, PKTableName, MIN(255, NameLength3));
3899 MADB_DynstrAppend(&StmtStr, EscapeBuf);
3900 MADB_DynstrAppend(&StmtStr, "' ");
3901 }
3902
3903 if (FKTableName && FKTableName[0])
3904 {
3905 MADB_DynstrAppend(&StmtStr, " AND A.TABLE_SCHEMA = ");
3906
3907 if (FKCatalogName && FKCatalogName[0])
3908 {
3909 MADB_DynstrAppend(&StmtStr, "'");
3910 mysql_real_escape_string(Stmt->Connection->mariadb, EscapeBuf, FKCatalogName, MIN(NameLength4, 255));
3911 MADB_DynstrAppend(&StmtStr, EscapeBuf);
3912 MADB_DynstrAppend(&StmtStr, "' ");
3913 }
3914 else
3915 MADB_DynstrAppend(&StmtStr, "DATABASE() ");
3916 MADB_DynstrAppend(&StmtStr, " AND A.TABLE_NAME = '");
3917
3918 mysql_real_escape_string(Stmt->Connection->mariadb, EscapeBuf, FKTableName, MIN(255, NameLength6));
3919 MADB_DynstrAppend(&StmtStr, EscapeBuf);
3920 MADB_DynstrAppend(&StmtStr, "' ");
3921 }
3922 MADB_DynstrAppend(&StmtStr, "ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, KEY_SEQ, PKTABLE_NAME");
3923
3924 ret= Stmt->Methods->ExecDirect(Stmt, StmtStr.str, SQL_NTS);
3925
3926 MADB_DynstrFree(&StmtStr);
3927
3928 return ret;
3929 }
3930 /* }}} */
3931
3932 /* {{{ MADB_StmtDescribeCol */
3933 SQLRETURN MADB_StmtDescribeCol(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, void *ColumnName,
3934 SQLSMALLINT BufferLength, SQLSMALLINT *NameLengthPtr,
3935 SQLSMALLINT *DataTypePtr, SQLULEN *ColumnSizePtr, SQLSMALLINT *DecimalDigitsPtr,
3936 SQLSMALLINT *NullablePtr, my_bool isWChar)
3937 {
3938 MADB_DescRecord *Record;
3939
3940 MADB_CLEAR_ERROR(&Stmt->Error);
3941
3942 if (!mysql_stmt_field_count(Stmt->stmt))
3943 {
3944 MADB_SetError(&Stmt->Error, MADB_ERR_07005, NULL, 0);
3945 return Stmt->Error.ReturnValue;
3946 }
3947
3948 if (ColumnNumber < 1 || ColumnNumber > mysql_stmt_field_count(Stmt->stmt))
3949 {
3950 MADB_SetError(&Stmt->Error, MADB_ERR_07009, NULL, 0);
3951 return SQL_ERROR;
3952 }
3953 if (!(Record= MADB_DescGetInternalRecord(Stmt->Ird, ColumnNumber - 1, MADB_DESC_WRITE)))
3954 {
3955 MADB_CopyError(&Stmt->Error, &Stmt->Ird->Error);
3956 return Stmt->Error.ReturnValue;
3957 }
3958 if (NameLengthPtr)
3959 *NameLengthPtr= 0;
3960
3961 /* Don't map types if ansi mode was set */
3962 if (DataTypePtr)
3963 *DataTypePtr= (isWChar && !Stmt->Connection->IsAnsi) ? MADB_GetWCharType(Record->ConciseType) : Record->ConciseType;
3964 /* Columnsize in characters, not bytes! */
3965 if (ColumnSizePtr)
3966 *ColumnSizePtr= Record->Length;
3967 //Record->Precision ? MIN(Record->DisplaySize, Record->Precision) : Record->DisplaySize;
3968 if (DecimalDigitsPtr)
3969 *DecimalDigitsPtr= Record->Scale;
3970 if (NullablePtr)
3971 *NullablePtr= Record->Nullable;
3972
3973 if ((ColumnName || BufferLength) && Record->ColumnName)
3974 {
3975 size_t Length= MADB_SetString(isWChar ? &Stmt->Connection->Charset : 0, ColumnName, ColumnName ? BufferLength : 0, Record->ColumnName, SQL_NTS, &Stmt->Error);
3976 if (NameLengthPtr)
3977 *NameLengthPtr= (SQLSMALLINT)Length;
3978 if (!BufferLength)
3979 MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
3980 }
3981 return Stmt->Error.ReturnValue;
3982 }
3983 /* }}} */
3984
3985 /* {{{ MADB_SetCursorName */
3986 SQLRETURN MADB_SetCursorName(MADB_Stmt *Stmt, char *Buffer, SQLINTEGER BufferLength)
3987 {
3988 MADB_List *LStmt, *LStmtNext;
3989 if (!Buffer)
3990 {
3991 MADB_SetError(&Stmt->Error, MADB_ERR_HY009, NULL, 0);
3992 return SQL_ERROR;
3993 }
3994 if (BufferLength== SQL_NTS)
3995 BufferLength= (SQLINTEGER)strlen(Buffer);
3996 if (BufferLength < 0)
3997 {
3998 MADB_SetError(&Stmt->Error, MADB_ERR_HY090, NULL, 0);
3999 return SQL_ERROR;
4000 }
4001 if ((BufferLength > 5 && strncmp(Buffer, "SQLCUR", 6) == 0) ||
4002 (BufferLength > 6 && strncmp(Buffer, "SQL_CUR", 7) == 0))
4003 {
4004 MADB_SetError(&Stmt->Error, MADB_ERR_34000, NULL, 0);
4005 return SQL_ERROR;
4006 }
4007 /* check if cursor name is unique */
4008 for (LStmt= Stmt->Connection->Stmts; LStmt; LStmt= LStmtNext)
4009 {
4010 MADB_Cursor *Cursor= &((MADB_Stmt *)LStmt->data)->Cursor;
4011 LStmtNext= LStmt->next;
4012
4013 if (Stmt != (MADB_Stmt *)LStmt->data &&
4014 Cursor->Name && strncmp(Cursor->Name, Buffer, BufferLength) == 0)
4015 {
4016 MADB_SetError(&Stmt->Error, MADB_ERR_3C000, NULL, 0);
4017 return SQL_ERROR;
4018 }
4019 }
4020 MADB_FREE(Stmt->Cursor.Name);
4021 Stmt->Cursor.Name= MADB_CALLOC(BufferLength + 1);
4022 MADB_SetString(0, Stmt->Cursor.Name, BufferLength + 1, Buffer, BufferLength, NULL);
4023 return SQL_SUCCESS;
4024 }
4025 /* }}} */
4026
4027 /* {{{ MADB_GetCursorName */
4028 SQLRETURN MADB_GetCursorName(MADB_Stmt *Stmt, void *CursorName, SQLSMALLINT BufferLength,
4029 SQLSMALLINT *NameLengthPtr, my_bool isWChar)
4030 {
4031 SQLSMALLINT Length;
4032 MADB_CLEAR_ERROR(&Stmt->Error);
4033
4034 if (BufferLength < 0)
4035 {
4036 MADB_SetError(&Stmt->Error, MADB_ERR_HY090, NULL, 0);
4037 return Stmt->Error.ReturnValue;
4038 }
4039 if (!Stmt->Cursor.Name)
4040 {
4041 Stmt->Cursor.Name= (char *)MADB_CALLOC(MADB_MAX_CURSOR_NAME);
4042 _snprintf(Stmt->Cursor.Name, MADB_MAX_CURSOR_NAME, "SQL_CUR%d",
4043 Stmt->Connection->CursorCount++);
4044 }
4045 Length= (SQLSMALLINT)MADB_SetString(isWChar ? &Stmt->Connection->Charset : 0, CursorName,
4046 BufferLength, Stmt->Cursor.Name, SQL_NTS, &Stmt->Error);
4047 if (NameLengthPtr)
4048 *NameLengthPtr= (SQLSMALLINT)Length;
4049 if (!BufferLength)
4050 MADB_SetError(&Stmt->Error, MADB_ERR_01004, NULL, 0);
4051
4052 return Stmt->Error.ReturnValue;
4053
4054 }
4055 /* }}} */
4056
4057 SQLRETURN MADB_RefreshRowPtrs(MADB_Stmt *Stmt)
4058 {
4059 SQLRETURN result= SQL_SUCCESS;
4060
4061 if (Stmt->result != NULL)
4062 {
4063 unsigned int i;
4064 char *saved_flag;
4065
4066 saved_flag= (char*)MADB_CALLOC(mysql_stmt_field_count(Stmt->stmt));
4067
4068 if (saved_flag == NULL)
4069 {
4070 return SQL_ERROR;
4071 }
4072
4073 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
4074 {
4075 saved_flag[i]= Stmt->stmt->bind[i].flags & MADB_BIND_DUMMY;
4076
4077 Stmt->stmt->bind[i].flags|= MADB_BIND_DUMMY;
4078 }
4079
4080 if (mysql_stmt_fetch(Stmt->stmt) == 1)
4081 {
4082 result= SQL_ERROR;
4083 }
4084
4085 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
4086 {
4087 Stmt->stmt->bind[i].flags &= (~MADB_BIND_DUMMY | saved_flag[i]);
4088 }
4089
4090 MADB_FREE(saved_flag);
4091 }
4092
4093 return result;
4094 }
4095
4096 /* {{{ MADB_RefreshDynamicCursor */
4097 SQLRETURN MADB_RefreshDynamicCursor(MADB_Stmt *Stmt)
4098 {
4099 SQLRETURN ret;
4100 SQLLEN CurrentRow= Stmt->Cursor.Position;
4101 long long AffectedRows= Stmt->AffectedRows;
4102 SQLLEN LastRowFetched= Stmt->LastRowFetched;
4103
4104 ret= Stmt->Methods->Execute(Stmt, FALSE);
4105
4106 Stmt->Cursor.Position= CurrentRow;
4107 if (Stmt->Cursor.Position > 0 && (my_ulonglong)Stmt->Cursor.Position >= mysql_stmt_num_rows(Stmt->stmt))
4108 {
4109 Stmt->Cursor.Position= (long)mysql_stmt_num_rows(Stmt->stmt) - 1;
4110 }
4111
4112 Stmt->LastRowFetched= LastRowFetched;
4113 Stmt->AffectedRows= AffectedRows;
4114
4115 if (Stmt->Cursor.Position > 0)
4116 {
4117 /* Looks likt this is not needed altogether. Leaving it commented out, so far */
4118 /*MADB_StmtDataSeek(Stmt, Stmt->Cursor.Position);
4119 if (SQL_SUCCEEDED(ret))
4120 {*/
4121 /* We need to prevent that bound variables will be overwritten
4122 by fetching data again: For subsequent GetData we need to update
4123 bind->row_ptr */
4124 /*Stmt->Methods->RefreshRowPtrs(Stmt);
4125
4126 MADB_StmtDataSeek(Stmt, Stmt->Cursor.Position);
4127 }*/
4128 }
4129 else
4130 {
4131 Stmt->Cursor.Position= 0;
4132 }
4133 return ret;
4134 }
4135 /* }}} */
4136
4137 /* Couple of macsros for this function specifically */
4138 #define MADB_SETPOS_FIRSTROW(agg_result) (agg_result == SQL_INVALID_HANDLE)
4139 #define MADB_SETPOS_AGG_RESULT(agg_result, row_result) if (MADB_SETPOS_FIRSTROW(agg_result)) agg_result= row_result; \
4140 else if (row_result != agg_result) agg_result= SQL_SUCCESS_WITH_INFO
4141
4142 /* {{{ MADB_SetPos */
4143 SQLRETURN MADB_StmtSetPos(MADB_Stmt *Stmt, SQLSETPOSIROW RowNumber, SQLUSMALLINT Operation,
4144 SQLUSMALLINT LockType, int ArrayOffset)
4145 {
4146 if (!Stmt->result && !Stmt->stmt->fields)
4147 {
4148 MADB_SetError(&Stmt->Error, MADB_ERR_24000, NULL, 0);
4149 return Stmt->Error.ReturnValue;
4150 }
4151 /* skip this for now, since we don't use unbuffered result sets
4152 if (Stmt->Options.CursorType == SQL_CURSOR_FORWARD_ONLY)
4153 {
4154 MADB_SetError(&Stmt->Error, MADB_ERR_24000, NULL, 0);
4155 return Stmt->Error.ReturnValue;
4156 }
4157 */
4158 if (LockType != SQL_LOCK_NO_CHANGE)
4159 {
4160 MADB_SetError(&Stmt->Error, MADB_ERR_HYC00, NULL, 0);
4161 return Stmt->Error.ReturnValue;
4162 }
4163 switch(Operation) {
4164 case SQL_POSITION:
4165 {
4166 if (RowNumber < 1 || RowNumber > mysql_stmt_num_rows(Stmt->stmt))
4167 {
4168 MADB_SetError(&Stmt->Error, MADB_ERR_HY109, NULL, 0);
4169 return Stmt->Error.ReturnValue;
4170 }
4171 if (Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4172 if (!SQL_SUCCEEDED(Stmt->Methods->RefreshDynamicCursor(Stmt)))
4173 return Stmt->Error.ReturnValue;
4174 EnterCriticalSection(&Stmt->Connection->cs);
4175 Stmt->Cursor.Position+=(RowNumber - 1);
4176 MADB_StmtDataSeek(Stmt, Stmt->Cursor.Position);
4177 LeaveCriticalSection(&Stmt->Connection->cs);
4178 }
4179 break;
4180 case SQL_ADD:
4181 {
4182 MADB_DynString DynStmt;
4183 SQLRETURN ret;
4184 char *TableName= MADB_GetTableName(Stmt);
4185 char *CatalogName= MADB_GetCatalogName(Stmt);
4186 int column, param= 0;
4187
4188 if (Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4189 if (!SQL_SUCCEEDED(Stmt->Methods->RefreshDynamicCursor(Stmt)))
4190 return Stmt->Error.ReturnValue;
4191
4192 Stmt->DaeRowNumber= RowNumber;
4193
4194 if (Stmt->DataExecutionType != MADB_DAE_ADD)
4195 {
4196 Stmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
4197 MA_SQLAllocHandle(SQL_HANDLE_STMT, Stmt->Connection, (SQLHANDLE *)&Stmt->DaeStmt);
4198
4199 if (MADB_InitDynamicString(&DynStmt, "INSERT INTO ", 8192, 1024) ||
4200 MADB_DynStrAppendQuoted(&DynStmt, CatalogName) ||
4201 MADB_DynstrAppend(&DynStmt, ".") ||
4202 MADB_DynStrAppendQuoted(&DynStmt, TableName)||
4203 MADB_DynStrInsertSet(Stmt, &DynStmt))
4204 {
4205 MADB_DynstrFree(&DynStmt);
4206 return Stmt->Error.ReturnValue;
4207 }
4208
4209 ResetMetadata(&Stmt->DaeStmt->DefaultsResult, MADB_GetDefaultColumnValues(Stmt, Stmt->stmt->fields));
4210
4211 Stmt->DataExecutionType= MADB_DAE_ADD;
4212 ret= Stmt->Methods->Prepare(Stmt->DaeStmt, DynStmt.str, SQL_NTS, FALSE);
4213
4214 MADB_DynstrFree(&DynStmt);
4215
4216 if (!SQL_SUCCEEDED(ret))
4217 {
4218 MADB_CopyError(&Stmt->Error, &Stmt->DaeStmt->Error);
4219 Stmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
4220 return Stmt->Error.ReturnValue;
4221 }
4222 }
4223
4224 /* Bind parameters - DaeStmt will process whole array of values, thus we don't need to iterate through the array*/
4225 for (column= 0; column < MADB_STMT_COLUMN_COUNT(Stmt); ++column)
4226 {
4227 MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Stmt->Ard, column, MADB_DESC_READ),
4228 *ApdRec= NULL;
4229
4230 if (Rec->inUse && MADB_ColumnIgnoredInAllRows(Stmt->Ard, Rec) == FALSE)
4231 {
4232 Stmt->DaeStmt->Methods->BindParam(Stmt->DaeStmt, param + 1, SQL_PARAM_INPUT, Rec->ConciseType, Rec->Type,
4233 Rec->DisplaySize, Rec->Scale, Rec->DataPtr, Rec->OctetLength, Rec->OctetLengthPtr);
4234 }
4235 else
4236 {
4237 /*Stmt->DaeStmt->Methods->BindParam(Stmt->DaeStmt, param + 1, SQL_PARAM_INPUT, SQL_CHAR, SQL_C_CHAR, 0, 0,
4238 ApdRec->DefaultValue, strlen(ApdRec->DefaultValue), NULL);*/
4239 continue;
4240 }
4241
4242 ApdRec= MADB_DescGetInternalRecord(Stmt->DaeStmt->Apd, param, MADB_DESC_READ);
4243 ApdRec->DefaultValue= MADB_GetDefaultColumnValue(Stmt->DaeStmt->DefaultsResult,
4244 Stmt->stmt->fields[column].org_name);
4245
4246 ++param;
4247 }
4248
4249 memcpy(&Stmt->DaeStmt->Apd->Header, &Stmt->Ard->Header, sizeof(MADB_Header));
4250 ret= Stmt->Methods->Execute(Stmt->DaeStmt, FALSE);
4251
4252 if (!SQL_SUCCEEDED(ret))
4253 {
4254 /* We can have SQL_NEED_DATA here, which would not set error (and its ReturnValue) */
4255 MADB_CopyError(&Stmt->Error, &Stmt->DaeStmt->Error);
4256 return ret;
4257 }
4258 if (Stmt->AffectedRows == -1)
4259 {
4260 Stmt->AffectedRows= 0;
4261 }
4262 Stmt->AffectedRows+= Stmt->DaeStmt->AffectedRows;
4263
4264 Stmt->DataExecutionType= MADB_DAE_NORMAL;
4265 Stmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
4266 Stmt->DaeStmt= NULL;
4267 }
4268 break;
4269 case SQL_UPDATE:
4270 {
4271 char *TableName= MADB_GetTableName(Stmt);
4272 my_ulonglong Start= 0,
4273 End= mysql_stmt_num_rows(Stmt->stmt);
4274 SQLRETURN result= SQL_INVALID_HANDLE; /* Just smth we cannot normally get */
4275
4276 if (!TableName)
4277 {
4278 MADB_SetError(&Stmt->Error, MADB_ERR_IM001, "Updatable Cursors with multiple tables are not supported", 0);
4279 return Stmt->Error.ReturnValue;
4280 }
4281
4282 Stmt->AffectedRows= 0;
4283
4284 if ((SQLLEN)RowNumber > Stmt->LastRowFetched)
4285 {
4286 MADB_SetError(&Stmt->Error, MADB_ERR_S1107, NULL, 0);
4287 return Stmt->Error.ReturnValue;
4288 }
4289
4290 if (RowNumber < 0 || RowNumber > End)
4291 {
4292 MADB_SetError(&Stmt->Error, MADB_ERR_HY109, NULL, 0);
4293 return Stmt->Error.ReturnValue;
4294 }
4295
4296 if (Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4297 if (!SQL_SUCCEEDED(Stmt->Methods->RefreshDynamicCursor(Stmt)))
4298 return Stmt->Error.ReturnValue;
4299
4300 Stmt->DaeRowNumber= MAX(1,RowNumber);
4301
4302 /* Cursor is open, but no row was fetched, so we simulate
4303 that first row was fetched */
4304 if (Stmt->Cursor.Position < 0)
4305 Stmt->Cursor.Position= 1;
4306
4307 if (RowNumber)
4308 Start= End= Stmt->Cursor.Position + RowNumber -1;
4309 else
4310 {
4311 Start= Stmt->Cursor.Position;
4312 /* TODO: if num_rows returns 1, End is 0? Start would be 1, no */
4313 End= MIN(mysql_stmt_num_rows(Stmt->stmt)-1, Start + Stmt->Ard->Header.ArraySize - 1);
4314 }
4315 /* Stmt->ArrayOffset will be incremented in StmtExecute() */
4316 Start+= Stmt->ArrayOffset;
4317
4318 /* TODO: SQL_ATTR_ROW_STATUS_PTR should be filled */
4319 while (Start <= End)
4320 {
4321 SQLSMALLINT param= 0, column;
4322 MADB_StmtDataSeek(Stmt,Start);
4323 Stmt->Methods->RefreshRowPtrs(Stmt);
4324
4325 /* We don't need to prepare the statement, if SetPos was called
4326 from SQLParamData() function */
4327 if (!ArrayOffset)
4328 {
4329 if (!SQL_SUCCEEDED(MADB_DaeStmt(Stmt, SQL_UPDATE)))
4330 {
4331 MADB_SETPOS_AGG_RESULT(result, Stmt->Error.ReturnValue);
4332 /* Moving to the next row */
4333 Stmt->DaeRowNumber++;
4334 Start++;
4335
4336 continue;
4337 }
4338
4339 for(column= 0; column < MADB_STMT_COLUMN_COUNT(Stmt); ++column)
4340 {
4341 SQLLEN *LengthPtr= NULL;
4342 my_bool GetDefault= FALSE;
4343 MADB_DescRecord *Rec= MADB_DescGetInternalRecord(Stmt->Ard, column, MADB_DESC_READ);
4344
4345 /* TODO: shouldn't here be IndicatorPtr? */
4346 if (Rec->OctetLengthPtr)
4347 LengthPtr= GetBindOffset(Stmt->Ard, Rec, Rec->OctetLengthPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber - 1 : 0, sizeof(SQLLEN)/*Rec->OctetLength*/);
4348 if (!Rec->inUse ||
4349 (LengthPtr && *LengthPtr == SQL_COLUMN_IGNORE))
4350 {
4351 GetDefault= TRUE;
4352 continue;
4353 }
4354
4355 /* TODO: Looks like this whole thing is not really needed. Not quite clear if !InUse should result in going this way */
4356 if (GetDefault)
4357 {
4358 SQLLEN Length= 0;
4359 /* set a default value */
4360 if (Stmt->Methods->GetData(Stmt, column + 1, SQL_C_CHAR, NULL, 0, &Length, TRUE) != SQL_ERROR && Length)
4361 {
4362 MADB_FREE(Rec->DefaultValue);
4363 if (Length > 0)
4364 {
4365 Rec->DefaultValue= (char *)MADB_CALLOC(Length + 1);
4366 Stmt->Methods->GetData(Stmt, column + 1, SQL_C_CHAR, Rec->DefaultValue, Length+1, 0, TRUE);
4367 }
4368 Stmt->DaeStmt->Methods->BindParam(Stmt->DaeStmt, param + 1, SQL_PARAM_INPUT, SQL_CHAR, SQL_C_CHAR, 0, 0,
4369 Rec->DefaultValue, Length, NULL);
4370 ++param;
4371 continue;
4372 }
4373 }
4374
4375 if (!GetDefault)
4376 {
4377 Stmt->DaeStmt->Methods->BindParam(Stmt->DaeStmt, param + 1, SQL_PARAM_INPUT, Rec->ConciseType, Rec->Type,
4378 Rec->DisplaySize, Rec->Scale,
4379 GetBindOffset(Stmt->Ard, Rec, Rec->DataPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber -1 : 0, Rec->OctetLength),
4380 Rec->OctetLength, LengthPtr);
4381 }
4382 if (PARAM_IS_DAE(LengthPtr) && !DAE_DONE(Stmt->DaeStmt))
4383 {
4384 Stmt->Status= SQL_NEED_DATA;
4385 ++param;
4386 continue;
4387 }
4388
4389 ++param;
4390 } /* End of for(column=0;...) */
4391 if (Stmt->Status == SQL_NEED_DATA)
4392 return SQL_NEED_DATA;
4393 } /* End of if (!ArrayOffset) */
4394
4395 if (Stmt->DaeStmt->Methods->Execute(Stmt->DaeStmt, FALSE) != SQL_ERROR)
4396 {
4397 Stmt->AffectedRows+= Stmt->DaeStmt->AffectedRows;
4398 }
4399 else
4400 {
4401 MADB_CopyError(&Stmt->Error, &Stmt->DaeStmt->Error);
4402 }
4403
4404 MADB_SETPOS_AGG_RESULT(result, Stmt->DaeStmt->Error.ReturnValue);
4405
4406 Stmt->DaeRowNumber++;
4407 Start++;
4408 } /* End of while (Start <= End) */
4409
4410 Stmt->Methods->StmtFree(Stmt->DaeStmt, SQL_DROP);
4411 Stmt->DaeStmt= NULL;
4412 Stmt->DataExecutionType= MADB_DAE_NORMAL;
4413
4414 /* Making sure we do not return initial value */
4415 return result == SQL_INVALID_HANDLE ? SQL_SUCCESS :result;
4416 }
4417 case SQL_DELETE:
4418 {
4419 MADB_DynString DynamicStmt;
4420 SQLULEN SaveArraySize= Stmt->Ard->Header.ArraySize;
4421 my_ulonglong Start= 0,
4422 End= mysql_stmt_num_rows(Stmt->stmt);
4423 char *TableName= MADB_GetTableName(Stmt);
4424
4425 if (!TableName)
4426 {
4427 MADB_SetError(&Stmt->Error, MADB_ERR_IM001, "Updatable Cursors with multiple tables are not supported", 0);
4428 return Stmt->Error.ReturnValue;
4429 }
4430
4431 Stmt->Ard->Header.ArraySize= 1;
4432 if (Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4433 if (!SQL_SUCCEEDED(Stmt->Methods->RefreshDynamicCursor(Stmt)))
4434 return Stmt->Error.ReturnValue;
4435 Stmt->AffectedRows= 0;
4436 if (RowNumber < 0 || RowNumber > End)
4437 {
4438 MADB_SetError(&Stmt->Error, MADB_ERR_HY109, NULL, 0);
4439 return Stmt->Error.ReturnValue;
4440 }
4441 Start= (RowNumber) ? Stmt->Cursor.Position + RowNumber - 1 : Stmt->Cursor.Position;
4442 if (SaveArraySize && !RowNumber)
4443 End= MIN(End, Start + SaveArraySize - 1);
4444 else
4445 End= Start;
4446
4447 while (Start <= End)
4448 {
4449 MADB_StmtDataSeek(Stmt, Start);
4450 Stmt->Methods->RefreshRowPtrs(Stmt);
4451 MADB_InitDynamicString(&DynamicStmt, "DELETE FROM ", 8192, 1024);
4452 if (MADB_DynStrAppendQuoted(&DynamicStmt, TableName) ||
4453 MADB_DynStrGetWhere(Stmt, &DynamicStmt, TableName, FALSE))
4454 {
4455 MADB_DynstrFree(&DynamicStmt);
4456 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
4457
4458 return Stmt->Error.ReturnValue;
4459 }
4460
4461 LOCK_MARIADB(Stmt->Connection);
4462 if (mysql_real_query(Stmt->Connection->mariadb, DynamicStmt.str, (unsigned long)DynamicStmt.length))
4463 {
4464 MADB_DynstrFree(&DynamicStmt);
4465 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, mysql_error(Stmt->Connection->mariadb),
4466 mysql_errno(Stmt->Connection->mariadb));
4467
4468 UNLOCK_MARIADB(Stmt->Connection);
4469
4470 return Stmt->Error.ReturnValue;
4471 }
4472 MADB_DynstrFree(&DynamicStmt);
4473 Stmt->AffectedRows+= mysql_affected_rows(Stmt->Connection->mariadb);
4474 Start++;
4475 }
4476 UNLOCK_MARIADB(Stmt->Connection);
4477
4478 Stmt->Ard->Header.ArraySize= SaveArraySize;
4479 /* if we have a dynamic cursor we need to adjust the rowset size */
4480 if (Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4481 Stmt->LastRowFetched-= (unsigned long)Stmt->AffectedRows;
4482 }
4483 break;
4484 case SQL_REFRESH:
4485 /* todo*/
4486 break;
4487 default:
4488 MADB_SetError(&Stmt->Error, MADB_ERR_HYC00, "Only SQL_POSITION and SQL_REFRESH Operations are supported", 0);
4489 return Stmt->Error.ReturnValue;
4490 }
4491 return SQL_SUCCESS;
4492 }
4493 /* }}} */
4494 #undef MADB_SETPOS_FIRSTROW
4495 #undef MADB_SETPOS_AGG_RESULT
4496
4497 /* {{{ MADB_StmtFetchScroll */
4498 SQLRETURN MADB_StmtFetchScroll(MADB_Stmt *Stmt, SQLSMALLINT FetchOrientation,
4499 SQLLEN FetchOffset)
4500 {
4501 SQLRETURN ret= SQL_SUCCESS;
4502 SQLLEN Position;
4503 SQLLEN RowsProcessed;
4504
4505 RowsProcessed= Stmt->LastRowFetched;
4506
4507 if (Stmt->Options.CursorType == SQL_CURSOR_FORWARD_ONLY &&
4508 FetchOrientation != SQL_FETCH_NEXT)
4509 {
4510 MADB_SetError(&Stmt->Error, MADB_ERR_HY106, NULL, 0);
4511 return Stmt->Error.ReturnValue;
4512 }
4513
4514 if (Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4515 {
4516 SQLRETURN rc;
4517 rc= Stmt->Methods->RefreshDynamicCursor(Stmt);
4518 if (!SQL_SUCCEEDED(rc))
4519 {
4520 return Stmt->Error.ReturnValue;
4521 }
4522 }
4523 switch(FetchOrientation) {
4524 case SQL_FETCH_NEXT:
4525 Position= Stmt->Cursor.Position < 0 ? 0 : Stmt->Cursor.Position + RowsProcessed;
4526 /* if (Stmt->Ird->Header.RowsProcessedPtr)
4527 Position+= MAX(1, *Stmt->Ird->Header.RowsProcessedPtr);
4528 else
4529 Position++; */
4530 break;
4531 case SQL_FETCH_PRIOR:
4532 Position= Stmt->Cursor.Position < 0 ? - 1: Stmt->Cursor.Position - MAX(1, Stmt->Ard->Header.ArraySize);
4533 /* if (Stmt->Ird->Header.RowsProcessedPtr)
4534 Position-= MAX(1, *Stmt->Ird->Header.RowsProcessedPtr);
4535 else
4536 Position--; */
4537 break;
4538 case SQL_FETCH_RELATIVE:
4539 Position= Stmt->Cursor.Position + FetchOffset;
4540 if (Position < 0 && Stmt->Cursor.Position > 0 &&
4541 -FetchOffset <= (SQLINTEGER)Stmt->Ard->Header.ArraySize)
4542 Position= 0;
4543 break;
4544 case SQL_FETCH_ABSOLUTE:
4545 if (FetchOffset < 0)
4546 {
4547 if ((long long)mysql_stmt_num_rows(Stmt->stmt) - 1 + FetchOffset < 0 &&
4548 ((SQLULEN)-FetchOffset <= Stmt->Ard->Header.ArraySize))
4549 Position= 0;
4550 else
4551 Position= (SQLLEN)mysql_stmt_num_rows(Stmt->stmt) + FetchOffset;
4552 }
4553 else
4554 Position= FetchOffset - 1;
4555 break;
4556 case SQL_FETCH_FIRST:
4557 Position= 0;
4558 break;
4559 case SQL_FETCH_LAST:
4560 Position= (SQLLEN)mysql_stmt_num_rows(Stmt->stmt) - MAX(1, Stmt->Ard->Header.ArraySize);
4561 /* if (Stmt->Ard->Header.ArraySize > 1)
4562 Position= MAX(0, Position - Stmt->Ard->Header.ArraySize + 1); */
4563 break;
4564 case SQL_FETCH_BOOKMARK:
4565 if (Stmt->Options.UseBookmarks == SQL_UB_OFF)
4566 {
4567 MADB_SetError(&Stmt->Error, MADB_ERR_HY106, NULL, 0);
4568 return Stmt->Error.ReturnValue;
4569 }
4570 if (!Stmt->Options.BookmarkPtr)
4571 {
4572 MADB_SetError(&Stmt->Error, MADB_ERR_HY111, NULL, 0);
4573 return Stmt->Error.ReturnValue;
4574 }
4575
4576 Position= *((long *)Stmt->Options.BookmarkPtr);
4577 if (Stmt->Connection->Environment->OdbcVersion >= SQL_OV_ODBC3)
4578 Position+= FetchOffset;
4579 break;
4580 default:
4581 MADB_SetError(&Stmt->Error, MADB_ERR_HY106, NULL, 0);
4582 return Stmt->Error.ReturnValue;
4583 break;
4584 }
4585
4586 if (Position < 0)
4587 {
4588 MADB_STMT_RESET_CURSOR(Stmt);
4589 }
4590 else
4591 {
4592 Stmt->Cursor.Position= (SQLLEN)MIN((my_ulonglong)Position, mysql_stmt_num_rows(Stmt->stmt));
4593 }
4594 if (Position < 0 || (my_ulonglong)Position > mysql_stmt_num_rows(Stmt->stmt) - 1)
4595 {
4596 /* We need to put cursor before RS start, not only return error */
4597 if (Position < 0)
4598 {
4599 MADB_StmtDataSeek(Stmt, 0);
4600 }
4601 return SQL_NO_DATA;
4602 }
4603
4604 if (FetchOrientation != SQL_FETCH_NEXT || RowsProcessed > 1 || Stmt->Options.CursorType == SQL_CURSOR_DYNAMIC)
4605 {
4606 ret= MADB_StmtDataSeek(Stmt, Stmt->Cursor.Position);
4607 }
4608
4609 /* Assuming, that ret before previous "if" was SQL_SUCCESS */
4610 if (ret == SQL_SUCCESS)
4611 {
4612 ret= Stmt->Methods->Fetch(Stmt);
4613 }
4614 if (ret == SQL_NO_DATA_FOUND && Stmt->LastRowFetched > 0)
4615 {
4616 ret= SQL_SUCCESS;
4617 }
4618 return ret;
4619 }
4620
4621 struct st_ma_stmt_methods MADB_StmtMethods=
4622 {
4623 MADB_StmtPrepare,
4624 MADB_StmtExecute,
4625 MADB_StmtFetch,
4626 MADB_StmtBindCol,
4627 MADB_StmtBindParam,
4628 MADB_StmtExecDirect,
4629 MADB_StmtGetData,
4630 MADB_StmtRowCount,
4631 MADB_StmtParamCount,
4632 MADB_StmtColumnCount,
4633 MADB_StmtGetAttr,
4634 MADB_StmtSetAttr,
4635 MADB_StmtFree,
4636 MADB_StmtColAttr,
4637 MADB_StmtColumnPrivileges,
4638 MADB_StmtTablePrivileges,
4639 MADB_StmtTables,
4640 MADB_StmtStatistics,
4641 MADB_StmtColumns,
4642 MADB_StmtProcedureColumns,
4643 MADB_StmtPrimaryKeys,
4644 MADB_StmtSpecialColumns,
4645 MADB_StmtProcedures,
4646 MADB_StmtForeignKeys,
4647 MADB_StmtDescribeCol,
4648 MADB_SetCursorName,
4649 MADB_GetCursorName,
4650 MADB_StmtSetPos,
4651 MADB_StmtFetchScroll,
4652 MADB_StmtParamData,
4653 MADB_StmtPutData,
4654 MADB_StmtBulkOperations,
4655 MADB_RefreshDynamicCursor,
4656 MADB_RefreshRowPtrs,
4657 MADB_GetOutParams
4658 };
0 /************************************************************************************
1 Copyright (C) 2013, 2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_statement_h_
19 #define _ma_statement_h_
20
21 #define MADB_FETCH_TYPE_FETCH 1
22 #define MADB_FETCH_TYPE_BULK 2
23 #define MADB_FETCH_TYPE_SETPOS 3
24
25
26 struct st_ma_stmt_methods
27 {
28 SQLRETURN (*Prepare)(MADB_Stmt *Stmt, char *StatementText, SQLINTEGER TextLength, BOOL ExecDirect);
29 SQLRETURN (*Execute)(MADB_Stmt *Stmt, BOOL ExecDirect);
30 SQLRETURN (*Fetch)(MADB_Stmt *Stmt);
31 SQLRETURN (*BindColumn)(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
32 SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN *StrLen_or_Ind);
33 SQLRETURN (*BindParam)(MADB_Stmt *Stmt, SQLUSMALLINT ParameterNumber, SQLSMALLINT InputOutputType, SQLSMALLINT ValueType,
34 SQLSMALLINT ParameterType, SQLULEN ColumnSize, SQLSMALLINT DecimalDigits, SQLPOINTER ParameterValuePtr,
35 SQLLEN BufferLength, SQLLEN *StrLen_or_IndPtr);
36 SQLRETURN (*ExecDirect)(MADB_Stmt *Stmt, char *StatementText, SQLINTEGER TextLength);
37 SQLRETURN (*GetData)(SQLHSTMT StatementHandle, SQLUSMALLINT Col_or_Param_Num, SQLSMALLINT TargetType,
38 SQLPOINTER TargetValuePtr, SQLLEN BufferLength, SQLLEN * StrLen_or_IndPtr, BOOL InternalUse);
39 SQLRETURN (*RowCount)(MADB_Stmt *Stmt, SQLLEN *RowCountPtr);
40 SQLRETURN (*ParamCount)(MADB_Stmt *Stmt, SQLSMALLINT *ParamCountPtr);
41 SQLRETURN (*ColumnCount)(MADB_Stmt *Stmt, SQLSMALLINT *ColumnCountPtr);
42 SQLRETURN (*GetAttr)(MADB_Stmt *Stmt, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER BufferLength,
43 SQLINTEGER *StringLength);
44 SQLRETURN (*SetAttr)(MADB_Stmt *Stmt, SQLINTEGER Attribute, SQLPOINTER ValuePtr, SQLINTEGER StringLength);
45 SQLRETURN (*StmtFree)(MADB_Stmt *Stmt, SQLUSMALLINT Option);
46 SQLRETURN (*ColAttribute)(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttributePtr,
47 SQLSMALLINT BufferLength, SQLSMALLINT *StringLengthPtr, SQLLEN *NumericAttributePtr,
48 my_bool isWchar);
49 SQLRETURN (*ColumnPrivileges)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
50 char *SchemaName, SQLSMALLINT NameLength2, char *TableName,
51 SQLSMALLINT NameLength3, char *ColumnName, SQLSMALLINT NameLength4);
52 SQLRETURN (*TablePrivileges)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
53 char *SchemaName, SQLSMALLINT NameLength2,
54 char *TableName, SQLSMALLINT NameLength3);
55 SQLRETURN (*Tables)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
56 char *SchemaName, SQLSMALLINT NameLength2, char *TableName,
57 SQLSMALLINT NameLength3, char *TableType, SQLSMALLINT NameLength4);
58 SQLRETURN (*Statistics)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
59 char *SchemaName, SQLSMALLINT NameLength2,
60 char *TableName, SQLSMALLINT NameLength3,
61 SQLUSMALLINT Unique, SQLUSMALLINT Reserved);
62 SQLRETURN (*Columns)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
63 char *SchemaName, SQLSMALLINT NameLength2,
64 char *TableName, SQLSMALLINT NameLength3,
65 char *ColumnName, SQLSMALLINT NameLength4);
66 SQLRETURN (*ProcedureColumns)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
67 char *SchemaName, SQLSMALLINT NameLength2, char *ProcName,
68 SQLSMALLINT NameLength3, char *ColumnName, SQLSMALLINT NameLength4);
69 SQLRETURN (*PrimaryKeys)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
70 char *SchemaName, SQLSMALLINT NameLength2, char *TableName,
71 SQLSMALLINT NameLength3);
72 SQLRETURN (*SpecialColumns)(MADB_Stmt *Stmt, SQLUSMALLINT IdentifierType,
73 char *CatalogName, SQLSMALLINT NameLength1,
74 char *SchemaName, SQLSMALLINT NameLength2,
75 char *TableName, SQLSMALLINT NameLength3,
76 SQLUSMALLINT Scope, SQLUSMALLINT Nullable);
77 SQLRETURN (*Procedures)(MADB_Stmt *Stmt, char *CatalogName, SQLSMALLINT NameLength1,
78 char *SchemaName, SQLSMALLINT NameLength2, char *ProcName,
79 SQLSMALLINT NameLength3);
80 SQLRETURN (*ForeignKeys)(MADB_Stmt *Stmt, char *PKCatalogName, SQLSMALLINT NameLength1,
81 char *PKSchemaName, SQLSMALLINT NameLength2, char *PKTableName,
82 SQLSMALLINT NameLength3, char *FKCatalogName, SQLSMALLINT NameLength4,
83 char *FKSchemaName, SQLSMALLINT NameLength5, char *FKTableName,
84 SQLSMALLINT NameLength6);
85 SQLRETURN (*DescribeCol)(MADB_Stmt *Stmt, SQLUSMALLINT ColumnNumber, void *ColumnName,
86 SQLSMALLINT BufferLength, SQLSMALLINT *NameLengthPtr,
87 SQLSMALLINT *DataTypePtr, SQLULEN *ColumnSizePtr, SQLSMALLINT *DecimalDigitsPtr,
88 SQLSMALLINT *NullablePtr, my_bool isWChar);
89 SQLRETURN (*SetCursorName)(MADB_Stmt *Stmt, char *Buffer, SQLINTEGER BufferLength);
90 SQLRETURN (*GetCursorName)(MADB_Stmt *Stmt, void *CursorName, SQLSMALLINT BufferLength,
91 SQLSMALLINT *NameLengthPtr, my_bool isWChar);
92 SQLRETURN (*SetPos)(MADB_Stmt *Stmt, SQLSETPOSIROW Row, SQLUSMALLINT Operation,
93 SQLUSMALLINT LockType, int ArrayOffset);
94 SQLRETURN (*FetchScroll)(MADB_Stmt *Stmt, SQLSMALLINT FetchOrientation,
95 SQLLEN FetchOffset);
96 SQLRETURN (*ParamData)(MADB_Stmt *Stmt, SQLPOINTER *ValuePtrPtr);
97 SQLRETURN (*PutData)(MADB_Stmt *Stmt, SQLPOINTER DataPtr, SQLLEN StrLen_or_Ind);
98 SQLRETURN (*BulkOperations)(MADB_Stmt *Stmt, SQLSMALLINT Operation);
99 SQLRETURN (*RefreshDynamicCursor)(MADB_Stmt *Stmt);
100 SQLRETURN (*RefreshRowPtrs)(MADB_Stmt *Stmt);
101 SQLRETURN (*GetOutParams)(MADB_Stmt *Stmt, int CurrentOffset);
102 };
103
104 SQLRETURN MADB_StmtInit (MADB_Dbc *Connection, SQLHANDLE *pHStmt);
105 SQLUSMALLINT MapColAttributeDescType(SQLUSMALLINT FieldIdentifier);
106 MYSQL_RES* FetchMetadata (MADB_Stmt *Stmt);
107 SQLRETURN MADB_DoExecute(MADB_Stmt *Stmt, BOOL ExecDirect);
108
109 #define MADB_MAX_CURSOR_NAME 64 * 3 + 1
110 #define MADB_CHECK_STMT_HANDLE(a,b)\
111 if (!(a) || !(a)->b)\
112 return SQL_INVALID_HANDLE
113
114 #define MADB_STMT_COLUMN_COUNT(aStmt) (aStmt)->Ird->Header.Count
115 #define MADB_RESET_COLUMT_COUNT(aStmt) (aStmt)->Ird->Header.Count= 0
116 #define MADB_STMT_PARAM_COUNT(aStmt) (aStmt)->ParamCount
117 #define MADB_POSITIONED_COMMAND(aStmt) ((aStmt)->PositionedCommand && (aStmt)->PositionedCursor)
118 /* So far we always use all fields for index. Once that is changed, this should be changed as well */
119 #define MADB_POS_COMM_IDX_FIELD_COUNT(aStmt) MADB_STMT_COLUMN_COUNT((aStmt)->PositionedCursor)
120 #define MADB_STMT_RESET_CURSOR(aStmt) (aStmt)->Cursor.Position= -1;
121 #define MADB_STMT_CLOSE_STMT(aStmt) mysql_stmt_close((aStmt)->stmt);(aStmt)->stmt= NULL
122
123 #define MADB_OCTETS_PER_CHAR 2
124
125 #define MADB_TRANSFER_OCTET_LENGTH(TYPE_DEF_COL_NAME)\
126 "@tol:=CAST(CASE @dt"\
127 " WHEN " XSTR(SQL_BIT) " THEN 1 "\
128 " WHEN " XSTR(SQL_TINYINT) " THEN 1 "\
129 " WHEN " XSTR(SQL_SMALLINT) " THEN 2 "\
130 " WHEN " XSTR(SQL_INTEGER) " THEN IF(DATA_TYPE='mediumint',3,4) "\
131 " WHEN " XSTR(SQL_BIGINT) " THEN 20 "\
132 " WHEN " XSTR(SQL_REAL) " THEN 4 "\
133 " WHEN " XSTR(SQL_FLOAT) " THEN 8 "\
134 " WHEN " XSTR(SQL_DOUBLE) " THEN 8 "\
135 " WHEN " XSTR(SQL_DATE) " THEN 6 "\
136 " WHEN " XSTR(SQL_TYPE_DATE) " THEN 6 "\
137 " WHEN " XSTR(SQL_TIME) " THEN 6 "\
138 " WHEN " XSTR(SQL_TYPE_TIME) " THEN 6 "\
139 " WHEN " XSTR(SQL_TIMESTAMP) " THEN 16 "\
140 " WHEN " XSTR(SQL_TYPE_TIMESTAMP) " THEN 16 "\
141 " WHEN " XSTR(SQL_GUID) " THEN 16 "\
142 " WHEN " XSTR(SQL_DECIMAL) " THEN @ColSize + IF(" #TYPE_DEF_COL_NAME " LIKE '%%unsigned',1,2) "\
143 " WHEN " XSTR(SQL_BINARY) " THEN IF(DATA_TYPE='bit', CAST(((NUMERIC_PRECISION + 7) / 8) AS SIGNED), CHARACTER_OCTET_LENGTH) "\
144 " WHEN " XSTR(SQL_VARBINARY) " THEN CHARACTER_OCTET_LENGTH "\
145 " WHEN " XSTR(SQL_LONGVARBINARY) " THEN CHARACTER_OCTET_LENGTH "\
146 " ELSE CHARACTER_MAXIMUM_LENGTH*%u "\
147 "END AS SIGNED)"
148
149 /* CASE for DATA_TYPE glued in 2 parts for ODBC v2 or v3 */
150 #define MADB_SQL_DATATYPEp1\
151 "CASE DATA_TYPE"\
152 " WHEN 'bit' THEN @dt:= IF(NUMERIC_PRECISION=1," XSTR(SQL_BIT) ", " XSTR(SQL_BINARY) ")"\
153 " WHEN 'tinyint' THEN @dt:=" XSTR(SQL_TINYINT)\
154 " WHEN 'smallint' THEN @dt:=" XSTR(SQL_SMALLINT)\
155 " WHEN 'year' THEN @dt:= " XSTR(SQL_SMALLINT)\
156 " WHEN 'mediumint' THEN @dt:=" XSTR(SQL_INTEGER)\
157 " WHEN 'int' THEN @dt:=" XSTR(SQL_INTEGER)\
158 " WHEN 'bigint' THEN @dt:=" XSTR(SQL_BIGINT)\
159 " WHEN 'blob' THEN @dt:=" XSTR(SQL_LONGVARBINARY)\
160 " WHEN 'tinyblob' THEN @dt:=" XSTR(SQL_LONGVARBINARY)\
161 " WHEN 'mediumblob' THEN @dt:=" XSTR(SQL_LONGVARBINARY)\
162 " WHEN 'longblob' THEN @dt:=" XSTR(SQL_LONGVARBINARY)\
163 " WHEN 'decimal' THEN @dt:=" XSTR(SQL_DECIMAL)\
164 " WHEN 'float' THEN @dt:=IF(NUMERIC_SCALE IS NULL," XSTR(SQL_REAL) ", " XSTR(SQL_DECIMAL) ")"\
165 " WHEN 'double' THEN @dt:=IF(NUMERIC_SCALE IS NULL," XSTR(SQL_DOUBLE) ", " XSTR(SQL_DECIMAL) ")"\
166 " WHEN 'binary' THEN @dt:=" XSTR(SQL_BINARY)\
167 " WHEN 'varbinary' THEN @dt:=" XSTR(SQL_VARBINARY)
168
169 #define MADB_SQL_DATATYPEp1U\
170 " WHEN 'text' THEN @dt:=" XSTR(SQL_WLONGVARCHAR)\
171 " WHEN 'tinytext' THEN @dt:=" XSTR(SQL_WLONGVARCHAR)\
172 " WHEN 'mediumtext' THEN @dt:=" XSTR(SQL_WLONGVARCHAR)\
173 " WHEN 'longtext' THEN @dt:=" XSTR(SQL_WLONGVARCHAR)\
174 " WHEN 'char' THEN @dt:=" XSTR(SQL_WCHAR)\
175 " WHEN 'enum' THEN @dt:=" XSTR(SQL_WCHAR)\
176 " WHEN 'set' THEN @dt:=" XSTR(SQL_WCHAR)\
177 " WHEN 'varchar' THEN @dt:=" XSTR(SQL_WVARCHAR)
178
179 #define MADB_SQL_DATATYPEp1A\
180 " WHEN 'text' THEN @dt:=" XSTR(SQL_LONGVARCHAR)\
181 " WHEN 'tinytext' THEN @dt:=" XSTR(SQL_LONGVARCHAR)\
182 " WHEN 'mediumtext' THEN @dt:=" XSTR(SQL_LONGVARCHAR)\
183 " WHEN 'longtext' THEN @dt:=" XSTR(SQL_LONGVARCHAR)\
184 " WHEN 'char' THEN @dt:=" XSTR(SQL_CHAR)\
185 " WHEN 'enum' THEN @dt:=" XSTR(SQL_CHAR)\
186 " WHEN 'set' THEN @dt:=" XSTR(SQL_CHAR)\
187 " WHEN 'varchar' THEN @dt:=" XSTR(SQL_VARCHAR)
188
189 #define MADB_SQL_DATATYPEp2_ODBC3\
190 " WHEN 'date' THEN @dt:=" XSTR(SQL_TYPE_DATE)\
191 " WHEN 'time' THEN @dt:=" XSTR(SQL_TYPE_TIME)\
192 " WHEN 'datetime' THEN @dt:=" XSTR(SQL_TYPE_TIMESTAMP)\
193 " WHEN 'timestamp' THEN @dt:=" XSTR(SQL_TYPE_TIMESTAMP)\
194 " ELSE @dt:=" XSTR(SQL_LONGVARBINARY)\
195 "END AS DATA_TYPE"
196
197 #define MADB_SQL_DATATYPEp2_ODBC2\
198 " WHEN 'date' THEN @dt:=" XSTR(SQL_DATE)\
199 " WHEN 'time' THEN @dt:=" XSTR(SQL_TIME)\
200 " WHEN 'datetime' THEN @dt:=" XSTR(SQL_TIMESTAMP)\
201 " WHEN 'timestamp' THEN @dt:=" XSTR(SQL_TIMESTAMP)\
202 " ELSE @dt:=" XSTR(SQL_LONGVARBINARY)\
203 "END AS DATA_TYPE"
204
205 #define MADB_SQL_DATATYPE_ODBC3U MADB_SQL_DATATYPEp1 MADB_SQL_DATATYPEp1U MADB_SQL_DATATYPEp2_ODBC3
206 #define MADB_SQL_DATATYPE_ODBC3A MADB_SQL_DATATYPEp1 MADB_SQL_DATATYPEp1A MADB_SQL_DATATYPEp2_ODBC3
207 #define MADB_SQL_DATATYPE_ODBC2U MADB_SQL_DATATYPEp1 MADB_SQL_DATATYPEp1U MADB_SQL_DATATYPEp2_ODBC2
208 #define MADB_SQL_DATATYPE_ODBC2A MADB_SQL_DATATYPEp1 MADB_SQL_DATATYPEp1A MADB_SQL_DATATYPEp2_ODBC2
209
210 #define MADB_SQL_DATATYPE(StmtHndl) (StmtHndl->Connection->Environment->OdbcVersion >= SQL_OV_ODBC3 ?\
211 (StmtHndl->Connection->IsAnsi ? MADB_SQL_DATATYPE_ODBC3A : MADB_SQL_DATATYPE_ODBC3U) :\
212 (StmtHndl->Connection->IsAnsi ? MADB_SQL_DATATYPE_ODBC2A : MADB_SQL_DATATYPE_ODBC2U))
213
214 /************** End of DATA_TYPE *************/
215
216 /************** SQLColumns *************/
217 #define MADB_COLUMN_SIZE\
218 "CAST(CASE" \
219 " WHEN DATA_TYPE = 'bit' THEN @ColSize:=((NUMERIC_PRECISION + 7) / 8) "\
220 " WHEN DATA_TYPE in ('tinyint', 'smallint', 'mediumint', 'int',"\
221 "'bigint', 'decimal') THEN @ColSize:=NUMERIC_PRECISION "\
222 " WHEN DATA_TYPE = 'float' THEN if(NUMERIC_SCALE IS NULL, @ColSize:=7, @ColSize:=NUMERIC_PRECISION)"\
223 " WHEN DATA_TYPE = 'double' THEN if(NUMERIC_SCALE IS NULL, @ColSize:=15, @ColSize:=NUMERIC_PRECISION)"\
224 " WHEN DATA_TYPE = 'date' THEN @ColSize:=10"\
225 " WHEN DATA_TYPE = 'time' THEN @ColSize:=8"\
226 " WHEN DATA_TYPE = 'year' THEN @ColSize:=4"\
227 " WHEN DATA_TYPE in ('timestamp', 'datetime') THEN @ColSize:=19 "\
228 " ELSE @ColSize:=CHARACTER_MAXIMUM_LENGTH "\
229 "END AS UNSIGNED)"
230
231 #define MADB_CATALOG_COLUMNSp1 "SELECT TABLE_SCHEMA AS TABLE_CAT, NULL AS TABLE_SCHEM, TABLE_NAME, COLUMN_NAME, "
232 #define MADB_CATALOG_COLUMNSp3 ", UCASE(IF(COLUMN_TYPE LIKE '%%(%%)%%', CONCAT(SUBSTRING(COLUMN_TYPE,1, LOCATE('(',COLUMN_TYPE) - 1 ), SUBSTRING(COLUMN_TYPE,1+locate(')',COLUMN_TYPE))), COLUMN_TYPE )) AS TYPE_NAME, "\
233 MADB_COLUMN_SIZE " AS COLUMN_SIZE,"\
234 MADB_TRANSFER_OCTET_LENGTH(COLUMN_TYPE) " AS BUFFER_LENGTH, "\
235 "NUMERIC_SCALE DECIMAL_DIGITS, IF(CHARACTER_OCTET_LENGTH IS NOT NULL, NULL, 10) AS NUM_PREC_RADIX,"\
236 "IF(DATA_TYPE='timestamp', 1, IF(IS_NULLABLE='YES',1,IF(EXTRA='auto_increment', 1, 0))) AS NULLABLE, "\
237 "COLUMN_COMMENT AS REMARKS,"
238 #define MADB_DEFAULT_COLUMN_OLD "IF(COLLATION_NAME IS NOT NULL AND COLUMN_DEFAULT IS NOT NULL, CONCAT(CHAR(39), COLUMN_DEFAULT, CHAR(39)), COLUMN_DEFAULT)"
239 #define MADB_DEFAULT_COLUMN_NEW "COLUMN_DEFAULT"
240 #define MADB_DEFAULT_COLUMN(DbcHndl) (MADB_ServerSupports(DbcHndl,MADB_ENCLOSES_COLUMN_DEF_WITH_QUOTES) ? MADB_DEFAULT_COLUMN_NEW : MADB_DEFAULT_COLUMN_OLD)
241 #define MADB_CATALOG_TYPE_SUB "CAST(CASE"\
242 " WHEN DATA_TYPE = 'date' THEN " XSTR(SQL_DATETIME)\
243 " WHEN DATA_TYPE = 'time' THEN " XSTR(SQL_DATETIME)\
244 " WHEN DATA_TYPE = 'datetime' THEN " XSTR(SQL_DATETIME)\
245 " WHEN DATA_TYPE = 'timestamp' THEN " XSTR(SQL_DATETIME)\
246 " ELSE @dt "\
247 "END AS SIGNED) SQL_DATA_TYPE,"\
248 "CAST(CASE"\
249 " WHEN DATA_TYPE = 'date' THEN " XSTR(SQL_CODE_DATE)\
250 " WHEN DATA_TYPE = 'time' THEN " XSTR(SQL_CODE_TIME)\
251 " WHEN DATA_TYPE = 'datetime' THEN " XSTR(SQL_CODE_TIMESTAMP)\
252 " WHEN DATA_TYPE = 'timestamp' THEN " XSTR(SQL_CODE_TIMESTAMP)\
253 " ELSE NULL "\
254 "END AS SIGNED) SQL_DATETIME_SUB,"
255 #define MADB_CATALOG_COLUMNSp4 " AS COLUMN_DEF," MADB_CATALOG_TYPE_SUB\
256 "IF(CHARACTER_OCTET_LENGTH IS NOT NULL, @tol, IF(DATA_TYPE='bit' AND NUMERIC_PRECISION =1, NULL, CAST((NUMERIC_PRECISION + 7)/8 AS SIGNED))) AS CHAR_OCTET_LENGTH, "\
257 "ORDINAL_POSITION,"\
258 "IF(DATA_TYPE='timestamp', 'YES', IF(IS_NULLABLE='YES','YES',IF(EXTRA='auto_increment', 'YES', 'NO'))) AS IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE "
259
260 /************** End of SQLColumns ************/
261
262 /************** SQLProcedureColumns **********/
263 #define MADB_PROCEDURE_COLUMNSp1 \
264 "SELECT SPECIFIC_SCHEMA AS PROCEDURE_CAT, NULL AS PROCEDURE_SCHEM, "\
265 "SPECIFIC_NAME PROCEDURE_NAME, IF(PARAMETER_NAME IS NULL, '', PARAMETER_NAME) COLUMN_NAME, "\
266 "CASE PARAMETER_MODE "\
267 " WHEN 'IN' THEN " XSTR(SQL_PARAM_INPUT)\
268 " WHEN 'OUT' THEN " XSTR(SQL_PARAM_OUTPUT)\
269 " WHEN 'INOUT' THEN " XSTR(SQL_PARAM_INPUT_OUTPUT)\
270 " ELSE IF(PARAMETER_MODE IS NULL, " XSTR(SQL_RETURN_VALUE) ", " XSTR(SQL_PARAM_TYPE_UNKNOWN) ")"\
271 "END COLUMN_TYPE, "
272 #define MADB_PROCEDURE_COLUMNSp3\
273 ", DATA_TYPE TYPE_NAME, "\
274 MADB_COLUMN_SIZE " AS COLUMN_SIZE, "\
275 MADB_TRANSFER_OCTET_LENGTH(DTD_IDENTIFIER) " AS BUFFER_LENGTH, "\
276 "NUMERIC_SCALE DECIMAL_DIGITS, IF(NUMERIC_PRECISION IS NULL, NULL, 10) AS NUM_PREC_RADIX,"\
277 XSTR(SQL_NULLABLE_UNKNOWN) " NULLABLE,"\
278 "NULL REMARKS, NULL COLUMN_DEF," MADB_CATALOG_TYPE_SUB \
279 "IF(CHARACTER_MAXIMUM_LENGTH IS NULL, NULL, @tol) CHAR_OCTET_LENGTH, "\
280 "ORDINAL_POSITION, 'YES' IS_NULLABLE FROM INFORMATION_SCHEMA.PARAMETERS "
281
282 #define MADB_PROCEDURE_COLUMNS_ODBC3U MADB_PROCEDURE_COLUMNSp1 MADB_SQL_DATATYPE_ODBC3U MADB_PROCEDURE_COLUMNSp3
283 #define MADB_PROCEDURE_COLUMNS_ODBC2U MADB_PROCEDURE_COLUMNSp1 MADB_SQL_DATATYPE_ODBC2U MADB_PROCEDURE_COLUMNSp3
284 #define MADB_PROCEDURE_COLUMNS_ODBC3A MADB_PROCEDURE_COLUMNSp1 MADB_SQL_DATATYPE_ODBC3A MADB_PROCEDURE_COLUMNSp3
285 #define MADB_PROCEDURE_COLUMNS_ODBC2A MADB_PROCEDURE_COLUMNSp1 MADB_SQL_DATATYPE_ODBC2A MADB_PROCEDURE_COLUMNSp3
286
287 #define MADB_PROCEDURE_COLUMNS(StmtHndl) (StmtHndl->Connection->Environment->OdbcVersion >= SQL_OV_ODBC3 ?\
288 (StmtHndl->Connection->IsAnsi ? MADB_PROCEDURE_COLUMNS_ODBC3A : MADB_PROCEDURE_COLUMNS_ODBC3U) : \
289 (StmtHndl->Connection->IsAnsi ? MADB_PROCEDURE_COLUMNS_ODBC2A : MADB_PROCEDURE_COLUMNS_ODBC2U))
290 /************** SQLProcedureColumns **********/
291
292 #endif
0 /************************************************************************************
1 Copyright (C) 2013,2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #include <ma_odbc.h>
19
20 extern MARIADB_CHARSET_INFO* DmUnicodeCs;
21
22 char *MADB_GetTableName(MADB_Stmt *Stmt)
23 {
24 char *TableName= NULL;
25 unsigned int i= 0;
26 if (Stmt->TableName && Stmt->TableName[0])
27 return Stmt->TableName;
28 if (!mysql_stmt_field_count(Stmt->stmt))
29 return NULL;
30
31 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
32 {
33 if (Stmt->stmt->fields[i].org_table)
34 {
35 if (!TableName)
36 TableName= Stmt->stmt->fields[i].org_table;
37 if (strcmp(TableName, Stmt->stmt->fields[i].org_table))
38 {
39 MADB_SetError(&Stmt->Error, MADB_ERR_HY000, "Couldn't identify unique table name", 0);
40 return NULL;
41 }
42 }
43 }
44 if (TableName)
45 Stmt->TableName= _strdup(TableName);
46 return TableName;
47 }
48
49 char *MADB_GetCatalogName(MADB_Stmt *Stmt)
50 {
51 char *CatalogName= NULL;
52 unsigned int i= 0;
53 if (Stmt->CatalogName && Stmt->CatalogName[0])
54 return Stmt->CatalogName;
55 if (!mysql_stmt_field_count(Stmt->stmt))
56 return NULL;
57
58 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
59 {
60 if (Stmt->stmt->fields[i].org_table)
61 {
62 if (!CatalogName)
63 CatalogName= Stmt->stmt->fields[i].db;
64 if (strcmp(CatalogName, Stmt->stmt->fields[i].db))
65 {
66 MADB_SetError(&Stmt->Error, MADB_ERR_HY000, "Couldn't identify unique catalog name", 0);
67 return NULL;
68 }
69 }
70 }
71 if (CatalogName)
72 Stmt->CatalogName= _strdup(CatalogName);
73 return CatalogName;
74 }
75
76 my_bool MADB_DynStrAppendQuoted(MADB_DynString *DynString, char *String)
77 {
78 if (MADB_DynstrAppend(DynString, "`") ||
79 MADB_DynstrAppend(DynString, String) ||
80 MADB_DynstrAppend(DynString, "`"))
81 return TRUE;
82 return FALSE;
83 }
84
85 my_bool MADB_DynStrUpdateSet(MADB_Stmt *Stmt, MADB_DynString *DynString)
86 {
87 int i, IgnoredColumns= 0;
88 MADB_DescRecord *Record;
89
90 if (MADB_DynstrAppend(DynString, " SET "))
91 {
92 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
93 return TRUE;
94 }
95 // ???? memcpy(&Stmt->Da->Apd->Header, &Stmt->Ard->Header, sizeof(MADB_Header));
96 for (i=0; i < MADB_STMT_COLUMN_COUNT(Stmt); i++)
97 {
98 SQLLEN *IndicatorPtr= NULL;
99 Record= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ);
100 if (Record->IndicatorPtr)
101 IndicatorPtr= (SQLLEN *)GetBindOffset(Stmt->Ard, Record, Record->IndicatorPtr, Stmt->DaeRowNumber > 1 ? Stmt->DaeRowNumber-1 : 0,
102 sizeof(SQLLEN)/*Record->OctetLength*/);
103 if ((IndicatorPtr && *IndicatorPtr == SQL_COLUMN_IGNORE) || !Record->inUse)
104 {
105 IgnoredColumns++;
106 continue;
107 }
108
109 if ((i - IgnoredColumns) && MADB_DynstrAppend(DynString, ","))
110 {
111 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
112 return TRUE;
113 }
114 if (MADB_DynStrAppendQuoted(DynString, Stmt->stmt->fields[i].org_name))
115 {
116 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
117 return TRUE;
118 }
119 if (MADB_DynstrAppend(DynString, "=?"))
120 {
121 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
122 return TRUE;
123 }
124 }
125 if (IgnoredColumns == mysql_stmt_field_count(Stmt->stmt))
126 {
127 MADB_SetError(&Stmt->Error, MADB_ERR_21S02, NULL, 0);
128 return TRUE;
129 }
130 return FALSE;
131 }
132
133 my_bool MADB_DynStrInsertSet(MADB_Stmt *Stmt, MADB_DynString *DynString)
134 {
135 MADB_DynString ColVals;
136 int i, NeedComma= 0;
137 MADB_DescRecord *Record;
138
139 MADB_InitDynamicString(&ColVals, "VALUES (", 32, 32);
140 if (MADB_DynstrAppend(DynString, " ("))
141 {
142 goto dynerror;
143
144 return TRUE;
145 }
146
147 /* We use only columns, that have been bound, and are not IGNORED */
148 for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); i++)
149 {
150 Record= MADB_DescGetInternalRecord(Stmt->Ard, i, MADB_DESC_READ);
151 if (!Record->inUse || MADB_ColumnIgnoredInAllRows(Stmt->Ard, Record) == TRUE)
152 {
153 continue;
154 }
155
156 if ((NeedComma) &&
157 (MADB_DynstrAppend(DynString, ",") || MADB_DynstrAppend(&ColVals, ",")))
158 goto dynerror;
159
160 if (MADB_DynStrAppendQuoted(DynString, Stmt->stmt->fields[i].org_name) ||
161 MADB_DynstrAppend(&ColVals, "?"))
162 goto dynerror;
163
164 NeedComma= 1;
165 }
166 if (MADB_DynstrAppend(DynString, ") " ) ||
167 MADB_DynstrAppend(&ColVals, ")") ||
168 MADB_DynstrAppend(DynString, ColVals.str))
169 goto dynerror;
170 MADB_DynstrFree(&ColVals);
171 return FALSE;
172 dynerror:
173 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
174 MADB_DynstrFree(&ColVals);
175 return TRUE;
176 }
177
178 my_bool MADB_DynStrGetColumns(MADB_Stmt *Stmt, MADB_DynString *DynString)
179 {
180 unsigned int i;
181 if (MADB_DynstrAppend(DynString, " ("))
182 {
183 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
184 return TRUE;
185 }
186 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
187 {
188 if (i && MADB_DynstrAppend(DynString, ", "))
189 {
190 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
191 return TRUE;
192 }
193 if (MADB_DynStrAppendQuoted(DynString, Stmt->stmt->fields[i].org_name))
194 {
195 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
196 return TRUE;
197 }
198 }
199 if (MADB_DynstrAppend(DynString, " )"))
200 {
201 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
202 return TRUE;
203 }
204 return FALSE;
205 }
206
207 my_bool MADB_DynStrGetWhere(MADB_Stmt *Stmt, MADB_DynString *DynString, char *TableName, my_bool ParameterMarkers)
208 {
209 int UniqueCount=0, PrimaryCount= 0;
210 int i, Flag= 0;
211 char *Column= NULL;
212 SQLLEN StrLength;
213
214 for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); i++)
215 {
216 MYSQL_FIELD *field= mysql_fetch_field_direct(FetchMetadata(Stmt), i);
217 if (field->flags & PRI_KEY_FLAG)
218 PrimaryCount++;
219 if (field->flags & UNIQUE_KEY_FLAG)
220 UniqueCount++;
221 }
222 /* We need to use all columns, otherwise it will be difficult to map fields for Positioned Update */
223 if (PrimaryCount && PrimaryCount != MADB_KeyTypeCount(Stmt->Connection, TableName, PRI_KEY_FLAG))
224 PrimaryCount= 0;
225 if (UniqueCount && UniqueCount != MADB_KeyTypeCount(Stmt->Connection, TableName, UNIQUE_KEY_FLAG))
226 UniqueCount= 0;
227
228 /* if no primary or unique key is in the cursor, the cursor must contain all
229 columns from table in TableName */
230 if (!PrimaryCount && !UniqueCount)
231 {
232 char StmtStr[256];
233 MADB_Stmt *CountStmt;
234 int FieldCount= 0;
235
236 MA_SQLAllocHandle(SQL_HANDLE_STMT, Stmt->Connection, (SQLHANDLE*)&CountStmt);
237 _snprintf(StmtStr, 256, "SELECT * FROM `%s` LIMIT 0", TableName);
238 CountStmt->Methods->ExecDirect(CountStmt, (char *)StmtStr, SQL_NTS);
239 FieldCount= mysql_stmt_field_count(((MADB_Stmt *)CountStmt)->stmt);
240 CountStmt->Methods->StmtFree(CountStmt, SQL_DROP);
241
242 if (FieldCount != MADB_STMT_COLUMN_COUNT(Stmt))
243 {
244 MADB_SetError(&Stmt->Error, MADB_ERR_S1000, "Can't build index for update/delete", 0);
245 return TRUE;
246 }
247 }
248 if (MADB_DynstrAppend(DynString, " WHERE 1"))
249 goto memerror;
250 for (i= 0; i < MADB_STMT_COLUMN_COUNT(Stmt); i++)
251 {
252 MYSQL_FIELD *field= mysql_fetch_field_direct(Stmt->metadata, i);
253 if (field->flags & Flag || !Flag)
254 {
255 if (MADB_DynstrAppend(DynString, " AND ") ||
256 MADB_DynStrAppendQuoted(DynString, field->org_name))
257 goto memerror;
258 if (ParameterMarkers)
259 {
260 if (MADB_DynstrAppend(DynString, "=?"))
261 goto memerror;
262 }
263 else
264 {
265 if (!SQL_SUCCEEDED(Stmt->Methods->GetData(Stmt, i+1, SQL_C_CHAR, NULL, 0, &StrLength, TRUE)))
266 {
267 MADB_FREE(Column);
268 return TRUE;
269 }
270 if (StrLength < 0)
271 {
272 if (MADB_DynstrAppend(DynString, " IS NULL"))
273 goto memerror;
274 }
275 else
276 {
277 Column= MADB_CALLOC(StrLength + 1);
278 Stmt->Methods->GetData(Stmt,i+1, SQL_C_CHAR, Column, StrLength + 1, NULL, TRUE);
279 if (MADB_DynstrAppend(DynString, "= '") ||
280 MADB_DynstrAppend(DynString, Column) ||
281 MADB_DynstrAppend(DynString, "'"))
282 {
283 goto memerror;
284 }
285 MADB_FREE(Column);
286 Column= NULL;
287 }
288 }
289 }
290 }
291 if (MADB_DynstrAppend(DynString, " LIMIT 1"))
292 goto memerror;
293 MADB_FREE(Column);
294
295 return FALSE;
296
297 memerror:
298 MADB_FREE(Column);
299 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
300
301 return TRUE;
302 }
303
304
305 my_bool MADB_DynStrGetValues(MADB_Stmt *Stmt, MADB_DynString *DynString)
306 {
307 unsigned int i;
308 if (MADB_DynstrAppend(DynString, " VALUES("))
309 {
310 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
311 return TRUE;
312 }
313 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
314 {
315 if (MADB_DynstrAppend(DynString, (i) ? ",?" : "?"))
316 {
317 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
318 return TRUE;
319 }
320 }
321 if (MADB_DynstrAppend(DynString, ")"))
322 {
323 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
324 return TRUE;
325 }
326 return FALSE;
327 }
328
329 char *MADB_GetInsertStatement(MADB_Stmt *Stmt)
330 {
331 char *StmtStr;
332 size_t Length= 1024;
333 char *p;
334 char *TableName;
335 unsigned int i;
336
337 if (!(StmtStr= MADB_CALLOC(1024)))
338 {
339 MADB_SetError(&Stmt->Error, MADB_ERR_HY013, NULL, 0);
340 return NULL;
341 }
342 if (!(TableName= MADB_GetTableName(Stmt)))
343 goto error;
344 p= StmtStr;
345
346 p+= _snprintf(StmtStr, 1024, "INSERT INTO `%s` (", TableName);
347 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
348 {
349 if (strlen(StmtStr) > Length - NAME_LEN - 4/* comma + 2 ticks + terminating NULL */)
350 {
351 Length+= 1024;
352 if (!(StmtStr= MADB_REALLOC(StmtStr, Length)))
353 {
354 MADB_SetError(&Stmt->Error, MADB_ERR_HY013, NULL, 0);
355 goto error;
356 }
357 }
358 p+= _snprintf(p, Length - strlen(StmtStr), "%s`%s`", (i==0) ? "" : ",", Stmt->stmt->fields[i].org_name);
359 }
360 p+= _snprintf(p, Length - strlen(StmtStr), ") VALUES (");
361
362 if (strlen(StmtStr) > Length - mysql_stmt_field_count(Stmt->stmt)*2 - 1)/* , and ? for each column + (- 1 comma for 1st column + closing ')')
363 + terminating NULL */
364 {
365 Length= strlen(StmtStr) + mysql_stmt_field_count(Stmt->stmt)*2 + 1;
366 if (!(StmtStr= MADB_REALLOC(StmtStr, Length)))
367 {
368 MADB_SetError(&Stmt->Error, MADB_ERR_HY013, NULL, 0);
369 goto error;
370 }
371 }
372
373 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
374 {
375 p+= _snprintf(p, Length - strlen(StmtStr), "%s?", (i==0) ? "" : ",");
376 }
377 p+= _snprintf(p, Length - strlen(StmtStr), ")");
378 return StmtStr;
379
380 error:
381 if (StmtStr)
382 MADB_FREE(StmtStr);
383 return NULL;
384 }
385
386
387 my_bool MADB_ValidateStmt(MADB_QUERY *Query)
388 {
389 return Query->QueryType != MADB_QUERY_SET_NAMES;
390 }
391
392
393 char *MADB_ToLower(const char *src, char *buff, size_t buff_size)
394 {
395 size_t i= 0;
396
397 if (buff_size > 0)
398 {
399 while (*src && i < buff_size)
400 {
401 buff[i++]= tolower(*src++);
402 }
403
404 buff[i == buff_size ? i - 1 : i]= '\0';
405 }
406 return buff;
407 }
408
409
410 int InitClientCharset(Client_Charset *cc, const char * name)
411 {
412 /* There is no legal charset names longer than 31 chars */
413 char lowered[32];
414 cc->cs_info= mariadb_get_charset_by_name(MADB_ToLower(name, lowered, sizeof(lowered)));
415
416 if (cc->cs_info == NULL)
417 {
418 return 1;
419 }
420
421 cc->CodePage= cc->cs_info->codepage;
422
423 return 0;
424 }
425
426
427 void CopyClientCharset(Client_Charset * Src, Client_Charset * Dst)
428 {
429 Dst->CodePage= Src->CodePage;
430 Dst->cs_info= Src->cs_info;
431 }
432
433
434 void CloseClientCharset(Client_Charset *cc)
435 {
436 }
437
438
439 /* Hmmm... Length in characters is SQLLEN, octet length SQLINTEGER */
440 SQLLEN MbstrOctetLen(const char *str, SQLLEN *CharLen, MARIADB_CHARSET_INFO *cs)
441 {
442 SQLLEN result= 0, inChars= *CharLen;
443
444 if (str)
445 {
446 if (cs->mb_charlen == NULL)
447 {
448 /* Charset uses no more than a byte per char. Result is strlen or umber of chars */
449 if (*CharLen < 0)
450 {
451 result= (SQLLEN)strlen(str);
452 *CharLen= result;
453 }
454 else
455 {
456 result= *CharLen;
457 }
458 return result;
459 }
460 else
461 {
462 while (inChars > 0 || (inChars < 0 && *str))
463 {
464 result+= cs->mb_charlen(0 + *str);
465 --inChars;
466 str+= cs->mb_charlen(*str);
467 }
468 }
469 }
470
471 if (*CharLen < 0)
472 {
473 *CharLen-= inChars;
474 }
475 return result;
476 }
477
478
479 /* Number of characters in given number of bytes */
480 SQLLEN MbstrCharLen(const char *str, SQLINTEGER OctetLen, MARIADB_CHARSET_INFO *cs)
481 {
482 SQLLEN result= 0;
483 const char *ptr= str;
484 unsigned int charlen;
485
486 if (str)
487 {
488 if (cs->mb_charlen == NULL || cs->char_maxlen == 1)
489 {
490 return OctetLen;
491 }
492 while (ptr < str + OctetLen)
493 {
494 charlen= cs->mb_charlen((unsigned char)*ptr);
495 if (charlen == 0)
496 {
497 /* Dirty hack to avoid dead loop - Has to be the error! */
498 charlen= 1;
499 }
500
501 /* Skipping thru 0 bytes */
502 while (charlen > 0 && *ptr == '\0')
503 {
504 --charlen;
505 ++ptr;
506 }
507
508 /* Stopping if current character is terminating NULL - charlen == 0 means all bytes of current char was 0 */
509 if (charlen == 0)
510 {
511 return result;
512 }
513 /* else we increment ptr for number of left bytes */
514 ptr+= charlen;
515 ++result;
516 }
517 }
518
519 return result;
520 }
521
522
523 /* Length of NT SQLWCHAR string in characters */
524 SQLINTEGER SqlwcsCharLen(SQLWCHAR *str, SQLLEN octets)
525 {
526 SQLINTEGER result= 0;
527 SQLWCHAR *end= octets != (SQLLEN)-1 ? str + octets/sizeof(SQLWCHAR) : (SQLWCHAR*)octets /*for simplicity - the address to be always bigger */;
528
529 if (str)
530 {
531 while (str < end && *str)
532 {
533 str+= (DmUnicodeCs->mb_charlen(*str))/sizeof(SQLWCHAR);
534
535 if (str > end)
536 {
537 break;
538 }
539 ++result;
540 }
541 }
542 return result;
543 }
544
545
546 /* Length in SQLWCHAR units
547 @buff_length[in] - size of the str buffer or negative number */
548 SQLLEN SqlwcsLen(SQLWCHAR *str, SQLLEN buff_length)
549 {
550 SQLINTEGER result= 0;
551
552 if (str)
553 {
554 /* If buff_length is negative - we will never hit 1st condition, otherwise we hit it after last character
555 of the buffer is processed */
556 while ((--buff_length) != -1 && *str)
557 {
558 ++result;
559 ++str;
560 }
561 }
562 return result;
563 }
564
565 /* Length of a string with respect to specified buffer size
566 @buff_length[in] - size of the str buffer or negative number */
567 SQLLEN SafeStrlen(SQLCHAR *str, SQLLEN buff_length)
568 {
569 SQLINTEGER result= 0;
570
571 if (str)
572 {
573 /* If buff_length is negative - we will never hit 1st condition, otherwise we hit it after last character
574 of the buffer is processed */
575 while ((--buff_length) != -1 && *str)
576 {
577 ++result;
578 ++str;
579 }
580 }
581 return result;
582 }
0 /************************************************************************************
1 Copyright (C) 2013,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #ifndef _ma_string_h_
19 #define _ma_string_h_
20
21 char *MADB_ConvertFromWChar(const SQLWCHAR *Ptr, SQLINTEGER PtrLength, SQLULEN *Length, Client_Charset* cc, BOOL *DefaultCharUsed);
22 int MADB_ConvertAnsi2Unicode(Client_Charset* cc, const char *AnsiString, SQLLEN AnsiLength,
23 SQLWCHAR *UnicodeString, SQLLEN UnicodeLength,
24 SQLLEN *LengthIndicator, BOOL IsNull, MADB_Error *Error);
25 char* MADB_GetInsertStatement(MADB_Stmt *Stmt);
26 char* MADB_GetTableName(MADB_Stmt *Stmt);
27 char* MADB_GetCatalogName(MADB_Stmt *Stmt);
28 my_bool MADB_DynStrUpdateSet(MADB_Stmt *Stmt, MADB_DynString *DynString);
29 my_bool MADB_DynStrInsertSet(MADB_Stmt *Stmt, MADB_DynString *DynString);
30 my_bool MADB_DynStrGetWhere(MADB_Stmt *Stmt, MADB_DynString *DynString, char *TableName, my_bool ParameterMarkers);
31 my_bool MADB_DynStrAppendQuoted(MADB_DynString *DynString, char *String);
32 my_bool MADB_DynStrGetColumns(MADB_Stmt *Stmt, MADB_DynString *DynString);
33 my_bool MADB_DynStrGetValues(MADB_Stmt *Stmt, MADB_DynString *DynString);
34 SQLWCHAR* MADB_ConvertToWchar(const char *Ptr, SQLLEN PtrLength, Client_Charset* cc);
35 SQLLEN MADB_SetString(Client_Charset* cc, void *Dest, SQLULEN DestLength,
36 const char *Src, SQLLEN SrcLength, MADB_Error *Error);
37 my_bool MADB_ValidateStmt(MADB_QUERY *Query);
38
39 SQLLEN MbstrOctetLen(const char *str, SQLLEN *CharLen, MARIADB_CHARSET_INFO *cs);
40 SQLLEN MbstrCharLen(const char *str, SQLINTEGER OctetLen, MARIADB_CHARSET_INFO *cs);
41 SQLINTEGER SqlwcsCharLen(SQLWCHAR *str, SQLLEN octets);
42 SQLLEN SqlwcsLen(SQLWCHAR *str, SQLLEN buff_length);
43 SQLLEN SafeStrlen(SQLCHAR *str, SQLLEN buff_length);
44
45 #define ADJUST_LENGTH(ptr, len)\
46 if((ptr) && ((len) == SQL_NTS))\
47 len= sizeof(len) == 2 ? (SQLSMALLINT)strlen((ptr)) : (SQLINTEGER)strlen((ptr));\
48 else if (!(ptr))\
49 len= 0
50
51 #endif
0 /************************************************************************************
1 Copyright (C) 2017 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 /* ODBC C->SQL and SQL->C type conversion functions */
20
21 #include <ma_odbc.h>
22
23 /* Borrowed from C/C and adapted */
24 SQLRETURN MADB_Str2Ts(const char *Str, size_t Length, MYSQL_TIME *Tm, BOOL Interval, MADB_Error *Error, BOOL *isTime)
25 {
26 char *Start= MADB_ALLOC(Length + 1), *Frac, *End= Start + Length;
27 my_bool isDate= 0;
28
29 if (Start == NULL)
30 {
31 return MADB_SetError(Error, MADB_ERR_HY001, NULL, 0);
32 }
33
34 memset(Tm, 0, sizeof(MYSQL_TIME));
35 memcpy(Start, Str, Length);
36 Start[Length]= '\0';
37
38 while (Length && isspace(*Start)) Start++, Length--;
39
40 if (Length == 0)
41 {
42 return SQL_SUCCESS;//MADB_SetError(Error, MADB_ERR_22008, NULL, 0);
43 }
44
45 /* Determine time type:
46 MYSQL_TIMESTAMP_DATE: [-]YY[YY].MM.DD
47 MYSQL_TIMESTAMP_DATETIME: [-]YY[YY].MM.DD hh:mm:ss.mmmmmm
48 MYSQL_TIMESTAMP_TIME: [-]hh:mm:ss.mmmmmm
49 */
50 if (strchr(Start, '-'))
51 {
52 if (sscanf(Start, "%d-%u-%u", &Tm->year, &Tm->month, &Tm->day) < 3)
53 {
54 return MADB_SetError(Error, MADB_ERR_22008, NULL, 0);
55 }
56 isDate= 1;
57 if (!(Start= strchr(Start, ' ')))
58 {
59 goto check;
60 }
61 }
62 if (!strchr(Start, ':'))
63 {
64 goto check;
65 }
66
67 if (isDate == 0)
68 {
69 *isTime= 1;
70 }
71
72 if ((Frac= strchr(Start, '.')) != NULL) /* fractional seconds */
73 {
74 size_t FracMulIdx= End - (Frac + 1) - 1/*to get index array index */;
75 /* ODBC - nano-seconds */
76 if (sscanf(Start, "%d:%u:%u.%6lu", &Tm->hour, &Tm->minute,
77 &Tm->second, &Tm->second_part) < 4)
78 {
79 return MADB_SetError(Error, MADB_ERR_22008, NULL, 0);
80 }
81 /* 9 digits up to nano-seconds, and -1 since comparing with arr idx */
82 if (FracMulIdx < 6 - 1)
83 {
84 static unsigned long Mul[]= {100000, 10000, 1000, 100, 10};
85 Tm->second_part*= Mul[FracMulIdx];
86 }
87 }
88 else
89 {
90 if (sscanf(Start, "%d:%u:%u", &Tm->hour, &Tm->minute,
91 &Tm->second) < 3)
92 {
93 return MADB_SetError(Error, MADB_ERR_22008, NULL, 0);
94 }
95 }
96
97 check:
98 if (Interval == FALSE)
99 {
100 if (isDate)
101 {
102 if (Tm->year > 0)
103 {
104 if (Tm->year < 70)
105 {
106 Tm->year+= 2000;
107 }
108 else if (Tm->year < 100)
109 {
110 Tm->year+= 1900;
111 }
112 }
113 }
114 }
115
116 return SQL_SUCCESS;
117 }
118
119 /* {{{ MADB_ConversionSupported */
120 BOOL MADB_ConversionSupported(MADB_DescRecord *From, MADB_DescRecord *To)
121 {
122 switch (From->ConciseType)
123 {
124 case SQL_C_TIMESTAMP:
125 case SQL_C_TYPE_TIMESTAMP:
126 case SQL_C_TIME:
127 case SQL_C_TYPE_TIME:
128 case SQL_C_DATE:
129 case SQL_C_TYPE_DATE:
130
131 if (To->Type == SQL_INTERVAL)
132 {
133 return FALSE;
134 }
135
136 }
137 return TRUE;
138 }
139 /* }}} */
140
141 /* {{{ MADB_ConvertCharToBit */
142 char MADB_ConvertCharToBit(MADB_Stmt *Stmt, char *src)
143 {
144 char *EndPtr= NULL;
145 float asNumber= strtof(src, &EndPtr);
146
147 if (asNumber < 0 || asNumber > 1)
148 {
149 /* 22003 */
150 }
151 else if (asNumber != 0 && asNumber != 1)
152 {
153 /* 22001 */
154 }
155 else if (EndPtr != NULL && *EndPtr != '\0')
156 {
157 /* 22018. TODO: check if condition is correct */
158 }
159
160 return asNumber != 0 ? '\1' : '\0';
161 }
162 /* }}} */
163
164 /* {{{ MADB_ConvertNumericToChar */
165 size_t MADB_ConvertNumericToChar(SQL_NUMERIC_STRUCT *Numeric, char *Buffer, int *ErrorCode)
166 {
167 long long Numerator= 0;
168 long long Denominator= 1;
169 unsigned long long Left= 0, Right= 0;
170 int Scale= 0;
171 int ppos= 0;
172 long ByteDenominator= 1;
173 int i;
174 char *p;
175 my_bool hasDot= FALSE;
176
177 Buffer[0]= 0;
178 *ErrorCode= 0;
179
180 Scale+= (Numeric->scale < 0) ? -Numeric->scale : Numeric->scale;
181
182 for (i=0; i < SQL_MAX_NUMERIC_LEN; ++i)
183 {
184 Numerator+= Numeric->val[i] * ByteDenominator;
185 ByteDenominator<<= 8;
186 }
187 if (!Numeric->sign)
188 Numerator= -Numerator;
189 Denominator= (long long)pow(10, Scale);
190 Left= Numerator / Denominator;
191 //_i64toa_s(Numerator, Buffer, 38, 10);
192 if (Numeric->scale > 0)
193 {
194 char tmp[38];
195 _snprintf(tmp, 38, "%%.%df", Numeric->scale);
196 _snprintf(Buffer, 38, tmp, Numerator / pow(10, Scale));
197 }
198 else
199 {
200 _snprintf(Buffer, 38, "%lld", Numerator);
201 while (strlen(Buffer) < (size_t)(Numeric->precision - Numeric->scale))
202 strcat(Buffer, "0");
203 }
204
205
206 if (Buffer[0] == '-')
207 Buffer++;
208
209 /* Truncation checks:
210 1st ensure, that the digits before decimal point will fit */
211 if ((p= strchr(Buffer, '.')))
212 {
213 if (p - Buffer - 1 > Numeric->precision)
214 {
215 *ErrorCode= MADB_ERR_22003;
216 Buffer[Numeric->precision]= 0;
217 goto end;
218 }
219 if (Numeric->scale > 0 && Left > 0 && (p - Buffer) + strlen(p) > Numeric->precision)
220 {
221 *ErrorCode= MADB_ERR_01S07;
222 Buffer[Numeric->precision + 1]= 0;
223 goto end;
224 }
225 }
226 while (Numeric->scale < 0 && strlen(Buffer) < (size_t)(Numeric->precision - Numeric->scale))
227 strcat(Buffer, "0");
228
229
230 if (strlen(Buffer) > (size_t)(Numeric->precision + Scale) && Numeric->scale > 0)
231 *ErrorCode= MADB_ERR_01S07;
232
233 end:
234 /* check if last char is decimal point */
235 if (strlen(Buffer) && Buffer[strlen(Buffer)-1] == '.')
236 Buffer[strlen(Buffer)-1] = 0;
237 if (!Numeric->sign)
238 Buffer--;
239 return strlen(Buffer);
240 }
241 /* }}} */
242
243 /* {{{ MADB_ConvertNullValue */
244 SQLRETURN MADB_ConvertNullValue(MADB_Stmt *Stmt, MYSQL_BIND *MaBind)
245 {
246 MaBind->buffer_type= MYSQL_TYPE_NULL;
247 MaBind->buffer_length= 0;
248
249 return SQL_SUCCESS;
250 }
251 /* }}} */
252
253 /* {{{ MADB_ProcessIndicator */
254 /* Returns TRUE if indicator contains some special value, and thus no further type conversion is needed */
255 BOOL MADB_ProcessIndicator(MADB_Stmt *Stmt, SQLLEN Indicator, char * DefaultValue, MYSQL_BIND *MaBind)
256 {
257 switch (Indicator)
258 {
259 case SQL_COLUMN_IGNORE:
260 if (DefaultValue == NULL)
261 {
262 MADB_ConvertNullValue(Stmt, MaBind);
263 }
264 else
265 {
266 MaBind->buffer= DefaultValue;
267 MaBind->buffer_length= (unsigned long)strlen(DefaultValue);
268 MaBind->buffer_type= MYSQL_TYPE_STRING;
269 }
270 return TRUE;
271 case SQL_NULL_DATA:
272 MADB_ConvertNullValue(Stmt, MaBind);
273 return TRUE;
274 }
275
276 return FALSE;
277 }
278 /* }}} */
279
280 /* {{{ MADB_CalculateLength */
281 SQLLEN MADB_CalculateLength(MADB_Stmt *Stmt, SQLLEN *OctetLengthPtr, MADB_DescRecord *CRec, void* DataPtr)
282 {
283 /* If no OctetLengthPtr was specified, or OctetLengthPtr is SQL_NTS character
284 are considered to be NULL binary data are null terminated */
285 if (!OctetLengthPtr || *OctetLengthPtr == SQL_NTS)
286 {
287 /* Meaning of Buffer Length is not quite clear in specs. Thus we treat in the way, that does not break
288 (old) testcases. i.e. we neglect its value if Length Ptr is specified */
289 SQLLEN BufferLen= OctetLengthPtr ? -1 : CRec->OctetLength;
290
291 switch (CRec->ConciseType)
292 {
293 case SQL_C_WCHAR:
294 /* CRec->OctetLength eq 0 means not 0-length buffer, but that this value is not specified. Thus -1, for SqlwcsLen
295 and SafeStrlen that means buffer len is not specified */
296 return SqlwcsLen((SQLWCHAR *)DataPtr, BufferLen/sizeof(SQLWCHAR) - test(BufferLen == 0)) * sizeof(SQLWCHAR);
297 break;
298 case SQL_C_BINARY:
299 case SQL_VARBINARY:
300 case SQL_LONGVARBINARY:
301 case SQL_C_CHAR:
302 return SafeStrlen((SQLCHAR *)DataPtr, BufferLen != 0 ? BufferLen : -1);
303 }
304 }
305 else
306 {
307 return *OctetLengthPtr;
308 }
309
310 return CRec->OctetLength;
311 }
312 /* }}} */
313
314 /* {{{ MADB_GetBufferForSqlValue */
315 void* MADB_GetBufferForSqlValue(MADB_Stmt *Stmt, MADB_DescRecord *CRec, size_t Size)
316 {
317 if (Stmt->RebindParams || CRec->InternalBuffer == NULL)
318 {
319 MADB_FREE(CRec->InternalBuffer);
320 CRec->InternalBuffer= MADB_CALLOC(Size);
321 if (CRec->InternalBuffer == NULL)
322 {
323 MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
324 return NULL;
325 }
326 }
327
328 return (void *)CRec->InternalBuffer;
329 }
330 /* }}} */
331
332 /* {{{ MADB_Wchar2Sql */
333 SQLRETURN MADB_Wchar2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
334 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
335 {
336 SQLULEN mbLength=0;
337
338 MADB_FREE(CRec->InternalBuffer);
339
340 /* conn cs ? */
341 CRec->InternalBuffer= MADB_ConvertFromWChar((SQLWCHAR *)DataPtr, (SQLINTEGER)(Length / sizeof(SQLWCHAR)),
342 &mbLength, &Stmt->Connection->Charset, NULL);
343
344 if (CRec->InternalBuffer == NULL)
345 {
346 return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, NULL, 0);
347 }
348
349 *LengthPtr= (unsigned long)mbLength;
350 *Buffer= CRec->InternalBuffer;
351
352 MaBind->buffer_type= MYSQL_TYPE_STRING;
353
354 return SQL_SUCCESS;
355 }
356 /* }}} */
357
358 /* {{{ MADB_Char2Sql */
359 SQLRETURN MADB_Char2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
360 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
361 {
362 switch (SqlRec->Type)
363 {
364 case SQL_BIT:
365 if (*Buffer == NULL)
366 {
367 CRec->InternalBuffer= (char *)MADB_GetBufferForSqlValue(Stmt, CRec, MaBind->buffer_length);
368
369 if (CRec->InternalBuffer == NULL)
370 {
371 return Stmt->Error.ReturnValue;
372 }
373 *Buffer= CRec->InternalBuffer;
374 }
375
376 *LengthPtr= 1;
377 **(char**)Buffer= MADB_ConvertCharToBit(Stmt, DataPtr);
378 MaBind->buffer_type= MYSQL_TYPE_TINY;
379 break;
380 case SQL_DATETIME:
381 {
382 MYSQL_TIME Tm;
383 SQL_TIMESTAMP_STRUCT Ts;
384 BOOL isTime;
385
386 /* Enforcing constraints on date/time values */
387 RETURN_ERROR_OR_CONTINUE(MADB_Str2Ts(DataPtr, Length, &Tm, FALSE, &Stmt->Error, &isTime));
388 MADB_CopyMadbTimeToOdbcTs(&Tm, &Ts);
389 RETURN_ERROR_OR_CONTINUE(MADB_TsConversionIsPossible(&Ts, SqlRec->ConciseType, &Stmt->Error, MADB_ERR_22018, isTime));
390 /* To stay on the safe side - still sending as string in the default branch */
391 }
392 default:
393 /* Bulk shouldn't get here, thus logic for single paramset execution */
394 *LengthPtr= (unsigned long)Length;
395 *Buffer= DataPtr;
396 MaBind->buffer_type= MYSQL_TYPE_STRING;
397 }
398
399 return SQL_SUCCESS;
400 }
401 /* }}} */
402
403 /* {{{ MADB_Numeric2Sql */
404 SQLRETURN MADB_Numeric2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
405 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
406 {
407 SQL_NUMERIC_STRUCT *p;
408 int ErrorCode= 0;
409
410 /* We might need to preserve this pointer to be able to later release the memory */
411 CRec->InternalBuffer= (char *)MADB_GetBufferForSqlValue(Stmt, CRec, MADB_CHARSIZE_FOR_NUMERIC);
412
413 if (CRec->InternalBuffer == NULL)
414 {
415 return Stmt->Error.ReturnValue;
416 }
417
418 p= (SQL_NUMERIC_STRUCT *)DataPtr;
419 p->scale= (SQLSCHAR)SqlRec->Scale;
420 p->precision= (SQLSCHAR)SqlRec->Precision;
421
422 *LengthPtr= (unsigned long)MADB_ConvertNumericToChar((SQL_NUMERIC_STRUCT *)p, CRec->InternalBuffer, &ErrorCode);;
423 *Buffer= CRec->InternalBuffer;
424
425 MaBind->buffer_type= MYSQL_TYPE_STRING;
426
427 if (ErrorCode)
428 {
429 /*TODO: I guess this parameters row should be skipped */
430 return MADB_SetError(&Stmt->Error, ErrorCode, NULL, 0);
431 }
432
433 return SQL_SUCCESS;
434 }
435 /* }}} */
436
437 /* {{{ MADB_TsConversionIsPossible */
438 SQLRETURN MADB_TsConversionIsPossible(SQL_TIMESTAMP_STRUCT *ts, SQLSMALLINT SqlType, MADB_Error *Error, enum enum_madb_error SqlState, int isTime)
439 {
440 /* I think instead of MADB_ERR_22008 there should be also SqlState */
441 switch (SqlType)
442 {
443 case SQL_TIME:
444 case SQL_TYPE_TIME:
445 if (ts->fraction)
446 {
447 return MADB_SetError(Error, MADB_ERR_22008, NULL, 0);
448 }
449 break;
450 case SQL_DATE:
451 case SQL_TYPE_DATE:
452 if (ts->hour + ts->minute + ts->second + ts->fraction)
453 {
454 return MADB_SetError(Error, MADB_ERR_22008, NULL, 0);
455 }
456 default:
457 /* This only would be good for SQL_TYPE_TIME. If C type is time(isTime!=0), and SQL type is timestamp, date fields may be NULL - driver should set them to current date */
458 if ((isTime == 0 && ts->year == 0) || ts->month == 0 || ts->day == 0)
459 {
460 return MADB_SetError(Error, SqlState, NULL, 0);
461 }
462 }
463 return SQL_SUCCESS;
464 }
465 /* }}} */
466
467 /* {{{ MADB_Timestamp2Sql */
468 SQLRETURN MADB_Timestamp2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
469 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
470 {
471 MYSQL_TIME *tm= NULL;
472 SQL_TIMESTAMP_STRUCT *ts= (SQL_TIMESTAMP_STRUCT *)DataPtr;
473
474 RETURN_ERROR_OR_CONTINUE(MADB_TsConversionIsPossible(ts, SqlRec->ConciseType, &Stmt->Error, MADB_ERR_22007, 0));
475
476 if (*Buffer == NULL)
477 {
478 tm= (MYSQL_TIME*)MADB_GetBufferForSqlValue(Stmt, CRec, sizeof(MYSQL_TIME));
479 if (tm == NULL)
480 {
481 /* Error is set in function responsible for allocation */
482 return Stmt->Error.ReturnValue;
483 }
484 *Buffer= tm;
485 }
486 else
487 {
488 tm= *Buffer;
489 }
490
491
492 /* Default types. Not quite clear if time_type has any effect */
493 tm->time_type= MYSQL_TIMESTAMP_DATETIME;
494 MaBind->buffer_type= MYSQL_TYPE_TIMESTAMP;
495
496 switch (SqlRec->ConciseType) {
497 case SQL_TYPE_DATE:
498 if (ts->hour + ts->minute + ts->second + ts->fraction != 0)
499 {
500 return MADB_SetError(&Stmt->Error, MADB_ERR_22008, "Time fields are nonzero", 0);
501 }
502
503 MaBind->buffer_type= MYSQL_TYPE_DATE;
504 tm->time_type= MYSQL_TIMESTAMP_DATE;
505 tm->year= ts->year;
506 tm->month= ts->month;
507 tm->day= ts->day;
508 break;
509 case SQL_TYPE_TIME:
510 if (ts->fraction != 0)
511 {
512 return MADB_SetError(&Stmt->Error, MADB_ERR_22008, "Fractional seconds fields are nonzero", 0);
513 }
514
515 if (!VALID_TIME(ts))
516 {
517 return MADB_SetError(&Stmt->Error, MADB_ERR_22007, "Invalid time", 0);
518 }
519 MaBind->buffer_type= MYSQL_TYPE_TIME;
520 tm->time_type= MYSQL_TIMESTAMP_TIME;
521 tm->hour= ts->hour;
522 tm->minute= ts->minute;
523 tm->second= ts->second;
524 break;
525 default:
526 MADB_CopyOdbcTsToMadbTime(ts, tm);
527 }
528
529 *LengthPtr= sizeof(MYSQL_TIME);
530
531 return SQL_SUCCESS;
532 }
533 /* }}} */
534
535 /* {{{ MADB_Time2Sql */
536 SQLRETURN MADB_Time2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
537 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
538 {
539 MYSQL_TIME *tm= NULL;
540 SQL_TIME_STRUCT *ts= (SQL_TIME_STRUCT *)DataPtr;
541
542 if ((SqlRec->ConciseType == SQL_TYPE_TIME || SqlRec->ConciseType == SQL_TYPE_TIMESTAMP ||
543 SqlRec->ConciseType == SQL_TIME || SqlRec->ConciseType == SQL_TIMESTAMP || SqlRec->ConciseType == SQL_DATETIME) &&
544 !VALID_TIME(ts))
545 {
546 return MADB_SetError(&Stmt->Error, MADB_ERR_22007, NULL, 0);
547 }
548
549 if (*Buffer == NULL)
550 {
551 tm= (MYSQL_TIME*)MADB_GetBufferForSqlValue(Stmt, CRec, sizeof(MYSQL_TIME));
552 if (tm == NULL)
553 {
554 /* Error is set in function responsible for allocation */
555 return Stmt->Error.ReturnValue;
556 }
557 *Buffer= tm;
558 }
559 else
560 {
561 tm= *Buffer;
562 }
563
564 if(SqlRec->ConciseType == SQL_TYPE_TIMESTAMP ||
565 SqlRec->ConciseType == SQL_TIMESTAMP || SqlRec->ConciseType == SQL_DATETIME)
566 {
567 time_t sec_time;
568 struct tm * cur_tm;
569
570 sec_time= time(NULL);
571 cur_tm= localtime(&sec_time);
572
573 tm->year= 1900 + cur_tm->tm_year;
574 tm->month= cur_tm->tm_mon + 1;
575 tm->day= cur_tm->tm_mday;
576 tm->second_part= 0;
577 }
578 else
579 {
580 tm->year= 0;
581 tm->month= 0;
582 tm->day= 0;
583 }
584
585
586 tm->hour= ts->hour;
587 tm->minute= ts->minute;
588 tm->second= ts->second;
589
590 tm->second_part= 0;
591
592 tm->time_type= MYSQL_TIMESTAMP_DATETIME;
593
594 MaBind->buffer_type= MYSQL_TYPE_DATETIME;
595 *LengthPtr= sizeof(MYSQL_TIME);
596
597 return SQL_SUCCESS;
598 }
599 /* }}} */
600
601 /* {{{ MADB_IntervalHtoMS2Sql */
602 SQLRETURN MADB_IntervalHtoMS2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
603 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
604 {
605 MYSQL_TIME *tm= NULL;
606 SQL_INTERVAL_STRUCT *is= (SQL_INTERVAL_STRUCT *)DataPtr;
607
608 if (*Buffer == NULL)
609 {
610 tm= (MYSQL_TIME*)MADB_GetBufferForSqlValue(Stmt, CRec, sizeof(MYSQL_TIME));
611 if (tm == NULL)
612 {
613 /* Error is set in function responsible for allocation */
614 return Stmt->Error.ReturnValue;
615 }
616 *Buffer= tm;
617 }
618 else
619 {
620 tm= *Buffer;
621 }
622
623 tm->hour= is->intval.day_second.hour;
624 tm->minute= is->intval.day_second.minute;
625 tm->second= CRec->ConciseType == SQL_C_INTERVAL_HOUR_TO_SECOND ? is->intval.day_second.second : 0;
626
627 tm->second_part= 0;
628
629 tm->time_type= MYSQL_TIMESTAMP_TIME;
630 MaBind->buffer_type= MYSQL_TYPE_TIME;
631 *LengthPtr= sizeof(MYSQL_TIME);
632
633 return SQL_SUCCESS;
634 }
635 /* }}} */
636
637 /* {{{ MADB_Date2Sql */
638 SQLRETURN MADB_Date2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
639 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
640 {
641 MYSQL_TIME *tm= NULL, **BuffPtr= (MYSQL_TIME**)Buffer;
642 SQL_DATE_STRUCT *ts= (SQL_DATE_STRUCT *)DataPtr;
643
644 if (*BuffPtr == NULL)
645 {
646 tm= (MYSQL_TIME*)MADB_GetBufferForSqlValue(Stmt, CRec, sizeof(MYSQL_TIME));
647 if (tm == NULL)
648 {
649 /* Error is set in function responsible for allocation */
650 return Stmt->Error.ReturnValue;
651 }
652 *BuffPtr= tm;
653 }
654 else
655 {
656 tm= *BuffPtr;
657 }
658
659 tm->year= ts->year;
660 tm->month= ts->month;
661 tm->day= ts->day;
662
663 tm->hour= tm->minute= tm->second= tm->second_part= 0;
664 tm->time_type= MYSQL_TIMESTAMP_DATE;
665
666 MaBind->buffer_type= MYSQL_TYPE_DATE;
667 *LengthPtr= sizeof(MYSQL_TIME);
668
669 return SQL_SUCCESS;
670 }
671 /* }}} */
672
673 /* {{{ MADB_ConvertC2Sql */
674 SQLRETURN MADB_ConvertC2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
675 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr)
676 {
677 if (Buffer == NULL)
678 {
679 MaBind->buffer= NULL;
680 Buffer= &MaBind->buffer;
681 }
682 if (LengthPtr == NULL)
683 {
684 LengthPtr= &MaBind->buffer_length;
685 }
686 /* Switch to fill BIND structures based on C and SQL type */
687 switch (CRec->ConciseType)
688 {
689 case WCHAR_TYPES:
690 RETURN_ERROR_OR_CONTINUE(MADB_Wchar2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
691 break;
692 case CHAR_BINARY_TYPES:
693 RETURN_ERROR_OR_CONTINUE(MADB_Char2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
694 break;
695 case SQL_C_NUMERIC:
696 RETURN_ERROR_OR_CONTINUE(MADB_Numeric2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
697 break;
698 case SQL_C_TIMESTAMP:
699 case SQL_TYPE_TIMESTAMP:
700 RETURN_ERROR_OR_CONTINUE(MADB_Timestamp2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
701 break;
702 case SQL_C_TIME:
703 case SQL_C_TYPE_TIME:
704 RETURN_ERROR_OR_CONTINUE(MADB_Time2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
705 break;
706 case SQL_C_INTERVAL_HOUR_TO_MINUTE:
707 case SQL_C_INTERVAL_HOUR_TO_SECOND:
708 RETURN_ERROR_OR_CONTINUE(MADB_IntervalHtoMS2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
709 break;
710 case SQL_C_DATE:
711 case SQL_TYPE_DATE:
712 RETURN_ERROR_OR_CONTINUE(MADB_Date2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, Buffer, LengthPtr));
713 break;
714 default:
715 /* memset(MaBind, 0, sizeof(MYSQL_BIND));
716 MaBind->buffer_length= 0; */
717 MaBind->buffer_type= 0;
718 MaBind->is_unsigned= 0;
719
720 *LengthPtr= (unsigned long)Length;
721 MaBind->buffer_type= MADB_GetMaDBTypeAndLength(CRec->ConciseType,
722 &MaBind->is_unsigned, &MaBind->buffer_length);
723
724 if (!CRec->OctetLength)
725 {
726 CRec->OctetLength= MaBind->buffer_length;
727 }
728 *Buffer= DataPtr;
729 } /* End of switch (CRec->ConsiseType) */
730
731 return SQL_SUCCESS;
732 }
733 /* }}} */
734
735 /* {{{ MADB_C2SQL */
736 /* Main entrance function for C type to SQL type conversion*/
737 SQLRETURN MADB_C2SQL(MADB_Stmt* Stmt, MADB_DescRecord *CRec, MADB_DescRecord *SqlRec, SQLULEN ParamSetIdx, MYSQL_BIND *MaBind)
738 {
739 SQLLEN *IndicatorPtr= NULL;
740 SQLLEN *OctetLengthPtr= NULL;
741 void *DataPtr= NULL;
742 SQLLEN Length= 0;
743
744 IndicatorPtr= (SQLLEN *)GetBindOffset(Stmt->Apd, CRec, CRec->IndicatorPtr, ParamSetIdx, sizeof(SQLLEN));
745 OctetLengthPtr= (SQLLEN *)GetBindOffset(Stmt->Apd, CRec, CRec->OctetLengthPtr, ParamSetIdx, sizeof(SQLLEN));
746
747 if (PARAM_IS_DAE(OctetLengthPtr))
748 {
749 if (!DAE_DONE(Stmt))
750 {
751 return SQL_NEED_DATA;
752 }
753 else
754 {
755 MaBind->buffer_type= MADB_GetMaDBTypeAndLength(CRec->ConciseType, &MaBind->is_unsigned, &MaBind->buffer_length);
756 /* I guess we can leave w/out this. Keeping it so far for safety */
757 MaBind->long_data_used= '\1';
758 return SQL_SUCCESS;
759 }
760 } /* -- End of DAE parameter processing -- */
761
762 if (IndicatorPtr && MADB_ProcessIndicator(Stmt, *IndicatorPtr, CRec->DefaultValue, MaBind))
763 {
764 return SQL_SUCCESS;
765 }
766
767 /* -- Special cases are done, i.e. not a DAE etc, general case -- */
768
769 DataPtr= GetBindOffset(Stmt->Apd, CRec, CRec->DataPtr, ParamSetIdx, CRec->OctetLength);
770
771 /* If indicator wasn't NULL_DATA, but data pointer is still NULL, we convert NULL value */
772 if (!DataPtr)
773 {
774 return MADB_ConvertNullValue(Stmt, MaBind);
775 }
776
777 Length= MADB_CalculateLength(Stmt, OctetLengthPtr, CRec, DataPtr);
778
779 RETURN_ERROR_OR_CONTINUE(MADB_ConvertC2Sql(Stmt, CRec, DataPtr, Length, SqlRec, MaBind, NULL, NULL));
780
781 return SQL_SUCCESS;
782 }
783 /* }}} */
0 /************************************************************************************
1 Copyright (C) 2017 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 #pragma once
20 #ifndef _ma_typeconv_h
21 #define _ma_typeconv_h
22
23 /* Argument should be pointer to SQL_TIMESTAMP_STRUCT or MYSQL_TIME */
24 #define VALID_TIME(PTR2TM_OR_TS) (PTR2TM_OR_TS->hour < 24 && PTR2TM_OR_TS->minute < 60 && PTR2TM_OR_TS->second < 60)
25 #define MADB_CHARSIZE_FOR_NUMERIC 80
26 BOOL MADB_ConversionSupported(MADB_DescRecord *From, MADB_DescRecord *To);
27 size_t MADB_ConvertNumericToChar(SQL_NUMERIC_STRUCT *Numeric, char *Buffer, int *ErrorCode);
28 SQLLEN MADB_CalculateLength(MADB_Stmt *Stmt, SQLLEN *OctetLengthPtr, MADB_DescRecord *CRec, void* DataPtr);
29 SQLRETURN MADB_C2SQL(MADB_Stmt* Stmt, MADB_DescRecord *CRec, MADB_DescRecord *SqlRec, SQLULEN ParamSetIdx, MYSQL_BIND *bind);
30
31 SQLRETURN MADB_Wchar2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
32 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
33 SQLRETURN MADB_Char2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
34 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
35 SQLRETURN MADB_Numeric2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
36 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
37 SQLRETURN MADB_Timestamp2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
38 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
39 SQLRETURN MADB_Time2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
40 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
41 SQLRETURN MADB_IntervalHtoMS2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
42 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
43 SQLRETURN MADB_Date2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
44 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
45
46 SQLRETURN MADB_ConvertC2Sql(MADB_Stmt *Stmt, MADB_DescRecord *CRec, void* DataPtr, SQLLEN Length,
47 MADB_DescRecord *SqlRec, MYSQL_BIND *MaBind, void **Buffer, unsigned long *LengthPtr);
48
49 SQLRETURN MADB_TsConversionIsPossible(SQL_TIMESTAMP_STRUCT *ts, SQLSMALLINT SqlType, MADB_Error *Error, enum enum_madb_error SqlState, int isTime);
50 SQLRETURN MADB_Str2Ts(const char *Str, size_t Length, MYSQL_TIME *Tm, BOOL Interval, MADB_Error *Error, BOOL *isTime);
51
52 #endif
0 {
1 global:
2 SQLAllocConnect;
3 SQLAllocEnv;
4 SQLAllocHandle;
5 SQLAllocStmt;
6 SQLBindCol;
7 SQLBindParameter;
8 SQLBrowseConnect;
9 SQLBrowseConnectW;
10 SQLBulkOperations;
11 SQLCancel;
12 SQLCloseCursor;
13 SQLColAttribute;
14 SQLColAttributeW;
15 SQLColAttributes;
16 SQLColAttributesW;
17 SQLColumnPrivileges;
18 SQLColumnPrivilegesW;
19 SQLColumns;
20 SQLColumnsW;
21 SQLConnect;
22 SQLConnectW;
23 SQLCopyDesc;
24 SQLDescribeCol;
25 SQLDescribeColW;
26 SQLDescribeParam;
27 SQLDisconnect;
28 SQLDriverConnect;
29 SQLDriverConnectW;
30 SQLEndTran;
31 SQLError;
32 SQLErrorW;
33 SQLExecDirect;
34 SQLExecDirectW;
35 SQLExecute;
36 SQLExtendedFetch;
37 SQLFetch;
38 SQLFetchScroll;
39 SQLForeignKeys;
40 SQLForeignKeysW;
41 SQLFreeConnect;
42 SQLFreeEnv;
43 SQLFreeHandle;
44 SQLFreeStmt;
45 SQLGetConnectAttr;
46 SQLGetConnectAttrW;
47 SQLGetConnectOption;
48 SQLGetConnectOptionW;
49 SQLGetCursorName;
50 SQLGetCursorNameW;
51 SQLGetData;
52 SQLGetDescField;
53 SQLGetDescFieldW;
54 SQLGetDescRec;
55 SQLGetDescRecW;
56 SQLGetDiagField;
57 SQLGetDiagFieldW;
58 SQLGetDiagRec;
59 SQLGetDiagRecW;
60 SQLGetEnvAttr;
61 SQLGetFunctions;
62 SQLGetInfo;
63 SQLGetInfoW;
64 SQLGetStmtAttr;
65 SQLGetStmtAttrW;
66 SQLGetStmtOption;
67 SQLGetTypeInfo;
68 SQLGetTypeInfoW;
69 SQLMoreResults;
70 SQLNativeSql;
71 SQLNativeSqlW;
72 SQLNumParams;
73 SQLNumResultCols;
74 SQLParamData;
75 SQLParamOptions;
76 SQLPrepare;
77 SQLPrepareW;
78 SQLPrimaryKeys;
79 SQLPrimaryKeysW;
80 SQLProcedureColumns;
81 SQLProcedureColumnsW;
82 SQLProcedures;
83 SQLProceduresW;
84 SQLPutData;
85 SQLRowCount;
86 SQLSetConnectAttr;
87 SQLSetConnectAttrW;
88 SQLSetConnectOption;
89 SQLSetConnectOptionW;
90 SQLSetCursorName;
91 SQLSetCursorNameW;
92 SQLSetDescField;
93 SQLSetDescFieldW;
94 SQLSetDescRec;
95 SQLSetDescRecW;
96 SQLSetEnvAttr;
97 SQLSetParam;
98 SQLSetPos;
99 SQLSetScrollOptions;
100 SQLSetStmtAttr;
101 SQLSetStmtAttrW;
102 SQLSetStmtOption;
103 SQLSpecialColumns;
104 SQLSpecialColumnsW;
105 SQLStatistics;
106 SQLStatisticsW;
107 SQLTablePrivileges;
108 SQLTablePrivilegesW;
109 SQLTables;
110 SQLTablesW;
111 SQLTransact;
112 local:
113 *;
114 };
Binary diff not shown
0 // Microsoft Visual C++ generated resource script.
1 //
2 #include "stringinfo.h"
3
4 #define APSTUDIO_READONLY_SYMBOLS
5 /////////////////////////////////////////////////////////////////////////////
6 //
7 // Generated from the TEXTINCLUDE 2 resource.
8 //
9 #include "WinResrc.h"
10
11 /////////////////////////////////////////////////////////////////////////////
12 #undef APSTUDIO_READONLY_SYMBOLS
13
14 /////////////////////////////////////////////////////////////////////////////
15 // Deutsch (Deutschland) resources
16
17 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
18 LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
19
20 #ifdef APSTUDIO_INVOKED
21 /////////////////////////////////////////////////////////////////////////////
22 //
23 // TEXTINCLUDE
24 //
25
26 1 TEXTINCLUDE
27 BEGIN
28 "resource3.h\0"
29 END
30
31 2 TEXTINCLUDE
32 BEGIN
33 "#include ""afxres.h""\r\n"
34 "\0"
35 END
36
37 3 TEXTINCLUDE
38 BEGIN
39 "\r\n"
40 "\0"
41 END
42
43 #endif // APSTUDIO_INVOKED
44
45
46 /////////////////////////////////////////////////////////////////////////////
47 //
48 // Version
49 //
50
51 VS_VERSION_INFO VERSIONINFO
52 FILEVERSION 3,1,1,0
53 PRODUCTVERSION 3,1,1,0
54 FILEFLAGSMASK 0x3fL
55 #ifdef _DEBUG
56 FILEFLAGS 0x1L
57 #else
58 FILEFLAGS 0x0L
59 #endif
60 FILEOS 0x40004L
61 FILETYPE 0x0L
62 FILESUBTYPE 0x0L
63 BEGIN
64 BLOCK "StringFileInfo"
65 BEGIN
66 BLOCK "040704b0"
67 BEGIN
68 VALUE "CompanyName", "MariaDB Corporation AB"
69 VALUE "FileDescription", "MariaDB ODBC Unicode Driver"
70 VALUE "FileVersion", "3.1.1.0"
71 VALUE "InternalName", "ma_odbc_u"
72 VALUE "LegalCopyright", "Copyright (C) 2013, 2019"
73 VALUE "OriginalFilename", "maodbc.dll"
74 VALUE "ProductName", "MariaDB ODBC Unicode Driver"
75 VALUE "ProductVersion", "3.1.1.0"
76 END
77 END
78 BLOCK "VarFileInfo"
79 BEGIN
80 VALUE "Translation", 0x407, 1200
81 END
82 END
83
84 #endif // Deutsch (Deutschland) resources
85 /////////////////////////////////////////////////////////////////////////////
86
87
88
89 #ifndef APSTUDIO_INVOKED
90 /////////////////////////////////////////////////////////////////////////////
91 //
92 // Generated from the TEXTINCLUDE 3 resource.
93 //
94
95
96 /////////////////////////////////////////////////////////////////////////////
97 #endif // not APSTUDIO_INVOKED
98
0 LIBRARY @LIBRARY_NAME@.dll
1 EXPORTS
2 DllMain
3 SQLAllocConnect
4 SQLAllocEnv
5 SQLAllocHandle
6 SQLAllocStmt
7 SQLBindCol
8 SQLBindParameter
9 SQLBrowseConnect
10 SQLBrowseConnect@UNICODE@
11 SQLBulkOperations
12 SQLCancel
13 SQLCloseCursor
14 SQLColAttribute
15 SQLColAttribute@UNICODE@
16 SQLColAttributes
17 SQLColAttributes@UNICODE@
18 SQLColumnPrivileges
19 SQLColumnPrivileges@UNICODE@
20 SQLColumns
21 SQLColumns@UNICODE@
22 SQLConnect
23 SQLConnect@UNICODE@
24 SQLCopyDesc
25 SQLDescribeCol
26 SQLDescribeCol@UNICODE@
27 SQLDescribeParam
28 SQLDisconnect
29 SQLDriverConnect
30 SQLDriverConnect@UNICODE@
31 SQLEndTran
32 SQLError
33 SQLError@UNICODE@
34 SQLExecDirect
35 SQLExecDirect@UNICODE@
36 SQLExecute
37 SQLExtendedFetch
38 SQLFetch
39 SQLFetchScroll
40 SQLForeignKeys
41 SQLForeignKeys@UNICODE@
42 SQLFreeConnect
43 SQLFreeEnv
44 SQLFreeHandle
45 SQLFreeStmt
46 SQLGetConnectAttr
47 SQLGetConnectAttr@UNICODE@
48 SQLGetConnectOption
49 SQLGetConnectOption@UNICODE@
50 SQLGetCursorName
51 SQLGetCursorName@UNICODE@
52 SQLGetData
53 SQLGetDescField
54 SQLGetDescField@UNICODE@
55 SQLGetDescRec
56 SQLGetDescRec@UNICODE@
57 SQLGetDiagField
58 SQLGetDiagField@UNICODE@
59 SQLGetDiagRec
60 SQLGetDiagRec@UNICODE@
61 SQLGetEnvAttr
62 SQLGetFunctions
63 SQLGetInfo
64 SQLGetInfo@UNICODE@
65 SQLGetStmtAttr
66 SQLGetStmtAttr@UNICODE@
67 SQLGetStmtOption
68 SQLGetTypeInfo
69 SQLGetTypeInfo@UNICODE@
70 SQLMoreResults
71 SQLNativeSql
72 SQLNativeSql@UNICODE@
73 SQLNumParams
74 SQLNumResultCols
75 SQLParamData
76 SQLParamOptions
77 SQLPrepare
78 SQLPrepare@UNICODE@
79 SQLPrimaryKeys
80 SQLPrimaryKeys@UNICODE@
81 SQLProcedureColumns
82 SQLProcedureColumns@UNICODE@
83 SQLProcedures
84 SQLProcedures@UNICODE@
85 SQLPutData
86 SQLRowCount
87 SQLSetConnectAttr
88 SQLSetConnectAttr@UNICODE@
89 SQLSetConnectOption
90 SQLSetConnectOption@UNICODE@
91 SQLSetCursorName
92 SQLSetCursorName@UNICODE@
93 SQLSetDescField
94 SQLSetDescField@UNICODE@
95 SQLSetDescRec
96 SQLSetDescRec@UNICODE@
97 SQLSetEnvAttr
98 SQLSetParam
99 SQLSetPos
100 SQLSetScrollOptions
101 SQLSetStmtAttr
102 SQLSetStmtAttr@UNICODE@
103 SQLSetStmtOption
104 SQLSpecialColumns
105 SQLSpecialColumns@UNICODE@
106 SQLStatistics
107 SQLStatistics@UNICODE@
108 SQLTablePrivileges
109 SQLTablePrivileges@UNICODE@
110 SQLTables
111 SQLTables@UNICODE@
112 SQLTransact
0 /************************************************************************************
1 Copyright (C) 2013,2016 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18 #undef MA_ODBC_DEBUG_ALL
19
20 #include <ma_odbc.h>
21
22 extern Client_Charset utf8;
23
24 /* {{{ SQLAllocHandle */
25 SQLRETURN MA_SQLAllocHandle(SQLSMALLINT HandleType,
26 SQLHANDLE InputHandle,
27 SQLHANDLE *OutputHandlePtr)
28 {
29 SQLRETURN ret= SQL_ERROR;
30
31 switch(HandleType) {
32 case SQL_HANDLE_DBC:
33 EnterCriticalSection(&((MADB_Env *)InputHandle)->cs);
34 MADB_CLEAR_ERROR(&((MADB_Env *)InputHandle)->Error);
35 if ((*OutputHandlePtr= (SQLHANDLE)MADB_DbcInit((MADB_Env *)InputHandle)) != NULL)
36 {
37 ret= SQL_SUCCESS;
38 }
39 LeaveCriticalSection(&((MADB_Env *)InputHandle)->cs);
40 break;
41 case SQL_HANDLE_DESC:
42 EnterCriticalSection(&((MADB_Dbc *)InputHandle)->cs);
43 MADB_CLEAR_ERROR(&((MADB_Dbc *)InputHandle)->Error);
44 if ((*OutputHandlePtr= (SQLHANDLE)MADB_DescInit((MADB_Dbc *)InputHandle, MADB_DESC_UNKNOWN, TRUE)) != NULL)
45 {
46 ret= SQL_SUCCESS;
47 }
48 LeaveCriticalSection(&((MADB_Dbc *)InputHandle)->cs);
49 break;
50 case SQL_HANDLE_ENV:
51 if ((*OutputHandlePtr= (SQLHANDLE)MADB_EnvInit()) != NULL)
52 {
53 ret= SQL_SUCCESS;
54 }
55 break;
56 case SQL_HANDLE_STMT:
57 {
58 MADB_Dbc *Connection= (MADB_Dbc *)InputHandle;
59 MDBUG_C_ENTER(InputHandle, "MA_SQLAllocHandle(Stmt)");
60 MDBUG_C_DUMP(InputHandle, InputHandle, 0x);
61 MDBUG_C_DUMP(InputHandle, OutputHandlePtr, 0x);
62
63 MADB_CLEAR_ERROR(&Connection->Error);
64
65 if (!CheckConnection(Connection))
66 {
67 MADB_SetError(&Connection->Error, MADB_ERR_08003, NULL, 0);
68 break;
69 }
70
71 ret= MADB_StmtInit(Connection, OutputHandlePtr);
72 MDBUG_C_DUMP(InputHandle, *OutputHandlePtr, 0x);
73 MDBUG_C_RETURN(InputHandle,ret, &Connection->Error);
74 }
75 break;
76 default:
77 /* todo: set error message */
78 break;
79 }
80 return ret;
81 }
82 /* }}} */
83
84 /* {{{ SQLAllocHandle */
85 SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType,
86 SQLHANDLE InputHandle,
87 SQLHANDLE *OutputHandlePtr)
88 {
89 SQLRETURN ret;
90 MDBUG_ENTER("SQLAllocHandle");
91 MDBUG_DUMP(HandleType, d);
92 MDBUG_DUMP(InputHandle, 0x);
93 MDBUG_DUMP(OutputHandlePtr, 0x);
94
95 ret= MA_SQLAllocHandle(HandleType, InputHandle, OutputHandlePtr);
96
97 MDBUG_DUMP(ret,d);
98 MDBUG_RETURN(ret);
99 }
100 /* }}} */
101
102 /* {{{ SQLAllocConnect */
103 SQLRETURN MA_SQLAllocConnect(SQLHANDLE InputHandle,
104 SQLHANDLE *OutputHandlePtr)
105 {
106 return MA_SQLAllocHandle(SQL_HANDLE_DBC, InputHandle, OutputHandlePtr);
107 }
108 SQLRETURN SQL_API SQLAllocConnect(SQLHANDLE InputHandle,
109 SQLHANDLE *OutputHandlePtr)
110 {
111 return MA_SQLAllocConnect(InputHandle, OutputHandlePtr);
112 }
113 /* }}} */
114
115 /* {{{ SQLAllocStmt */
116 SQLRETURN SQL_API SQLAllocStmt(SQLHANDLE InputHandle,
117 SQLHANDLE *OutputHandlePtr)
118 {
119 MDBUG_C_ENTER(InputHandle, "SQLAllocStmt");
120 MDBUG_C_DUMP(InputHandle, InputHandle, 0x);
121 MDBUG_C_DUMP(InputHandle, OutputHandlePtr, 0x);
122
123 return MA_SQLAllocHandle(SQL_HANDLE_STMT, InputHandle, OutputHandlePtr);
124 }
125 /* }}} */
126
127 /* {{{ SQLAllocEnv */
128 SQLRETURN SQL_API SQLAllocEnv(SQLHANDLE *OutputHandlePtr)
129 {
130 return MA_SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, OutputHandlePtr);
131 }
132 /* }}} */
133
134 /* {{{ SQLBindCol */
135 SQLRETURN SQL_API SQLBindCol(SQLHSTMT StatementHandle,
136 SQLUSMALLINT ColumnNumber,
137 SQLSMALLINT TargetType,
138 SQLPOINTER TargetValuePtr,
139 SQLLEN BufferLength,
140 SQLLEN *StrLen_or_Ind)
141 {
142 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
143 SQLRETURN ret;
144 MADB_CLEAR_ERROR(&Stmt->Error);
145 MADB_CHECK_STMT_HANDLE(Stmt,stmt);
146
147 MDBUG_C_ENTER(Stmt->Connection, "SQLBindCol");
148 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
149 MDBUG_C_DUMP(Stmt->Connection, ColumnNumber, u);
150 MDBUG_C_DUMP(Stmt->Connection, TargetType, d);
151 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d);
152 MDBUG_C_DUMP(Stmt->Connection, StrLen_or_Ind, 0x);
153
154 ret= Stmt->Methods->BindColumn(Stmt, ColumnNumber, TargetType, TargetValuePtr, BufferLength, StrLen_or_Ind);
155
156 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
157 }
158 /* }}} */
159
160 /* {{{ MA_SQLBindParameter */
161 SQLRETURN MA_SQLBindParameter(SQLHSTMT StatementHandle,
162 SQLUSMALLINT ParameterNumber,
163 SQLSMALLINT InputOutputType,
164 SQLSMALLINT ValueType,
165 SQLSMALLINT ParameterType,
166 SQLULEN ColumnSize,
167 SQLSMALLINT DecimalDigits,
168 SQLPOINTER ParameterValuePtr,
169 SQLLEN BufferLength,
170 SQLLEN *StrLen_or_IndPtr)
171 {
172 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
173 SQLRETURN ret;
174
175 if (!Stmt)
176 return SQL_INVALID_HANDLE;
177
178 MDBUG_C_ENTER(Stmt->Connection, "SQLBindParameter");
179 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
180 MDBUG_C_DUMP(Stmt->Connection, ParameterNumber, u);
181 MDBUG_C_DUMP(Stmt->Connection, InputOutputType, d);
182 MDBUG_C_DUMP(Stmt->Connection, ValueType, d);
183 MDBUG_C_DUMP(Stmt->Connection, ParameterType, d);
184 MDBUG_C_DUMP(Stmt->Connection, ColumnSize, u);
185 MDBUG_C_DUMP(Stmt->Connection, DecimalDigits, d);
186 MDBUG_C_DUMP(Stmt->Connection, ParameterValuePtr, 0x);
187 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d);
188 MDBUG_C_DUMP(Stmt->Connection, StrLen_or_IndPtr, 0x);
189
190 MADB_CHECK_STMT_HANDLE(Stmt,stmt);
191 ret= Stmt->Methods->BindParam(Stmt, ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize, DecimalDigits,
192 ParameterValuePtr, BufferLength, StrLen_or_IndPtr);
193
194 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
195 }
196 /* }}} */
197
198 /* {{{ SQLBindParameter */
199 SQLRETURN SQL_API SQLBindParameter(SQLHSTMT StatementHandle,
200 SQLUSMALLINT ParameterNumber,
201 SQLSMALLINT InputOutputType,
202 SQLSMALLINT ValueType,
203 SQLSMALLINT ParameterType,
204 SQLULEN ColumnSize,
205 SQLSMALLINT DecimalDigits,
206 SQLPOINTER ParameterValuePtr,
207 SQLLEN BufferLength,
208 SQLLEN *StrLen_or_IndPtr)
209 {
210 if (!StatementHandle)
211 return SQL_INVALID_HANDLE;
212 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
213 return MA_SQLBindParameter(StatementHandle, ParameterNumber, InputOutputType, ValueType, ParameterType,
214 ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, StrLen_or_IndPtr);
215 }
216 /* }}} */
217
218 /* {{{ SQLBrowseConnect */
219 SQLRETURN SQL_API SQLBrowseConnect(SQLHDBC ConnectionHandle,
220 SQLCHAR *InConnectionString,
221 SQLSMALLINT StringLength1,
222 SQLCHAR *OutConnectionString,
223 SQLSMALLINT BufferLength,
224 SQLSMALLINT *StringLength2Ptr)
225 {
226 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
227 SQLRETURN ret;
228 MDBUG_C_ENTER(Dbc, "SQLBrowseConnect");
229 MADB_SetError(&Dbc->Error, MADB_ERR_IM001, NULL, 0);
230 ret= Dbc->Error.ReturnValue;
231
232 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
233 }
234 /* }}} */
235
236 /* {{{ SQLBrowseConnectW */
237 SQLRETURN SQL_API SQLBrowseConnectW(SQLHDBC ConnectionHandle,
238 SQLWCHAR *InConnectionString,
239 SQLSMALLINT StringLength1,
240 SQLWCHAR *OutConnectionString,
241 SQLSMALLINT BufferLength,
242 SQLSMALLINT *StringLength2Ptr)
243 {
244 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
245 SQLRETURN ret;
246 MDBUG_C_ENTER(Dbc, SQLBrowseConnectW);
247 MADB_SetError(&Dbc->Error, MADB_ERR_IM001, NULL, 0);
248 ret= Dbc->Error.ReturnValue;
249
250 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
251 }
252 /* }}} */
253
254 /* {{{ SQLBulkOperations */
255 SQLRETURN SQL_API SQLBulkOperations(SQLHSTMT StatementHandle,
256 SQLSMALLINT Operation)
257 {
258 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
259 SQLRETURN ret;
260 if (!Stmt)
261 return SQL_INVALID_HANDLE;
262 MADB_CLEAR_ERROR(&Stmt->Error);
263
264 MDBUG_C_ENTER(Stmt->Connection, "SQLBulkOperations");
265 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
266 MDBUG_C_DUMP(Stmt->Connection, Operation, d);
267
268 ret= Stmt->Methods->BulkOperations(Stmt, Operation);
269
270 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
271 }
272 /* }}} */
273
274 /* {{{ SQLCancel */
275 SQLRETURN MA_SQLCancel(SQLHSTMT StatementHandle)
276 {
277 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
278 SQLRETURN ret= SQL_ERROR;
279
280 if (!Stmt)
281 return SQL_INVALID_HANDLE;
282
283 MADB_CLEAR_ERROR(&Stmt->Error);
284
285 MDBUG_C_ENTER(Stmt->Connection, "SQLCancel");
286 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
287
288 if (TryEnterCriticalSection(&Stmt->Connection->cs))
289 {
290 LeaveCriticalSection(&Stmt->Connection->cs);
291 ret= Stmt->Methods->StmtFree(Stmt, SQL_CLOSE);
292
293 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
294 } else
295 {
296 MYSQL *MariaDb, *Kill=Stmt->Connection->mariadb;
297
298 char StmtStr[30];
299
300 if (!(MariaDb= mysql_init(NULL)))
301 {
302 ret= SQL_ERROR;
303 goto end;
304 }
305 if (!(mysql_real_connect(MariaDb, Kill->host, Kill->user, Kill->passwd,
306 "", Kill->port, Kill->unix_socket, 0)))
307 {
308 mysql_close(MariaDb);
309 goto end;
310 }
311
312 _snprintf(StmtStr, 30, "KILL QUERY %ld", mysql_thread_id(Kill));
313 if (mysql_query(MariaDb, StmtStr))
314 {
315 mysql_close(MariaDb);
316 goto end;
317 }
318 mysql_close(MariaDb);
319 ret= SQL_SUCCESS;
320 }
321 end:
322 LeaveCriticalSection(&Stmt->Connection->cs);
323
324 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
325 }
326
327 SQLRETURN SQL_API SQLCancel(SQLHSTMT StatementHandle)
328 {
329 return MA_SQLCancel(StatementHandle);
330 }
331 /* }}} */
332
333 /* {{{ SQLCancelHandle */
334 /* ODBC version 3.8 */
335 SQLRETURN SQL_API SQLCancelHandle(SQLSMALLINT HandleType,
336 SQLHANDLE Handle)
337 {
338 if (Handle)
339 return SQL_INVALID_HANDLE;
340
341 switch(HandleType) {
342 case SQL_HANDLE_DBC:
343 {
344 MADB_Stmt Stmt;
345 Stmt.Connection= (MADB_Dbc *)Handle;
346 return MA_SQLCancel((SQLHSTMT)&Stmt);
347 }
348 break;
349 case SQL_HANDLE_STMT:
350 return MA_SQLCancel((SQLHSTMT)Handle);
351 break;
352 }
353 return SQL_INVALID_HANDLE;
354 }
355 /* }}} */
356
357 /* {{{ SQLCloseCursor */
358 SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT StatementHandle)
359 {
360 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
361 SQLRETURN ret;
362 if (!Stmt)
363 return SQL_INVALID_HANDLE;
364
365 MADB_CLEAR_ERROR(&Stmt->Error);
366
367 MDBUG_C_ENTER(Stmt->Connection, "SQLCloseCursor");
368 MDBUG_C_DUMP(Stmt->Connection, StatementHandle, 0x);
369
370 if (!Stmt->stmt ||
371 (!mysql_stmt_field_count(Stmt->stmt) &&
372 Stmt->Connection->Environment->OdbcVersion >= SQL_OV_ODBC3))
373 {
374 MADB_SetError(&Stmt->Error, MADB_ERR_24000, NULL, 0);
375 ret= Stmt->Error.ReturnValue;
376 }
377 else
378 ret= MA_SQLFreeStmt(StatementHandle, SQL_CLOSE);
379
380 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
381 }
382 /* }}} */
383
384 /* {{{ SQLColAttribute */
385 SQLRETURN SQL_API SQLColAttribute (SQLHSTMT StatementHandle,
386 SQLUSMALLINT ColumnNumber,
387 SQLUSMALLINT FieldIdentifier,
388 SQLPOINTER CharacterAttributePtr,
389 SQLSMALLINT BufferLength,
390 SQLSMALLINT *StringLengthPtr,
391 #ifdef SQLCOLATTRIB_SQLPOINTER
392 SQLPOINTER NumericAttributePtr
393 #else
394 SQLLEN *NumericAttributePtr
395 #endif
396 )
397 {
398 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
399 SQLRETURN ret;
400 if (!Stmt)
401 return SQL_INVALID_HANDLE;
402
403 MADB_CLEAR_ERROR(&Stmt->Error);
404
405 MDBUG_C_ENTER(Stmt->Connection, "SQLColAttribute");
406 MDBUG_C_DUMP(Stmt->Connection, StatementHandle, 0x);
407 MDBUG_C_DUMP(Stmt->Connection, ColumnNumber, u);
408 MDBUG_C_DUMP(Stmt->Connection, FieldIdentifier, u);
409 MDBUG_C_DUMP(Stmt->Connection, CharacterAttributePtr, 0x);
410 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d);
411 MDBUG_C_DUMP(Stmt->Connection, StringLengthPtr, 0x);
412 MDBUG_C_DUMP(Stmt->Connection, NumericAttributePtr, 0x);
413
414 ret= Stmt->Methods->ColAttribute(Stmt, ColumnNumber, FieldIdentifier, CharacterAttributePtr,
415 BufferLength, StringLengthPtr, NumericAttributePtr, FALSE);
416
417 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
418 }
419 /* }}} */
420
421 /* {{{ SQLColAttributeW */
422 SQLRETURN SQL_API SQLColAttributeW (SQLHSTMT StatementHandle,
423 SQLUSMALLINT ColumnNumber,
424 SQLUSMALLINT FieldIdentifier,
425 SQLPOINTER CharacterAttributePtr,
426 SQLSMALLINT BufferLength,
427 SQLSMALLINT *StringLengthPtr,
428 #ifdef SQLCOLATTRIB_SQLPOINTER
429 SQLPOINTER NumericAttributePtr
430 #else
431 SQLLEN *NumericAttributePtr
432 #endif
433 )
434 {
435 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
436 SQLRETURN ret;
437 if (!Stmt)
438 return SQL_INVALID_HANDLE;
439
440 MADB_CLEAR_ERROR(&Stmt->Error);
441
442 MDBUG_C_ENTER(Stmt->Connection, "SQLColAttributeW");
443 MDBUG_C_DUMP(Stmt->Connection, StatementHandle, 0x);
444 MDBUG_C_DUMP(Stmt->Connection, ColumnNumber, u);
445 MDBUG_C_DUMP(Stmt->Connection, FieldIdentifier, u);
446 MDBUG_C_DUMP(Stmt->Connection, CharacterAttributePtr, 0x);
447 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d);
448 MDBUG_C_DUMP(Stmt->Connection, StringLengthPtr, 0x);
449 MDBUG_C_DUMP(Stmt->Connection, NumericAttributePtr, 0x);
450
451 ret= Stmt->Methods->ColAttribute(Stmt, ColumnNumber, FieldIdentifier, CharacterAttributePtr,
452 BufferLength, StringLengthPtr, NumericAttributePtr, TRUE);
453
454 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
455 }
456 /* }}} */
457
458 /* {{{ SQLColAttributes */
459 SQLRETURN SQL_API SQLColAttributes(SQLHSTMT hstmt,
460 SQLUSMALLINT icol,
461 SQLUSMALLINT fDescType,
462 SQLPOINTER rgbDesc,
463 SQLSMALLINT cbDescMax,
464 SQLSMALLINT * pcbDesc,
465 SQLLEN * pfDesc)
466 {
467 MADB_Stmt *Stmt= (MADB_Stmt *)hstmt;
468 if (!Stmt)
469 return SQL_INVALID_HANDLE;
470
471 MADB_CLEAR_ERROR(&Stmt->Error);
472
473 return Stmt->Methods->ColAttribute(Stmt, icol, MapColAttributeDescType(fDescType), rgbDesc,
474 cbDescMax, pcbDesc, pfDesc, FALSE);
475 }
476 /* }}} */
477
478 /* {{{ SQLColAttributesW */
479 SQLRETURN SQL_API SQLColAttributesW(SQLHSTMT hstmt,
480 SQLUSMALLINT icol,
481 SQLUSMALLINT fDescType,
482 SQLPOINTER rgbDesc,
483 SQLSMALLINT cbDescMax,
484 SQLSMALLINT * pcbDesc,
485 SQLLEN * pfDesc)
486 {
487 /* TODO: use internal function, not api */
488 return SQLColAttributeW(hstmt, icol, MapColAttributeDescType(fDescType), rgbDesc, cbDescMax, pcbDesc, pfDesc);
489 }
490 /* }}} */
491
492 /* {{{ SQLColumnPrivileges */
493 SQLRETURN SQL_API SQLColumnPrivileges(SQLHSTMT StatementHandle,
494 SQLCHAR *CatalogName,
495 SQLSMALLINT NameLength1,
496 SQLCHAR *SchemaName,
497 SQLSMALLINT NameLength2,
498 SQLCHAR *TableName,
499 SQLSMALLINT NameLength3,
500 SQLCHAR *ColumnName,
501 SQLSMALLINT NameLength4)
502 {
503 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
504 SQLRETURN ret;
505
506 if (!Stmt)
507 return SQL_INVALID_HANDLE;
508
509 MADB_CLEAR_ERROR(&Stmt->Error);
510
511 MDBUG_C_ENTER(Stmt->Connection, "SQLColumnPrivileges");
512 ret= Stmt->Methods->ColumnPrivileges(Stmt, (char *)CatalogName, NameLength1, (char *)SchemaName, NameLength2,
513 (char *)TableName, NameLength3, (char *)ColumnName, NameLength4);
514
515 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
516 }
517 /* }}} */
518
519 /* {{{ SQLColumnPrivilegesW */
520 SQLRETURN SQL_API SQLColumnPrivilegesW(SQLHSTMT StatementHandle,
521 SQLWCHAR *CatalogName,
522 SQLSMALLINT NameLength1,
523 SQLWCHAR *SchemaName,
524 SQLSMALLINT NameLength2,
525 SQLWCHAR *TableName,
526 SQLSMALLINT NameLength3,
527 SQLWCHAR *ColumnName,
528 SQLSMALLINT NameLength4)
529 {
530 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
531 SQLULEN CpLength1, CpLength2, CpLength3, CpLength4;
532 char *CpCatalog= NULL,
533 *CpSchema= NULL,
534 *CpTable= NULL,
535 *CpColumn= NULL;
536 SQLRETURN ret;
537
538 if (!StatementHandle)
539 return SQL_INVALID_HANDLE;
540
541 MADB_CLEAR_ERROR(&Stmt->Error);
542
543 MDBUG_C_ENTER(Stmt->Connection, "SQLColumnPrivilegesW");
544
545 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
546 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
547 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
548 CpColumn= MADB_ConvertFromWChar(ColumnName, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
549
550 ret= Stmt->Methods->ColumnPrivileges(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
551 CpTable, (SQLSMALLINT)CpLength3, CpColumn, (SQLSMALLINT)CpLength4);
552
553 MADB_FREE(CpCatalog);
554 MADB_FREE(CpSchema);
555 MADB_FREE(CpTable);
556 MADB_FREE(CpColumn);
557
558 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
559 }
560 /* }}} */
561
562 /* {{{ SQLColumns */
563 SQLRETURN SQL_API SQLColumns(SQLHSTMT StatementHandle,
564 SQLCHAR *CatalogName,
565 SQLSMALLINT NameLength1,
566 SQLCHAR *SchemaName,
567 SQLSMALLINT NameLength2,
568 SQLCHAR *TableName,
569 SQLSMALLINT NameLength3,
570 SQLCHAR *ColumnName,
571 SQLSMALLINT NameLength4)
572 {
573 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
574 SQLRETURN ret;
575 if (!Stmt)
576 return SQL_INVALID_HANDLE;
577
578 MADB_CLEAR_ERROR(&Stmt->Error);
579
580 MDBUG_C_ENTER(Stmt->Connection, "SQLColumns");
581
582 ret= Stmt->Methods->Columns(Stmt, (char *)CatalogName,NameLength1, (char *)SchemaName, NameLength2,
583 (char *)TableName, NameLength3, (char *)ColumnName, NameLength4);
584
585 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
586 }
587 /* }}} */
588
589 /* {{{ SQLColumnsW */
590 SQLRETURN SQL_API SQLColumnsW(SQLHSTMT StatementHandle,
591 SQLWCHAR *CatalogName,
592 SQLSMALLINT NameLength1,
593 SQLWCHAR *SchemaName,
594 SQLSMALLINT NameLength2,
595 SQLWCHAR *TableName,
596 SQLSMALLINT NameLength3,
597 SQLWCHAR *ColumnName,
598 SQLSMALLINT NameLength4)
599 {
600 char *CpCatalog= NULL,
601 *CpSchema= NULL,
602 *CpTable= NULL,
603 *CpColumn= NULL;
604 SQLULEN CpLength1= 0, CpLength2= 0, CpLength3= 0, CpLength4= 0;
605 SQLRETURN ret;
606 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
607
608 if (!Stmt)
609 return SQL_INVALID_HANDLE;
610
611 MADB_CLEAR_ERROR(&Stmt->Error);
612
613 MDBUG_C_ENTER(Stmt->Connection, "SQLColumns");
614
615 if (CatalogName != NULL)
616 {
617 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
618 }
619 if (SchemaName != NULL)
620 {
621 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
622 }
623 if (TableName != NULL)
624 {
625 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
626 }
627 if (ColumnName != NULL)
628 {
629 CpColumn= MADB_ConvertFromWChar(ColumnName, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
630 }
631
632 ret= Stmt->Methods->Columns(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
633 CpTable, (SQLSMALLINT)CpLength3, CpColumn, (SQLSMALLINT)CpLength4);
634
635 MADB_FREE(CpCatalog);
636 MADB_FREE(CpSchema);
637 MADB_FREE(CpTable);
638 MADB_FREE(CpColumn);
639
640 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
641 }
642 /* }}} */
643
644 /* {{{ SQLCompleteAsync */
645 /* ODBC 3.8 */
646 SQLRETURN SQL_API SQLCompleteAsync(SQLSMALLINT HandleType,
647 SQLHANDLE Handle,
648 RETCODE *AsyncRetCodePtr)
649 {
650 SQLRETURN ret= SQL_ERROR;
651 return ret;
652 }
653
654 /* }}} */
655
656 /* {{{ SQLConnectCommon */
657 SQLRETURN SQLConnectCommon(SQLHDBC ConnectionHandle,
658 SQLCHAR *ServerName,
659 SQLSMALLINT NameLength1,
660 SQLCHAR *UserName,
661 SQLSMALLINT NameLength2,
662 SQLCHAR *Authentication,
663 SQLSMALLINT NameLength3)
664 {
665 MADB_Dbc *Connection= (MADB_Dbc *)ConnectionHandle;
666 MADB_Dsn *Dsn;
667 SQLRETURN ret;
668 my_bool DsnFound;
669
670 if (!Connection)
671 return SQL_INVALID_HANDLE;
672
673 MADB_CLEAR_ERROR(&Connection->Error);
674
675 MDBUG_C_ENTER(Connection, "SQLConnect");
676 MDBUG_C_DUMP(Connection, Connection, 0x);
677 MDBUG_C_DUMP(Connection, ServerName, s);
678 MDBUG_C_DUMP(Connection, NameLength1, d);
679 MDBUG_C_DUMP(Connection, UserName, s);
680 MDBUG_C_DUMP(Connection, NameLength2, d);
681 MDBUG_C_DUMP(Connection, Authentication, s);
682 MDBUG_C_DUMP(Connection, NameLength3, d);
683
684 if (CheckConnection(Connection))
685 {
686 MADB_SetError(&Connection->Error, MADB_ERR_08002, NULL, 0);
687 return SQL_ERROR;
688 }
689
690 if (!(Dsn= MADB_DSN_Init()))
691 {
692 MADB_SetError(&Connection->Error, MADB_ERR_HY001, NULL, 0);
693 return SQL_ERROR;
694 }
695
696 if (ServerName && !ServerName[0])
697 {
698 MADB_SetError(&Connection->Error, MADB_ERR_HY000, "Invalid DSN", 0);
699 return Connection->Error.ReturnValue;
700 }
701
702 MADB_DSN_SET_STR(Dsn, DSNName, (char *)ServerName, NameLength1);
703 DsnFound= MADB_ReadDSN(Dsn, NULL, TRUE);
704
705 MADB_DSN_SET_STR(Dsn, UserName, (char *)UserName, NameLength2);
706 MADB_DSN_SET_STR(Dsn, Password, (char *)Authentication, NameLength3);
707
708 ret= Connection->Methods->ConnectDB(Connection, Dsn);
709
710 if (SQL_SUCCEEDED(ret))
711 {
712 MADB_DSN_Free(Connection->Dsn);
713 Connection->Dsn= Dsn;
714 }
715 else
716 {
717 MADB_DSN_Free(Dsn);
718 }
719
720 MDBUG_C_RETURN(Connection, ret, &Connection->Error);
721 }
722 /* }}} */
723
724 /* {{{ SQLConnect */
725 SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle,
726 SQLCHAR *ServerName,
727 SQLSMALLINT NameLength1,
728 SQLCHAR *UserName,
729 SQLSMALLINT NameLength2,
730 SQLCHAR *Authentication,
731 SQLSMALLINT NameLength3)
732 {
733 return SQLConnectCommon(ConnectionHandle, ServerName, NameLength1,
734 UserName, NameLength2, Authentication, NameLength3);
735 }
736 /* }}} */
737
738 /* {{{ SQLConnectW */
739 SQLRETURN SQL_API SQLConnectW(SQLHDBC ConnectionHandle,
740 SQLWCHAR *ServerName,
741 SQLSMALLINT NameLength1,
742 SQLWCHAR *UserName,
743 SQLSMALLINT NameLength2,
744 SQLWCHAR *Authentication,
745 SQLSMALLINT NameLength3)
746 {
747 char *MBServerName= NULL, *MBUserName= NULL, *MBAuthentication= NULL;
748 SQLRETURN ret;
749 MADB_Dbc *Dbc= (MADB_Dbc*)ConnectionHandle;
750
751 if (!Dbc)
752 return SQL_INVALID_HANDLE;
753
754 MADB_CLEAR_ERROR(&Dbc->Error);
755
756 /* Convert parameters to Cp */
757 if (ServerName)
758 MBServerName= MADB_ConvertFromWChar(ServerName, NameLength1, 0, Dbc->IsAnsi ? Dbc->ConnOrSrcCharset : &utf8, NULL);
759 if (UserName)
760 MBUserName= MADB_ConvertFromWChar(UserName, NameLength2, 0, Dbc->IsAnsi ? Dbc->ConnOrSrcCharset : &utf8, NULL);
761 if (Authentication)
762 MBAuthentication= MADB_ConvertFromWChar(Authentication, NameLength3, 0, Dbc->IsAnsi ? Dbc->ConnOrSrcCharset : &utf8, NULL);
763
764 ret= SQLConnectCommon(ConnectionHandle, (SQLCHAR *)MBServerName, SQL_NTS, (SQLCHAR *)MBUserName, SQL_NTS,
765 (SQLCHAR *)MBAuthentication, SQL_NTS);
766 MADB_FREE(MBServerName);
767 MADB_FREE(MBUserName);
768 MADB_FREE(MBAuthentication);
769 return ret;
770 }
771 /* }}} */
772
773 /* {{{ SQLCopyDesc */
774 SQLRETURN SQL_API SQLCopyDesc(SQLHDESC SourceDescHandle,
775 SQLHDESC TargetDescHandle)
776 {
777 /*TODO: clear error */
778 return MADB_DescCopyDesc((MADB_Desc *)SourceDescHandle, (MADB_Desc *)TargetDescHandle);
779 }
780 /* }}} */
781
782 /* {{{ SQLDataSources */
783 SQLRETURN SQL_API SQLDataSources(SQLHENV EnvironmentHandle,
784 SQLUSMALLINT Direction,
785 SQLCHAR *ServerName,
786 SQLSMALLINT BufferLength1,
787 SQLSMALLINT *NameLength1Ptr,
788 SQLCHAR *Description,
789 SQLSMALLINT BufferLength2,
790 SQLSMALLINT *NameLength2Ptr)
791 {
792 SQLRETURN ret= SQL_ERROR;
793
794 return ret;
795 }
796 /* }}} */
797
798 /* {{{ SQLDataSourcesW */
799 SQLRETURN SQL_API SQLDataSourcesW(SQLHENV EnvironmentHandle,
800 SQLUSMALLINT Direction,
801 SQLWCHAR *ServerName,
802 SQLSMALLINT BufferLength1,
803 SQLSMALLINT *NameLength1Ptr,
804 SQLWCHAR *Description,
805 SQLSMALLINT BufferLength2,
806 SQLSMALLINT *NameLength2Ptr)
807 {
808 SQLRETURN ret= SQL_ERROR;
809
810 return ret;
811 }
812 /* }}} */
813
814 /* {{{ SQLDescribeCol */
815 SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle,
816 SQLUSMALLINT ColumnNumber,
817 SQLCHAR *ColumnName,
818 SQLSMALLINT BufferLength,
819 SQLSMALLINT *NameLengthPtr,
820 SQLSMALLINT *DataTypePtr,
821 SQLULEN *ColumnSizePtr,
822 SQLSMALLINT *DecimalDigitsPtr,
823 SQLSMALLINT *NullablePtr)
824 {
825 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
826 SQLRETURN ret;
827 if (!Stmt)
828 return SQL_INVALID_HANDLE;
829
830 MADB_CLEAR_ERROR(&Stmt->Error);
831
832 MDBUG_C_ENTER(Stmt->Connection, "SQLDescribeCol");
833 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
834 MDBUG_C_DUMP(Stmt->Connection, ColumnNumber, u);
835
836 ret= Stmt->Methods->DescribeCol(Stmt, ColumnNumber, (void *)ColumnName, BufferLength,
837 NameLengthPtr, DataTypePtr, ColumnSizePtr, DecimalDigitsPtr,
838 NullablePtr, FALSE);
839
840 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
841 }
842 /* }}} */
843
844 /* {{{ SQLDescribeColW */
845 SQLRETURN SQL_API SQLDescribeColW(SQLHSTMT StatementHandle,
846 SQLUSMALLINT ColumnNumber,
847 SQLWCHAR *ColumnName,
848 SQLSMALLINT BufferLength,
849 SQLSMALLINT *NameLengthPtr,
850 SQLSMALLINT *DataTypePtr,
851 SQLULEN *ColumnSizePtr,
852 SQLSMALLINT *DecimalDigitsPtr,
853 SQLSMALLINT *NullablePtr)
854 {
855 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
856 SQLRETURN ret;
857
858 if (!Stmt)
859 return SQL_INVALID_HANDLE;
860
861 MADB_CLEAR_ERROR(&Stmt->Error);
862
863 MDBUG_C_ENTER(Stmt->Connection, "SQLDescribeColW");
864 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
865 MDBUG_C_DUMP(Stmt->Connection, ColumnNumber, u);
866
867 ret= Stmt->Methods->DescribeCol(Stmt, ColumnNumber, (void *)ColumnName, BufferLength,
868 NameLengthPtr, DataTypePtr, ColumnSizePtr, DecimalDigitsPtr,
869 NullablePtr, TRUE);
870
871 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
872 }
873 /* }}} */
874
875 /* {{{ SQLDescribeParam */
876 SQLRETURN SQL_API SQLDescribeParam(SQLHSTMT StatementHandle,
877 SQLUSMALLINT ParameterNumber,
878 SQLSMALLINT *DataTypePtr,
879 SQLULEN *ParameterSizePtr,
880 SQLSMALLINT *DecimalDigitsPtr,
881 SQLSMALLINT *NullablePtr)
882 {
883 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
884
885 if (!Stmt)
886 return SQL_INVALID_HANDLE;
887
888 MADB_CLEAR_ERROR(&Stmt->Error);
889
890 /* MariaDB doesn't support metadata for parameters,
891 so we return default values */
892 if (DataTypePtr)
893 *DataTypePtr= SQL_VARCHAR;
894 if (ParameterSizePtr)
895 *ParameterSizePtr= 1024 * 1024 * 24;
896 if (NullablePtr)
897 *NullablePtr= SQL_NULLABLE_UNKNOWN;
898 return SQL_SUCCESS;
899 }
900 /* }}} */
901
902 /* {{{ SQLDisconnect */
903 SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle)
904 {
905 SQLRETURN ret= SQL_ERROR;
906 MADB_Dbc *Connection = (MADB_Dbc *)ConnectionHandle;
907 MADB_List *Element, *NextElement;
908
909 if (!Connection)
910 return SQL_INVALID_HANDLE;
911
912 MADB_CLEAR_ERROR(&Connection->Error);
913
914 MDBUG_C_ENTER(Connection, "SQLDisconnect");
915 MDBUG_C_DUMP(Connection, ConnectionHandle, 0x);
916
917 /* Close all statements */
918 for (Element= Connection->Stmts; Element; Element= NextElement)
919 {
920 NextElement= Element->next;
921 MA_SQLFreeStmt((SQLHSTMT)Element->data, SQL_DROP);
922 }
923
924 /* Close all explicitly allocated descriptors */
925 for (Element= Connection->Descrs; Element; Element= NextElement)
926 {
927 NextElement= Element->next;
928 MADB_DescFree((MADB_Desc*)Element->data, FALSE);
929 }
930
931 if (Connection->mariadb)
932 {
933 mysql_close(Connection->mariadb);
934 Connection->mariadb= NULL;
935 ret= SQL_SUCCESS;
936 }
937 else
938 {
939 MADB_SetError(&Connection->Error, MADB_ERR_08003, NULL, 0);
940 ret= Connection->Error.ReturnValue;
941 }
942 Connection->ConnOrSrcCharset= NULL;
943
944 MDBUG_C_RETURN(Connection, ret, &Connection->Error);
945 }
946 /* }}} */
947
948 /* {{{ SQLDriverConnect */
949 SQLRETURN SQL_API SQLDriverConnect(SQLHDBC ConnectionHandle,
950 SQLHWND WindowHandle,
951 SQLCHAR *InConnectionString,
952 SQLSMALLINT StringLength1,
953 SQLCHAR *OutConnectionString,
954 SQLSMALLINT BufferLength,
955 SQLSMALLINT *StringLength2Ptr,
956 SQLUSMALLINT DriverCompletion)
957 {
958 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
959 SQLRETURN ret;
960 if (!Dbc)
961 return SQL_INVALID_HANDLE;
962
963 MADB_CLEAR_ERROR(&Dbc->Error);
964
965 MDBUG_C_ENTER(Dbc, "SQLDriverConnect");
966 MDBUG_C_DUMP(Dbc, Dbc, 0x);
967 MDBUG_C_DUMP(Dbc, InConnectionString, s);
968 MDBUG_C_DUMP(Dbc, StringLength1, d);
969 MDBUG_C_DUMP(Dbc, OutConnectionString, 0x);
970 MDBUG_C_DUMP(Dbc, BufferLength, d);
971 MDBUG_C_DUMP(Dbc, StringLength2Ptr, 0x);
972 MDBUG_C_DUMP(Dbc, DriverCompletion, d);
973 ret= Dbc->Methods->DriverConnect(Dbc, WindowHandle, InConnectionString, StringLength1, OutConnectionString,
974 BufferLength, StringLength2Ptr, DriverCompletion);
975
976 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
977 }
978 /* }}} */
979
980 /* {{{ SQLDriverConnectW */
981 SQLRETURN SQL_API SQLDriverConnectW(SQLHDBC ConnectionHandle,
982 SQLHWND WindowHandle,
983 SQLWCHAR *InConnectionString,
984 SQLSMALLINT StringLength1,
985 SQLWCHAR *OutConnectionString,
986 SQLSMALLINT BufferLength,
987 SQLSMALLINT *StringLength2Ptr,
988 SQLUSMALLINT DriverCompletion)
989 {
990 SQLRETURN ret= SQL_ERROR;
991 SQLULEN Length= 0; /* Since we need bigger(in bytes) buffer for utf8 string, the length may be > max SQLSMALLINT */
992 char *InConnStrA= NULL;
993 SQLULEN InStrAOctLen= 0;
994 char *OutConnStrA= NULL;
995 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
996
997 if (!ConnectionHandle)
998 {
999 return SQL_INVALID_HANDLE;
1000 }
1001
1002 MDBUG_C_ENTER(Dbc, "SQLDriverConnectW");
1003
1004 MADB_CLEAR_ERROR(&Dbc->Error);
1005
1006 InConnStrA= MADB_ConvertFromWChar(InConnectionString, StringLength1, &InStrAOctLen, Dbc->IsAnsi ? Dbc->ConnOrSrcCharset : &utf8, NULL);
1007 MDBUG_C_DUMP(Dbc, Dbc, 0x);
1008 MDBUG_C_DUMP(Dbc, InConnStrA, s);
1009 MDBUG_C_DUMP(Dbc, StringLength1, d);
1010 MDBUG_C_DUMP(Dbc, OutConnectionString, 0x);
1011 MDBUG_C_DUMP(Dbc, BufferLength, d);
1012 MDBUG_C_DUMP(Dbc, StringLength2Ptr, 0x);
1013 MDBUG_C_DUMP(Dbc, DriverCompletion, d);
1014
1015 /* Allocate buffer for Asc OutConnectionString */
1016 if (OutConnectionString && BufferLength)
1017 {
1018 Length= BufferLength*4 /*Max bytes per utf8 character */;
1019 OutConnStrA= (char *)MADB_CALLOC(Length);
1020
1021 if (OutConnStrA == NULL)
1022 {
1023 ret= MADB_SetError(&Dbc->Error, MADB_ERR_HY001, NULL, 0);
1024 goto end;
1025 }
1026 }
1027
1028 ret= Dbc->Methods->DriverConnect(Dbc, WindowHandle, (SQLCHAR *)InConnStrA, InStrAOctLen, (SQLCHAR *)OutConnStrA,
1029 Length, StringLength2Ptr, DriverCompletion);
1030 MDBUG_C_DUMP(Dbc, ret, d);
1031 if (!SQL_SUCCEEDED(ret))
1032 goto end;
1033
1034 if (OutConnectionString)
1035 {
1036 Length= MADB_SetString(&utf8, OutConnectionString, BufferLength,
1037 OutConnStrA, SQL_NTS, &((MADB_Dbc *)ConnectionHandle)->Error);
1038 if (StringLength2Ptr)
1039 *StringLength2Ptr= (SQLSMALLINT)Length;
1040 }
1041
1042 end:
1043 MADB_FREE(OutConnStrA);
1044 MADB_FREE(InConnStrA);
1045 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
1046 }
1047 /* }}} */
1048
1049 /* {{{ SQLDrivers */
1050 SQLRETURN SQL_API SQLDrivers(SQLHENV EnvironmentHandle,
1051 SQLUSMALLINT Direction,
1052 SQLCHAR *DriverDescription,
1053 SQLSMALLINT BufferLength1,
1054 SQLSMALLINT *DescriptionLengthPtr,
1055 SQLCHAR *DriverAttributes,
1056 SQLSMALLINT BufferLength2,
1057 SQLSMALLINT *AttributesLengthPtr)
1058 {
1059 SQLRETURN ret= SQL_ERROR;
1060
1061 return ret;
1062 }
1063 /* }}} */
1064
1065 /* {{{ SQLDriversW */
1066 SQLRETURN SQL_API SQLDriversW(SQLHENV EnvironmentHandle,
1067 SQLUSMALLINT Direction,
1068 SQLWCHAR *DriverDescription,
1069 SQLSMALLINT BufferLength1,
1070 SQLSMALLINT *DescriptionLengthPtr,
1071 SQLWCHAR *DriverAttributes,
1072 SQLSMALLINT BufferLength2,
1073 SQLSMALLINT *AttributesLengthPtr)
1074 {
1075 SQLRETURN ret= SQL_ERROR;
1076
1077 return ret;
1078 }
1079 /* }}} */
1080
1081 /* {{{ MA_SQLEndTran */
1082 SQLRETURN MA_SQLEndTran(SQLSMALLINT HandleType,
1083 SQLHANDLE Handle,
1084 SQLSMALLINT CompletionType)
1085 {
1086 SQLRETURN ret= SQL_SUCCESS;
1087 switch (HandleType) {
1088 case SQL_HANDLE_ENV:
1089 {
1090 MADB_Env *Env= (MADB_Env *)Handle;
1091 MADB_List *List= Env->Dbcs;
1092
1093 for (List= Env->Dbcs; List; List= List->next)
1094 ((MADB_Dbc *)List->data)->Methods->EndTran((MADB_Dbc *)List->data, CompletionType);
1095 }
1096 break;
1097 case SQL_HANDLE_DBC:
1098 {
1099 MADB_Dbc *Dbc= (MADB_Dbc *)Handle;
1100 if (!Dbc->mariadb)
1101 MADB_SetError(&Dbc->Error, MADB_ERR_08002, NULL, 0);
1102 else
1103 Dbc->Methods->EndTran(Dbc, CompletionType);
1104 ret= Dbc->Error.ReturnValue;
1105 }
1106 break;
1107 default:
1108 /* todo: Do we need to set an error ?! */
1109 break;
1110 }
1111
1112 return ret;
1113 }
1114
1115 SQLRETURN SQL_API SQLEndTran(SQLSMALLINT HandleType,
1116 SQLHANDLE Handle,
1117 SQLSMALLINT CompletionType)
1118 {
1119 MADB_CHECK_HANDLE_CLEAR_ERROR(HandleType, Handle);
1120 return MA_SQLEndTran(HandleType, Handle, CompletionType);
1121 }
1122 /* }}} */
1123
1124 /* {{{ SQLError */
1125 SQLRETURN SQL_API SQLError(SQLHENV Env, SQLHDBC Dbc, SQLHSTMT Stmt,
1126 SQLCHAR *Sqlstate, SQLINTEGER *NativeError,
1127 SQLCHAR *Message, SQLSMALLINT MessageMax,
1128 SQLSMALLINT *MessageLen)
1129 {
1130 SQLSMALLINT HandleType= 0;
1131 SQLHANDLE Handle= NULL;
1132 MADB_Error *error;
1133
1134 if (Stmt)
1135 {
1136 MDBUG_C_ENTER(((MADB_Stmt*)Stmt)->Connection, "SQLError->SQLGetDiagRec");
1137
1138 MDBUG_C_DUMP(((MADB_Stmt*)Stmt)->Connection, Env, 0x);
1139 MDBUG_C_DUMP(((MADB_Stmt*)Stmt)->Connection, Dbc, 0x);
1140 MDBUG_C_DUMP(((MADB_Stmt*)Stmt)->Connection, Stmt, 0x);
1141
1142 Handle= Stmt;
1143 HandleType= SQL_HANDLE_STMT;
1144 error= &((MADB_Stmt*)Stmt)->Error;
1145 }
1146 else if (Dbc)
1147 {
1148 MDBUG_C_ENTER((MADB_Dbc*)Dbc, "SQLError->SQLGetDiagRec");
1149
1150 MDBUG_C_DUMP((MADB_Dbc*)Dbc, Env, 0x);
1151 MDBUG_C_DUMP((MADB_Dbc*)Dbc, Dbc, 0x);
1152 MDBUG_C_DUMP((MADB_Dbc*)Dbc, Stmt, 0x);
1153
1154 Handle= Dbc;
1155 HandleType= SQL_HANDLE_DBC;
1156 error= &((MADB_Dbc*)Dbc)->Error;
1157 }
1158 else
1159 {
1160 MDBUG_ENTER("SQLError->SQLGetDiagRec");
1161 MDBUG_DUMP(Env, 0x);
1162 MDBUG_DUMP(Dbc, 0x);
1163 MDBUG_DUMP(Stmt, 0x);
1164
1165 Handle= Env;
1166 HandleType= SQL_HANDLE_ENV;
1167 error= &((MADB_Env*)Env)->Error;
1168 }
1169
1170 return MA_SQLGetDiagRec(HandleType, Handle, ++error->ErrorNum, Sqlstate, NativeError, Message, MessageMax, MessageLen);
1171 }
1172 /* }}} */
1173
1174 /* {{{ MA_SQLGetDiagRecW */
1175 SQLRETURN SQL_API MA_SQLGetDiagRecW(SQLSMALLINT HandleType,
1176 SQLHANDLE Handle,
1177 SQLSMALLINT RecNumber,
1178 SQLWCHAR *SQLState,
1179 SQLINTEGER *NativeErrorPtr,
1180 SQLWCHAR *MessageText,
1181 SQLSMALLINT BufferLength,
1182 SQLSMALLINT *TextLengthPtr)
1183 {
1184 if (!Handle)
1185 return SQL_INVALID_HANDLE;
1186
1187 /* Maria ODBC driver doesn't support error lists, so only the first record can be retrieved */
1188 if (RecNumber != 1)
1189 return SQL_NO_DATA_FOUND;
1190
1191 switch (HandleType) {
1192 case SQL_HANDLE_DBC:
1193 {
1194 MADB_Dbc *Dbc= (MADB_Dbc *)Handle;
1195 return MADB_GetDiagRec(&Dbc->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1196 (void *)MessageText, BufferLength, TextLengthPtr, TRUE,
1197 Dbc->Environment->OdbcVersion);
1198 }
1199 break;
1200 case SQL_HANDLE_STMT:
1201 {
1202 MADB_Stmt *Stmt= (MADB_Stmt *)Handle;
1203 return MADB_GetDiagRec(&Stmt->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1204 (void *)MessageText, BufferLength, TextLengthPtr, TRUE,
1205 Stmt->Connection->Environment->OdbcVersion);
1206 }
1207 break;
1208 case SQL_HANDLE_DESC:
1209 {
1210 MADB_Desc *Desc= (MADB_Desc *)Handle;
1211 return MADB_GetDiagRec(&Desc->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1212 (void *)MessageText, BufferLength, TextLengthPtr, TRUE,
1213 SQL_OV_ODBC3);
1214 }
1215 break;
1216 case SQL_HANDLE_ENV:
1217 {
1218 MADB_Env *Env= (MADB_Env *)Handle;
1219 return MADB_GetDiagRec(&Env->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1220 (void *)MessageText, BufferLength, TextLengthPtr, TRUE,
1221 Env->OdbcVersion);
1222 }
1223 default:
1224 return SQL_ERROR;
1225 break;
1226 }
1227 }
1228 /* }}} */
1229
1230 /*{{{ SQLErrorW */
1231 SQLRETURN SQL_API
1232 SQLErrorW(SQLHENV Env, SQLHDBC Dbc, SQLHSTMT Stmt, SQLWCHAR *Sqlstate,
1233 SQLINTEGER *NativeError, SQLWCHAR *Message, SQLSMALLINT MessageMax,
1234 SQLSMALLINT *MessageLen)
1235
1236 {
1237 SQLSMALLINT HandleType= 0;
1238 SQLHANDLE Handle= NULL;
1239 MADB_Error *error;
1240
1241 if (Stmt)
1242 {
1243 Handle= Stmt;
1244 HandleType= SQL_HANDLE_STMT;
1245 error= &((MADB_Stmt*)Stmt)->Error;
1246 }
1247 else if (Dbc)
1248 {
1249 Handle= Dbc;
1250 HandleType= SQL_HANDLE_DBC;
1251 error= &((MADB_Dbc*)Dbc)->Error;
1252 }
1253 else
1254 {
1255 Handle= Env;
1256 HandleType= SQL_HANDLE_ENV;
1257 error= &((MADB_Env*)Env)->Error;
1258 }
1259
1260 return MA_SQLGetDiagRecW(HandleType, Handle, ++error->ErrorNum, Sqlstate, NativeError, Message, MessageMax, MessageLen);
1261 }
1262 /* }}} */
1263
1264 /* {{{ SQLTransact */
1265 SQLRETURN SQL_API SQLTransact(SQLHENV Env, SQLHDBC Dbc, SQLUSMALLINT CompletionType)
1266 {
1267 if (Env != SQL_NULL_HENV)
1268 {
1269 MADB_CLEAR_ERROR(&((MADB_Env*)Env)->Error);
1270 return MA_SQLEndTran(SQL_HANDLE_ENV, Env, CompletionType);
1271 }
1272 else if (Dbc != SQL_NULL_HDBC)
1273 {
1274 MADB_CLEAR_ERROR(&((MADB_Dbc*)Dbc)->Error);
1275 return MA_SQLEndTran(SQL_HANDLE_DBC, Dbc, CompletionType);
1276 }
1277 else
1278 return SQL_INVALID_HANDLE;
1279 }
1280 /* }}} */
1281
1282 /* {{{ SQLExecDirect */
1283 SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle,
1284 SQLCHAR *StatementText,
1285 SQLINTEGER TextLength)
1286 {
1287 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1288 SQLRETURN ret;
1289
1290 if (!Stmt)
1291 ret= SQL_INVALID_HANDLE;
1292 else
1293 ret= Stmt->Methods->ExecDirect(Stmt, (char *)StatementText, TextLength);
1294
1295 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
1296 }
1297 /* }}} */
1298
1299 /* {{{ SQLExecDirectW */
1300 SQLRETURN SQL_API SQLExecDirectW(SQLHSTMT StatementHandle,
1301 SQLWCHAR *StatementText,
1302 SQLINTEGER TextLength)
1303 {
1304 char *CpStmt;
1305 SQLULEN StmtLength;
1306 SQLRETURN ret;
1307 BOOL ConversionError;
1308
1309 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1310
1311 if (!Stmt)
1312 return SQL_INVALID_HANDLE;
1313
1314 MADB_CLEAR_ERROR(&Stmt->Error);
1315
1316 MDBUG_C_ENTER(Stmt->Connection, "SQLExecDirectW");
1317 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
1318
1319 CpStmt= MADB_ConvertFromWChar(StatementText, TextLength, &StmtLength, Stmt->Connection->ConnOrSrcCharset, &ConversionError);
1320 MDBUG_C_DUMP(Stmt->Connection, CpStmt, s);
1321 if (ConversionError)
1322 {
1323 MADB_SetError(&Stmt->Error, MADB_ERR_22018, NULL, 0);
1324 ret= Stmt->Error.ReturnValue;
1325 }
1326 else
1327 ret= Stmt->Methods->ExecDirect(Stmt, CpStmt, (SQLINTEGER)StmtLength);
1328 MADB_FREE(CpStmt);
1329
1330 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
1331 }
1332 /* }}} */
1333
1334 SQLRETURN SQL_API SQLExecute(SQLHSTMT StatementHandle)
1335 {
1336 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1337
1338 if (StatementHandle == SQL_NULL_HSTMT)
1339 return SQL_INVALID_HANDLE;
1340
1341 MADB_CLEAR_ERROR(&Stmt->Error);
1342
1343 MDBUG_C_ENTER(Stmt->Connection, "SQLExecute");
1344 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
1345
1346 return Stmt->Methods->Execute(Stmt, FALSE);
1347 }
1348 /* }}} */
1349
1350 /* {{{ SQLExtendedFetch */
1351 SQLRETURN SQL_API SQLExtendedFetch(SQLHSTMT StatementHandle,
1352 SQLUSMALLINT FetchOrientation,
1353 SQLLEN FetchOffset,
1354 SQLULEN *RowCountPtr,
1355 SQLUSMALLINT *RowStatusArray)
1356 {
1357 SQLRETURN ret;
1358 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1359
1360 SQLULEN *SaveRowsProcessedPtr= Stmt->Ird->Header.RowsProcessedPtr;
1361 SQLUSMALLINT *SaveArrayStatusPtr= Stmt->Ird->Header.ArrayStatusPtr;
1362
1363 if (!Stmt)
1364 return SQL_INVALID_HANDLE;
1365 MADB_CLEAR_ERROR(&Stmt->Error);
1366
1367 MDBUG_C_ENTER(Stmt->Connection, "SQLExtendedFetch");
1368 MDBUG_C_DUMP(Stmt->Connection, FetchOrientation, u);
1369 MDBUG_C_DUMP(Stmt->Connection, FetchOffset, d);
1370 MDBUG_C_DUMP(Stmt->Connection, RowCountPtr, 0x);
1371 MDBUG_C_DUMP(Stmt->Connection, RowStatusArray, 0x);
1372
1373 Stmt->Ird->Header.RowsProcessedPtr= RowCountPtr;
1374 Stmt->Ird->Header.ArrayStatusPtr= RowStatusArray;
1375 ret= Stmt->Methods->FetchScroll(Stmt, FetchOrientation, FetchOffset);
1376
1377 if (RowStatusArray && SaveArrayStatusPtr)
1378 {
1379 SQLUINTEGER i;
1380 for (i=0; i < Stmt->Ard->Header.ArraySize; i++)
1381 SaveArrayStatusPtr[i]= RowStatusArray[i];
1382 }
1383
1384 Stmt->Ird->Header.RowsProcessedPtr= SaveRowsProcessedPtr;
1385 Stmt->Ird->Header.ArrayStatusPtr= SaveArrayStatusPtr;
1386
1387 if (ret == SQL_NO_DATA)
1388 {
1389 if (RowCountPtr)
1390 *RowCountPtr= 0;
1391 }
1392 if (ret == SQL_ERROR)
1393 if (strcmp(Stmt->Error.SqlState, "22002") == 0)
1394 ret= SQL_SUCCESS_WITH_INFO;
1395
1396 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
1397 }
1398 /* }}} */
1399
1400 /* {{{ SQLFetch */
1401 SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle)
1402 {
1403 MADB_Stmt *Stmt;
1404
1405 if (StatementHandle == SQL_NULL_HSTMT)
1406 return SQL_INVALID_HANDLE;
1407
1408 Stmt= (MADB_Stmt *)StatementHandle;
1409
1410 MDBUG_C_ENTER(Stmt->Connection, "SQLFetch");
1411 MADB_CLEAR_ERROR(&Stmt->Error);
1412
1413 /* SQLFetch is equivalent of SQLFetchScroll(SQL_FETCH_NEXT), 3rd parameter is ignored for SQL_FETCH_NEXT */
1414 MDBUG_C_RETURN(Stmt->Connection, Stmt->Methods->FetchScroll(Stmt, SQL_FETCH_NEXT, 1), &Stmt->Error);
1415 }
1416 /* }}} */
1417
1418 /* {{{ SQLFetchScroll */
1419 SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT StatementHandle,
1420 SQLSMALLINT FetchOrientation,
1421 SQLLEN FetchOffset)
1422 {
1423 MADB_Stmt *Stmt;
1424
1425 if (StatementHandle == SQL_NULL_HSTMT)
1426 return SQL_INVALID_HANDLE;
1427
1428 Stmt= (MADB_Stmt *)StatementHandle;
1429
1430 MDBUG_C_ENTER(Stmt->Connection, "SQLFetchScroll");
1431 MDBUG_C_DUMP(Stmt->Connection, FetchOrientation, d);
1432
1433 MADB_CLEAR_ERROR(&Stmt->Error);
1434
1435 MDBUG_C_RETURN(Stmt->Connection, Stmt->Methods->FetchScroll(Stmt, FetchOrientation, FetchOffset), &Stmt->Error);
1436 }
1437 /* }}} */
1438
1439 /* {{{ SQLFreeHandle */
1440 SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT HandleType,
1441 SQLHANDLE Handle)
1442 {
1443 SQLRETURN ret;
1444 MADB_CHECK_HANDLE_CLEAR_ERROR(HandleType, Handle);
1445
1446 switch (HandleType)
1447 {
1448 case SQL_HANDLE_ENV:
1449 MDBUG_ENTER("SQLFreeHandle");
1450 MDBUG_DUMP(HandleType, d);
1451 MDBUG_DUMP(Handle, 0x);
1452
1453 ret= MADB_EnvFree((MADB_Env *)Handle);
1454 break;
1455 case SQL_HANDLE_DBC:
1456 {
1457 MADB_Dbc *Dbc= (MADB_Dbc *)Handle;
1458
1459 MDBUG_C_ENTER(Dbc, "SQLFreeHandle");
1460 MDBUG_C_DUMP(Dbc, HandleType, d);
1461 MDBUG_C_DUMP(Dbc, Handle, 0x);
1462
1463 ret= MADB_DbcFree(Dbc);
1464 return ret;
1465 /*MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);*/
1466 }
1467 case SQL_HANDLE_DESC:
1468 {
1469 MADB_Desc *Desc= (MADB_Desc *)Handle;
1470 MADB_Dbc *Dbc= Desc->Dbc;
1471
1472 MDBUG_C_ENTER(Dbc, "SQLFreeHandle");
1473 MDBUG_C_DUMP(Dbc, HandleType, d);
1474 MDBUG_C_DUMP(Dbc, Handle, 0x);
1475
1476 /* Error if the descriptor does not belong to application(was automatically alliocated by the driver)
1477 Basically DM is supposed to take care of this. Keeping in mind direct linking */
1478 if (!Desc->AppType)
1479 {
1480 MADB_SetError(&Desc->Error, MADB_ERR_HY017, NULL, 0);
1481 MDBUG_C_RETURN(Dbc, Desc->Error.ReturnValue, &Desc->Error);
1482 }
1483 ret= MADB_DescFree(Desc, FALSE);
1484 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
1485 }
1486 case SQL_HANDLE_STMT:
1487 {
1488 MADB_Stmt *Stmt= (MADB_Stmt *)Handle;
1489 MADB_Dbc *Dbc= Stmt->Connection;
1490
1491 MDBUG_C_ENTER(Dbc, "SQLFreeHandle");
1492 MDBUG_C_DUMP(Dbc, HandleType, d);
1493 MDBUG_C_DUMP(Dbc, Handle, 0x);
1494
1495 ret= MA_SQLFreeStmt(Stmt, SQL_DROP);
1496
1497 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
1498 }
1499 }
1500
1501 MDBUG_RETURN(ret);
1502 }
1503 /* }}} */
1504
1505 /* {{{ SQLFreeEnv */
1506 SQLRETURN SQL_API SQLFreeEnv(SQLHANDLE henv)
1507 {
1508 if (henv == SQL_NULL_HENV)
1509 return SQL_INVALID_HANDLE;
1510 MADB_CLEAR_ERROR(&((MADB_Env*)henv)->Error);
1511
1512 return MADB_EnvFree((MADB_Env *)henv);
1513 }
1514 /* }}} */
1515
1516 /* {{{ SQLFreeConnect */
1517 SQLRETURN SQL_API SQLFreeConnect(SQLHANDLE hdbc)
1518 {
1519 if (hdbc == SQL_NULL_HDBC)
1520 return SQL_INVALID_HANDLE;
1521 MADB_CLEAR_ERROR(&((MADB_Dbc*)hdbc)->Error);
1522
1523 return MADB_DbcFree((MADB_Dbc*)hdbc);
1524 }
1525 /* }}} */
1526
1527 /* {{{ SQLFreeStmt */
1528 SQLRETURN MA_SQLFreeStmt(SQLHSTMT StatementHandle,
1529 SQLUSMALLINT Option)
1530 {
1531 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1532 MDBUG_C_PRINT(Stmt->Connection, "%sMA_SQLFreeStmt","\t->");
1533 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
1534 MDBUG_C_DUMP(Stmt->Connection, Option, d);
1535
1536 return Stmt->Methods->StmtFree(Stmt, Option);
1537 }
1538
1539 SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle,
1540 SQLUSMALLINT Option)
1541 {
1542 if (StatementHandle== SQL_NULL_HSTMT)
1543 return SQL_INVALID_HANDLE;
1544 MDBUG_C_ENTER(((MADB_Stmt*)StatementHandle)->Connection, "SQLFreeStmt");
1545 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
1546
1547 return MA_SQLFreeStmt(StatementHandle, Option);
1548 }
1549 /* }}} */
1550
1551 /* {{{ SQLForeignKeys */
1552 SQLRETURN SQL_API SQLForeignKeys(SQLHSTMT StatementHandle,
1553 SQLCHAR *PKCatalogName,
1554 SQLSMALLINT NameLength1,
1555 SQLCHAR *PKSchemaName,
1556 SQLSMALLINT NameLength2,
1557 SQLCHAR *PKTableName,
1558 SQLSMALLINT NameLength3,
1559 SQLCHAR *FKCatalogName,
1560 SQLSMALLINT NameLength4,
1561 SQLCHAR *FKSchemaName,
1562 SQLSMALLINT NameLength5,
1563 SQLCHAR *FKTableName,
1564 SQLSMALLINT NameLength6)
1565 {
1566 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1567 SQLRETURN ret;
1568
1569 if(!Stmt)
1570 return SQL_INVALID_HANDLE;
1571 MADB_CLEAR_ERROR(&Stmt->Error);
1572
1573 MDBUG_C_ENTER(Stmt->Connection, "SQLForeignKeys");
1574
1575 ret= Stmt->Methods->ForeignKeys(Stmt, (char *)PKCatalogName, NameLength1, (char *)PKSchemaName, NameLength2,
1576 (char *)PKTableName, NameLength3, (char *)FKCatalogName, NameLength4,
1577 (char *)FKSchemaName, NameLength4, (char *)FKTableName, NameLength6);
1578
1579 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
1580 }
1581 /* }}} */
1582
1583 /* {{{ SQLForeignKeysW */
1584 SQLRETURN SQL_API SQLForeignKeysW(SQLHSTMT StatementHandle,
1585 SQLWCHAR *PKCatalogName,
1586 SQLSMALLINT NameLength1,
1587 SQLWCHAR *PKSchemaName,
1588 SQLSMALLINT NameLength2,
1589 SQLWCHAR *PKTableName,
1590 SQLSMALLINT NameLength3,
1591 SQLWCHAR *FKCatalogName,
1592 SQLSMALLINT NameLength4,
1593 SQLWCHAR *FKSchemaName,
1594 SQLSMALLINT NameLength5,
1595 SQLWCHAR *FKTableName,
1596 SQLSMALLINT NameLength6)
1597 {
1598 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1599 char *CpPkCatalog= NULL,
1600 *CpPkSchema= NULL,
1601 *CpPkTable= NULL,
1602 *CpFkCatalog= NULL,
1603 *CpFkSchema= NULL,
1604 *CpFkTable= NULL;
1605 SQLULEN CpLength1, CpLength2, CpLength3,
1606 CpLength4, CpLength5, CpLength6;
1607 SQLRETURN ret;
1608 if(!Stmt)
1609 return SQL_INVALID_HANDLE;
1610 MADB_CLEAR_ERROR(&Stmt->Error);
1611
1612 MDBUG_C_ENTER(Stmt->Connection, "SQLForeignKeysW");
1613
1614 CpPkCatalog= MADB_ConvertFromWChar(PKCatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
1615 CpPkSchema= MADB_ConvertFromWChar(PKSchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
1616 CpPkTable= MADB_ConvertFromWChar(PKTableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
1617 CpFkCatalog= MADB_ConvertFromWChar(FKCatalogName, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
1618 CpFkSchema= MADB_ConvertFromWChar(FKSchemaName, NameLength5, &CpLength5, Stmt->Connection->ConnOrSrcCharset, NULL);
1619 CpFkTable= MADB_ConvertFromWChar(FKTableName, NameLength6, &CpLength6, Stmt->Connection->ConnOrSrcCharset, NULL);
1620
1621 ret= Stmt->Methods->ForeignKeys(Stmt, CpPkCatalog, (SQLSMALLINT)CpLength1, CpPkSchema, (SQLSMALLINT)CpLength2,
1622 CpPkTable, (SQLSMALLINT)CpLength3, CpFkCatalog, (SQLSMALLINT)CpLength4,
1623 CpFkSchema, (SQLSMALLINT)CpLength5, CpFkTable, (SQLSMALLINT)CpLength6);
1624 MADB_FREE(CpPkCatalog);
1625 MADB_FREE(CpPkSchema);
1626 MADB_FREE(CpPkTable);
1627 MADB_FREE(CpFkCatalog);
1628 MADB_FREE(CpFkSchema);
1629 MADB_FREE(CpFkTable);
1630
1631 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
1632 }
1633 /* }}} */
1634
1635 /* {{{ SQLGetConnectAttr */
1636 SQLRETURN MA_SQLGetConnectAttr(SQLHDBC ConnectionHandle,
1637 SQLINTEGER Attribute,
1638 SQLPOINTER ValuePtr,
1639 SQLINTEGER BufferLength,
1640 SQLINTEGER *StringLengthPtr)
1641 {
1642 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
1643 SQLRETURN ret;
1644
1645 if (!Dbc)
1646 return SQL_INVALID_HANDLE;
1647
1648 MDBUG_C_ENTER(Dbc, "SQLGetConnectAttr");
1649 MDBUG_C_DUMP(Dbc, Attribute, d);
1650 MDBUG_C_DUMP(Dbc, ValuePtr, 0x);
1651 MDBUG_C_DUMP(Dbc, BufferLength, d);
1652 MDBUG_C_DUMP(Dbc, StringLengthPtr, 0x);
1653
1654 ret= Dbc->Methods->GetAttr(Dbc, Attribute, ValuePtr, BufferLength, StringLengthPtr, FALSE);
1655
1656 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
1657 }
1658
1659
1660 SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC ConnectionHandle,
1661 SQLINTEGER Attribute,
1662 SQLPOINTER ValuePtr,
1663 SQLINTEGER BufferLength,
1664 SQLINTEGER *StringLengthPtr)
1665 {
1666 if (ConnectionHandle == SQL_NULL_HDBC)
1667 return SQL_INVALID_HANDLE;
1668 MADB_CLEAR_ERROR(&((MADB_Dbc *)ConnectionHandle)->Error);
1669
1670 return MA_SQLGetConnectAttr(ConnectionHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr);
1671 }
1672 /* }}} */
1673
1674 /* {{{ SQLGetConnectAttrW */
1675 SQLRETURN SQL_API SQLGetConnectAttrW(SQLHDBC ConnectionHandle,
1676 SQLINTEGER Attribute,
1677 SQLPOINTER ValuePtr,
1678 SQLINTEGER BufferLength,
1679 SQLINTEGER *StringLengthPtr)
1680 {
1681 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
1682 SQLRETURN ret;
1683
1684 if (!Dbc)
1685 return SQL_INVALID_HANDLE;
1686 MADB_CLEAR_ERROR(&Dbc->Error);
1687
1688 MDBUG_C_ENTER(Dbc, "SQLGetConnectAttr");
1689 MDBUG_C_DUMP(Dbc, Attribute, d);
1690 MDBUG_C_DUMP(Dbc, ValuePtr, 0x);
1691 MDBUG_C_DUMP(Dbc, BufferLength, d);
1692 MDBUG_C_DUMP(Dbc, StringLengthPtr, 0x);
1693
1694 ret= Dbc->Methods->GetAttr(Dbc, Attribute, ValuePtr, BufferLength, StringLengthPtr, TRUE);
1695
1696 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
1697 }
1698 /* }}} */
1699
1700 /* {{{ SQLGetConnectOption */
1701 SQLRETURN SQL_API SQLGetConnectOption(SQLHDBC ConnectionHandle, SQLUSMALLINT Option, SQLPOINTER ValuePtr)
1702 {
1703 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
1704
1705 if (!Dbc)
1706 return SQL_INVALID_HANDLE;
1707 MADB_CLEAR_ERROR(&Dbc->Error);
1708
1709 return MA_SQLGetConnectAttr(ConnectionHandle, Option, ValuePtr,
1710 Option == SQL_ATTR_CURRENT_CATALOG ? SQL_MAX_OPTION_STRING_LENGTH : 0, NULL);
1711 }
1712 /* }}} */
1713
1714 /* {{{ SQLGetConnectOptionW */
1715 SQLRETURN SQL_API SQLGetConnectOptionW(SQLHDBC ConnectionHandle, SQLUSMALLINT Option, SQLPOINTER ValuePtr)
1716 {
1717 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
1718 if (!Dbc)
1719 return SQL_INVALID_HANDLE;
1720 MADB_CLEAR_ERROR(&Dbc->Error);
1721 return SQLGetConnectAttrW(ConnectionHandle, Option, ValuePtr,
1722 Option == SQL_ATTR_CURRENT_CATALOG ? SQL_MAX_OPTION_STRING_LENGTH : 0, NULL);
1723 }
1724 /* }}} */
1725
1726 /* {{{ SQLGetCursorName */
1727 SQLRETURN SQL_API SQLGetCursorName(
1728 SQLHSTMT StatementHandle,
1729 SQLCHAR * CursorName,
1730 SQLSMALLINT BufferLength,
1731 SQLSMALLINT * NameLengthPtr)
1732 {
1733 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1734 if (!Stmt)
1735 return SQL_INVALID_HANDLE;
1736 MADB_CLEAR_ERROR(&Stmt->Error);
1737
1738 return Stmt->Methods->GetCursorName(Stmt, CursorName, BufferLength, NameLengthPtr, FALSE);
1739 }
1740 /* }}} */
1741
1742 /* {{{ SQLGetCursorNameW */
1743 SQLRETURN SQL_API SQLGetCursorNameW(
1744 SQLHSTMT StatementHandle,
1745 SQLWCHAR * CursorName,
1746 SQLSMALLINT BufferLength,
1747 SQLSMALLINT * NameLengthPtr)
1748 {
1749 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
1750 if (!Stmt)
1751 return SQL_INVALID_HANDLE;
1752 MADB_CLEAR_ERROR(&Stmt->Error);
1753
1754 return Stmt->Methods->GetCursorName(Stmt, CursorName, BufferLength, NameLengthPtr, TRUE);
1755 }
1756 /* }}} */
1757
1758 /* {{{ SQLGetData */
1759 SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle,
1760 SQLUSMALLINT Col_or_Param_Num,
1761 SQLSMALLINT TargetType,
1762 SQLPOINTER TargetValuePtr,
1763 SQLLEN BufferLength,
1764 SQLLEN *StrLen_or_IndPtr)
1765 {
1766 MADB_Stmt *Stmt= (MADB_Stmt*)StatementHandle;
1767 unsigned int i;
1768 MADB_DescRecord *IrdRec;
1769
1770 if (StatementHandle== SQL_NULL_HSTMT)
1771 return SQL_INVALID_HANDLE;
1772 MADB_CLEAR_ERROR(&Stmt->Error);
1773
1774 /* In case we don't have DM(it check for that) */
1775 if (TargetValuePtr == NULL)
1776 {
1777 return MADB_SetError(&Stmt->Error, MADB_ERR_HY009, NULL, 0);
1778 }
1779
1780 /* Bookmark */
1781 if (Col_or_Param_Num == 0)
1782 {
1783 return MADB_GetBookmark(Stmt, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr);
1784 }
1785
1786 /* We don't need this to be checked in case of "internal" use of the GetData, i.e. for internal needs we should always get the data */
1787 if ( Stmt->CharOffset[Col_or_Param_Num - 1] > 0
1788 && Stmt->CharOffset[Col_or_Param_Num - 1] >= Stmt->Lengths[Col_or_Param_Num - 1])
1789 {
1790 return SQL_NO_DATA;
1791 }
1792
1793 if (BufferLength < 0)
1794 {
1795 return MADB_SetError(&Stmt->Error, MADB_ERR_HY090, NULL, 0);
1796 }
1797
1798 /* reset offsets for other columns. Doing that here since "internal" calls should not do that */
1799 for (i=0; i < mysql_stmt_field_count(Stmt->stmt); i++)
1800 {
1801 if (i != Col_or_Param_Num - 1)
1802 {
1803 IrdRec= MADB_DescGetInternalRecord(Stmt->Ird, i, MADB_DESC_READ);
1804 if (IrdRec)
1805 {
1806 MADB_FREE(IrdRec->InternalBuffer);
1807 }
1808 Stmt->CharOffset[i]= 0;
1809 }
1810 }
1811
1812 return Stmt->Methods->GetData(StatementHandle, Col_or_Param_Num, TargetType, TargetValuePtr, BufferLength, StrLen_or_IndPtr, FALSE);
1813 }
1814 /* }}} */
1815
1816 /* {{{ SQLGetDescField */
1817 SQLRETURN SQL_API SQLGetDescField(SQLHDESC DescriptorHandle,
1818 SQLSMALLINT RecNumber,
1819 SQLSMALLINT FieldIdentifier,
1820 SQLPOINTER ValuePtr,
1821 SQLINTEGER BufferLength,
1822 SQLINTEGER *StringLengthPtr)
1823 {
1824 if (!DescriptorHandle)
1825 return SQL_INVALID_HANDLE;
1826 MADB_CLEAR_ERROR(&((MADB_Desc*)DescriptorHandle)->Error);
1827
1828 return MADB_DescGetField(DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, StringLengthPtr, FALSE);
1829 }
1830 /* }}} */
1831
1832 /* {{{ SQLGetDescFieldW */
1833 SQLRETURN SQL_API SQLGetDescFieldW(SQLHDESC DescriptorHandle,
1834 SQLSMALLINT RecNumber,
1835 SQLSMALLINT FieldIdentifier,
1836 SQLPOINTER ValuePtr,
1837 SQLINTEGER BufferLength,
1838 SQLINTEGER *StringLengthPtr)
1839 {
1840 if (!DescriptorHandle)
1841 return SQL_INVALID_HANDLE;
1842 MADB_CLEAR_ERROR(&((MADB_Desc*)DescriptorHandle)->Error);
1843
1844 return MADB_DescGetField(DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, StringLengthPtr, TRUE);
1845 }
1846 /* }}} */
1847
1848 /* {{{ SQLGetDescRec */
1849 SQLRETURN SQL_API SQLGetDescRec(SQLHDESC DescriptorHandle,
1850 SQLSMALLINT RecNumber,
1851 SQLCHAR *Name,
1852 SQLSMALLINT BufferLength,
1853 SQLSMALLINT *StringLengthPtr,
1854 SQLSMALLINT *TypePtr,
1855 SQLSMALLINT *SubTypePtr,
1856 SQLLEN *LengthPtr,
1857 SQLSMALLINT *PrecisionPtr,
1858 SQLSMALLINT *ScalePtr,
1859 SQLSMALLINT *NullablePtr)
1860 {
1861 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
1862 if (!Desc)
1863 return SQL_INVALID_HANDLE;
1864 MADB_CLEAR_ERROR(&Desc->Error);
1865
1866 return MADB_DescGetRec(Desc, RecNumber, Name, BufferLength, StringLengthPtr, TypePtr, SubTypePtr,
1867 LengthPtr, PrecisionPtr, ScalePtr, NullablePtr, FALSE);
1868 }
1869 /* }}} */
1870
1871 /* {{{ SQLGetDescRecW */
1872 SQLRETURN SQL_API SQLGetDescRecW(SQLHDESC DescriptorHandle,
1873 SQLSMALLINT RecNumber,
1874 SQLWCHAR *Name,
1875 SQLSMALLINT BufferLength,
1876 SQLSMALLINT *StringLengthPtr,
1877 SQLSMALLINT *TypePtr,
1878 SQLSMALLINT *SubTypePtr,
1879 SQLLEN *LengthPtr,
1880 SQLSMALLINT *PrecisionPtr,
1881 SQLSMALLINT *ScalePtr,
1882 SQLSMALLINT *NullablePtr)
1883 {
1884 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
1885 if (!Desc)
1886 return SQL_INVALID_HANDLE;
1887 MADB_CLEAR_ERROR(&Desc->Error);
1888
1889 return MADB_DescGetRec(Desc, RecNumber, (SQLCHAR *)Name, BufferLength, StringLengthPtr, TypePtr, SubTypePtr,
1890 LengthPtr, PrecisionPtr, ScalePtr, NullablePtr, TRUE);
1891 }
1892 /* }}} */
1893
1894 /* {{{ SQLGetDiagField */
1895 SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType,
1896 SQLHANDLE Handle,
1897 SQLSMALLINT RecNumber,
1898 SQLSMALLINT DiagIdentifier,
1899 SQLPOINTER DiagInfoPtr,
1900 SQLSMALLINT BufferLength,
1901 SQLSMALLINT *StringLengthPtr)
1902 {
1903 if (!Handle)
1904 return SQL_INVALID_HANDLE;
1905 return MADB_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier, DiagInfoPtr, BufferLength, StringLengthPtr, FALSE);
1906 }
1907 /* }}} */
1908
1909 /* {{{ SQLGetDiagFieldW */
1910 SQLRETURN SQL_API SQLGetDiagFieldW(SQLSMALLINT HandleType,
1911 SQLHANDLE Handle,
1912 SQLSMALLINT RecNumber,
1913 SQLSMALLINT DiagIdentifier,
1914 SQLPOINTER DiagInfoPtr,
1915 SQLSMALLINT BufferLength,
1916 SQLSMALLINT *StringLengthPtr)
1917 {
1918 if (!Handle)
1919 return SQL_INVALID_HANDLE;
1920 return MADB_GetDiagField(HandleType, Handle, RecNumber, DiagIdentifier, DiagInfoPtr, BufferLength, StringLengthPtr, TRUE);
1921 }
1922 /* }}} */
1923
1924 /* {{{ SQLGetDiagRec */
1925 SQLRETURN MA_SQLGetDiagRec(SQLSMALLINT HandleType,
1926 SQLHANDLE Handle,
1927 SQLSMALLINT RecNumber,
1928 SQLCHAR *SQLState,
1929 SQLINTEGER *NativeErrorPtr,
1930 SQLCHAR *MessageText,
1931 SQLSMALLINT BufferLength,
1932 SQLSMALLINT *TextLengthPtr)
1933 {
1934 SQLRETURN ret= SQL_ERROR;
1935
1936 if (!Handle)
1937 MDBUG_RETURN(SQL_INVALID_HANDLE);
1938
1939 if (RecNumber < 1 || BufferLength < 0)
1940 MDBUG_RETURN(SQL_ERROR);
1941
1942 /* Maria ODBC driver doesn't support error lists, so only the first record can be retrieved */
1943 if (RecNumber != 1)
1944 MDBUG_RETURN(SQL_NO_DATA_FOUND);
1945
1946 switch (HandleType) {
1947 case SQL_HANDLE_DBC:
1948 {
1949 MADB_Dbc *Dbc= (MADB_Dbc *)Handle;
1950
1951 MDBUG_C_ENTER(Dbc, "SQLGetDiagRec");
1952 MDBUG_C_DUMP(Dbc, HandleType, d);
1953 MDBUG_C_DUMP(Dbc, Handle, 0x);
1954 MDBUG_C_DUMP(Dbc, MessageText, 0x);
1955 MDBUG_C_DUMP(Dbc, BufferLength, d);
1956 MDBUG_C_DUMP(Dbc, TextLengthPtr, 0x);
1957
1958 ret= MADB_GetDiagRec(&Dbc->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1959 (void *) MessageText, BufferLength, TextLengthPtr, FALSE,
1960 Dbc->Environment->OdbcVersion);
1961 }
1962 break;
1963 case SQL_HANDLE_STMT:
1964 {
1965 MADB_Stmt *Stmt= (MADB_Stmt *)Handle;
1966
1967 MDBUG_C_ENTER(Stmt->Connection, "SQLGetDiagRec");
1968 MDBUG_C_DUMP(Stmt->Connection, HandleType, d);
1969 MDBUG_C_DUMP(Stmt->Connection, Handle, 0x);
1970 MDBUG_C_DUMP(Stmt->Connection, MessageText, 0x);
1971 MDBUG_C_DUMP(Stmt->Connection, BufferLength, d);
1972 MDBUG_C_DUMP(Stmt->Connection, TextLengthPtr, 0x);
1973
1974 ret= MADB_GetDiagRec(&Stmt->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1975 (void *)MessageText, BufferLength, TextLengthPtr, FALSE,
1976 Stmt->Connection->Environment->OdbcVersion);
1977 }
1978 break;
1979 case SQL_HANDLE_DESC:
1980 {
1981 MADB_Desc *Desc= (MADB_Desc *)Handle;
1982
1983 MDBUG_C_ENTER(Desc->Dbc, "SQLGetDiagRec");
1984 MDBUG_C_DUMP(Desc->Dbc, HandleType, d);
1985 MDBUG_C_DUMP(Desc->Dbc, Handle, 0x);
1986 MDBUG_C_DUMP(Desc->Dbc, MessageText, 0x);
1987 MDBUG_C_DUMP(Desc->Dbc, BufferLength, d);
1988 MDBUG_C_DUMP(Desc->Dbc, TextLengthPtr, 0x);
1989
1990 ret= MADB_GetDiagRec(&Desc->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1991 (void *)MessageText, BufferLength, TextLengthPtr, FALSE,
1992 SQL_OV_ODBC3);
1993 }
1994 break;
1995 case SQL_HANDLE_ENV:
1996 {
1997 MADB_Env *Env= (MADB_Env *)Handle;
1998 ret= MADB_GetDiagRec(&Env->Error, RecNumber, (void *)SQLState, NativeErrorPtr,
1999 (void *)MessageText, BufferLength, TextLengthPtr, FALSE,
2000 Env->OdbcVersion);
2001 }
2002 break;
2003 }
2004
2005 MDBUG_RETURN(ret);
2006 }
2007 SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT HandleType,
2008 SQLHANDLE Handle,
2009 SQLSMALLINT RecNumber,
2010 SQLCHAR *SQLState,
2011 SQLINTEGER *NativeErrorPtr,
2012 SQLCHAR *MessageText,
2013 SQLSMALLINT BufferLength,
2014 SQLSMALLINT *TextLengthPtr)
2015 {
2016 return MA_SQLGetDiagRec(HandleType, Handle, RecNumber, SQLState, NativeErrorPtr,
2017 MessageText, BufferLength, TextLengthPtr);
2018 }
2019 /* }}} */
2020
2021 /* {{{ SQLGetDiagRecW */
2022 SQLRETURN SQL_API SQLGetDiagRecW(SQLSMALLINT HandleType,
2023 SQLHANDLE Handle,
2024 SQLSMALLINT RecNumber,
2025 SQLWCHAR *SQLState,
2026 SQLINTEGER *NativeErrorPtr,
2027 SQLWCHAR *MessageText,
2028 SQLSMALLINT BufferLength,
2029 SQLSMALLINT *TextLengthPtr)
2030 {
2031 return MA_SQLGetDiagRecW(HandleType, Handle, RecNumber, SQLState, NativeErrorPtr, MessageText,
2032 BufferLength, TextLengthPtr);
2033 }
2034 /* }}} */
2035
2036 /* {{{ SQLGetEnvAttr */
2037 SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV EnvironmentHandle,
2038 SQLINTEGER Attribute,
2039 SQLPOINTER ValuePtr,
2040 SQLINTEGER BufferLength,
2041 SQLINTEGER *StringLengthPtr)
2042 {
2043 MADB_Env *Env= (MADB_Env *)EnvironmentHandle;
2044 SQLRETURN ret;
2045
2046 MDBUG_ENTER("SQLGetEnvAttr");
2047 MDBUG_DUMP(Attribute, d);
2048 MDBUG_DUMP(ValuePtr, 0x);
2049 MDBUG_DUMP(BufferLength, d);
2050 MDBUG_DUMP(StringLengthPtr, 0x);
2051
2052 if (!Env)
2053 ret= SQL_INVALID_HANDLE;
2054 else
2055 {
2056 MADB_CLEAR_ERROR(&Env->Error);
2057 ret= MADB_EnvGetAttr(Env, Attribute, ValuePtr, BufferLength, StringLengthPtr);
2058 }
2059
2060 MDBUG_DUMP(ret, d);
2061 MDBUG_RETURN(ret);
2062 }
2063 /* {{{ SQLGetFunctions */
2064 SQLRETURN SQL_API SQLGetFunctions(SQLHDBC ConnectionHandle,
2065 SQLUSMALLINT FunctionId,
2066 SQLUSMALLINT *SupportedPtr)
2067 {
2068 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
2069 SQLRETURN ret;
2070
2071 if (!Dbc)
2072 return SQL_INVALID_HANDLE;
2073 MADB_CLEAR_ERROR(&Dbc->Error);
2074
2075 MDBUG_C_ENTER(Dbc, "SQLGetFunctions");
2076 MDBUG_C_DUMP(Dbc, FunctionId, d);
2077 MDBUG_C_DUMP(Dbc, SupportedPtr, 0x);
2078 ret= Dbc->Methods->GetFunctions(Dbc, FunctionId, SupportedPtr);
2079
2080 MDBUG_C_RETURN(Dbc,ret, &Dbc->Error);
2081 }
2082 /* }}} */
2083
2084 /* {{{ SQLGetInfo */
2085 SQLRETURN SQL_API SQLGetInfo(SQLHDBC ConnectionHandle,
2086 SQLUSMALLINT InfoType,
2087 SQLPOINTER InfoValuePtr,
2088 SQLSMALLINT BufferLength,
2089 SQLSMALLINT *StringLengthPtr)
2090 {
2091 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
2092 SQLRETURN ret;
2093 if (!Dbc)
2094 return SQL_INVALID_HANDLE;
2095 MADB_CLEAR_ERROR(&Dbc->Error);
2096
2097 MDBUG_C_ENTER(Dbc, "SQLGetInfo");
2098 MDBUG_C_DUMP(Dbc, InfoType, d);
2099 ret= Dbc->Methods->GetInfo(Dbc, InfoType, InfoValuePtr, BufferLength, StringLengthPtr, FALSE);
2100
2101 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
2102 }
2103 /* }}} */
2104
2105 /* {{{ SQLGetInfoW */
2106 SQLRETURN SQL_API SQLGetInfoW(SQLHDBC ConnectionHandle,
2107 SQLUSMALLINT InfoType,
2108 SQLPOINTER InfoValuePtr,
2109 SQLSMALLINT BufferLength,
2110 SQLSMALLINT *StringLengthPtr)
2111 {
2112 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
2113 SQLRETURN ret;
2114 if (!Dbc)
2115 return SQL_INVALID_HANDLE;
2116 MADB_CLEAR_ERROR(&Dbc->Error);
2117
2118 MDBUG_C_ENTER(Dbc, "SQLGetInfo");
2119 MDBUG_C_DUMP(Dbc, InfoType, d);
2120 MDBUG_C_DUMP(Dbc, InfoValuePtr, 0x);
2121 MDBUG_C_DUMP(Dbc, StringLengthPtr, 0x);
2122 ret= Dbc->Methods->GetInfo(Dbc, InfoType, InfoValuePtr, BufferLength, StringLengthPtr, TRUE);
2123
2124 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
2125 }
2126 /* }}} */
2127
2128 /* {{{ SQLGetStmtAttr */
2129 SQLRETURN MA_SQLGetStmtAttr(SQLHSTMT StatementHandle,
2130 SQLINTEGER Attribute,
2131 SQLPOINTER ValuePtr,
2132 SQLINTEGER BufferLength,
2133 SQLINTEGER *StringLengthPtr)
2134 {
2135 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2136 if (!Stmt)
2137 return SQL_INVALID_HANDLE;
2138 return Stmt->Methods->GetAttr(Stmt, Attribute, ValuePtr, BufferLength, StringLengthPtr);
2139 }
2140 SQLRETURN SQL_API SQLGetStmtAttr(SQLHSTMT StatementHandle,
2141 SQLINTEGER Attribute,
2142 SQLPOINTER ValuePtr,
2143 SQLINTEGER BufferLength,
2144 SQLINTEGER *StringLengthPtr)
2145 {
2146 if (StatementHandle == SQL_NULL_HSTMT)
2147 {
2148 return SQL_INVALID_HANDLE;
2149 }
2150 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
2151
2152 return MA_SQLGetStmtAttr(StatementHandle, Attribute, ValuePtr, BufferLength, StringLengthPtr);
2153 }
2154 /* }}} */
2155
2156 /* {{{ SQLGetStmtAttrW */
2157 SQLRETURN SQL_API SQLGetStmtAttrW(SQLHSTMT StatementHandle,
2158 SQLINTEGER Attribute,
2159 SQLPOINTER ValuePtr,
2160 SQLINTEGER BufferLength,
2161 SQLINTEGER *StringLengthPtr)
2162 {
2163 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2164 if (!Stmt)
2165 return SQL_INVALID_HANDLE;
2166 MADB_CLEAR_ERROR(&Stmt->Error);
2167
2168 return Stmt->Methods->GetAttr(Stmt, Attribute, ValuePtr, BufferLength, StringLengthPtr);
2169 }
2170 /* }}} */
2171
2172 /* {{{ SQLGetStmtOption */
2173 SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT StatementHandle,
2174 SQLUSMALLINT Option, SQLPOINTER Value)
2175 {
2176 if (StatementHandle == SQL_NULL_HSTMT)
2177 {
2178 return SQL_INVALID_HANDLE;
2179 }
2180 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
2181
2182 return MA_SQLGetStmtAttr(StatementHandle, Option, Value, SQL_NTS, (SQLINTEGER *)NULL);
2183 }
2184
2185 /* }}} */
2186
2187 /* {{{ SQLGetTypeInfo */
2188 SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT StatementHandle,
2189 SQLSMALLINT DataType)
2190 {
2191 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2192 if (!Stmt)
2193 return SQL_INVALID_HANDLE;
2194 MADB_CLEAR_ERROR(&Stmt->Error);
2195
2196 return MADB_GetTypeInfo(Stmt, DataType);
2197 }
2198 /* }}} */
2199
2200 /* {{{ SQLGetTypeInfoW */
2201 SQLRETURN SQL_API SQLGetTypeInfoW(SQLHSTMT StatementHandle,
2202 SQLSMALLINT DataType)
2203 {
2204 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2205 if (!Stmt)
2206 return SQL_INVALID_HANDLE;
2207 MADB_CLEAR_ERROR(&Stmt->Error);
2208
2209 return MADB_GetTypeInfo(Stmt, DataType);}
2210 /* }}} */
2211
2212 /* {{{ SQLMoreResults */
2213 SQLRETURN SQL_API SQLMoreResults(SQLHSTMT StatementHandle)
2214 {
2215 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2216 if (!Stmt)
2217 return SQL_INVALID_HANDLE;
2218 MADB_CLEAR_ERROR(&Stmt->Error);
2219
2220 return MADB_StmtMoreResults(Stmt);
2221 }
2222 /* }}} */
2223
2224 /* {{{ SQLNativeSql */
2225 SQLRETURN SQL_API SQLNativeSql(SQLHDBC ConnectionHandle,
2226 SQLCHAR *InStatementText,
2227 SQLINTEGER TextLength1,
2228 SQLCHAR *OutStatementText,
2229 SQLINTEGER BufferLength,
2230 SQLINTEGER *TextLength2Ptr)
2231 {
2232 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
2233 SQLINTEGER Length;
2234 if (!Dbc)
2235 return SQL_INVALID_HANDLE;
2236 MADB_CLEAR_ERROR(&Dbc->Error);
2237
2238 if (!TextLength2Ptr && (!OutStatementText || !BufferLength))
2239 {
2240 MADB_SetError(&Dbc->Error, MADB_ERR_01004, NULL, 0);
2241 return Dbc->Error.ReturnValue;
2242 }
2243 Length= (SQLINTEGER)MADB_SetString(0, OutStatementText, BufferLength, (char *)InStatementText, TextLength1, &Dbc->Error);
2244 if (TextLength2Ptr)
2245 *TextLength2Ptr= Length;
2246 return Dbc->Error.ReturnValue;
2247 }
2248 /* }}} */
2249
2250 /* {{{ SQLNativeSqlW */
2251 SQLRETURN SQL_API SQLNativeSqlW(SQLHDBC ConnectionHandle,
2252 SQLWCHAR *InStatementText,
2253 SQLINTEGER TextLength1,
2254 SQLWCHAR *OutStatementText,
2255 SQLINTEGER BufferLength,
2256 SQLINTEGER *TextLength2Ptr)
2257 {
2258 MADB_Dbc *Conn= (MADB_Dbc *)ConnectionHandle;
2259 SQLINTEGER Length= (TextLength1 == SQL_NTS) ? SqlwcsCharLen(InStatementText, (SQLLEN)-1) : TextLength1;
2260
2261 if (!Conn)
2262 return SQL_INVALID_HANDLE;
2263 MADB_CLEAR_ERROR(&Conn->Error);
2264
2265 if (TextLength2Ptr)
2266 *TextLength2Ptr= Length;
2267
2268 if(OutStatementText && BufferLength < Length)
2269 MADB_SetError(&Conn->Error, MADB_ERR_01004, NULL, 0);
2270
2271 if(OutStatementText && BufferLength < Length)
2272 MADB_SetError(&Conn->Error, MADB_ERR_01004, NULL, 0);
2273 Length= MIN(Length, BufferLength - 1);
2274
2275 if (OutStatementText && BufferLength)
2276 {
2277 memcpy(OutStatementText, InStatementText, Length * sizeof(SQLWCHAR));
2278 OutStatementText[Length]= 0;
2279 }
2280 return Conn->Error.ReturnValue;
2281 }
2282 /* }}} */
2283
2284 /* {{{ SQLNumParams */
2285 SQLRETURN SQL_API SQLNumParams(SQLHSTMT StatementHandle,
2286 SQLSMALLINT *ParameterCountPtr)
2287 {
2288 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2289
2290 MADB_CHECK_STMT_HANDLE(Stmt, stmt);
2291 MADB_CLEAR_ERROR(&Stmt->Error);
2292
2293 return Stmt->Methods->ParamCount(Stmt, ParameterCountPtr);
2294 }
2295 /* }}} */
2296
2297 /* {{{ SQLNumResultCols */
2298 SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle,
2299 SQLSMALLINT *ColumnCountPtr)
2300 {
2301 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2302 MADB_CHECK_STMT_HANDLE(Stmt, stmt);
2303 MADB_CLEAR_ERROR(&Stmt->Error);
2304
2305 return Stmt->Methods->ColumnCount(Stmt, ColumnCountPtr);
2306 }
2307 /* }}} */
2308
2309 /* {{{ SQLParamData */
2310 SQLRETURN SQL_API SQLParamData(SQLHSTMT StatementHandle,
2311 SQLPOINTER *ValuePtrPtr)
2312 {
2313 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2314 if (!Stmt)
2315 return SQL_INVALID_HANDLE;
2316 MADB_CLEAR_ERROR(&Stmt->Error);
2317
2318 return Stmt->Methods->ParamData(Stmt, ValuePtrPtr);
2319 }
2320 /* }}} */
2321
2322
2323 SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle,
2324 SQLCHAR *StatementText,
2325 SQLINTEGER TextLength)
2326 {
2327 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2328
2329 if (StatementHandle == SQL_NULL_HSTMT)
2330 {
2331 return SQL_INVALID_HANDLE;
2332 }
2333
2334 MDBUG_C_ENTER(Stmt->Connection, "SQLPrepare");
2335
2336 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
2337 MDBUG_C_DUMP(Stmt->Connection, StatementText, s);
2338 MDBUG_C_DUMP(Stmt->Connection, TextLength, d);
2339
2340 /* Prepare method clears error */
2341
2342 return Stmt->Methods->Prepare(Stmt, (char *)StatementText, TextLength, FALSE);
2343 }
2344 /* }}} */
2345
2346 /* {{{ SQLPrepareW */
2347 SQLRETURN SQL_API SQLPrepareW(SQLHSTMT StatementHandle,
2348 SQLWCHAR *StatementText,
2349 SQLINTEGER TextLength)
2350 {
2351 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2352 char *StmtStr;
2353 SQLULEN StmtLength;
2354 SQLRETURN ret;
2355 BOOL ConversionError;
2356
2357 if (!Stmt)
2358 return SQL_INVALID_HANDLE;
2359 MADB_CLEAR_ERROR(&Stmt->Error);
2360
2361 MDBUG_C_ENTER(Stmt->Connection, "SQLPrepareW");
2362
2363 StmtStr= MADB_ConvertFromWChar(StatementText, TextLength, &StmtLength, Stmt->Connection->ConnOrSrcCharset, &ConversionError);
2364
2365 MDBUG_C_DUMP(Stmt->Connection, Stmt, 0x);
2366 MDBUG_C_DUMP(Stmt->Connection, StmtStr, s);
2367 MDBUG_C_DUMP(Stmt->Connection, TextLength, d);
2368
2369 if (ConversionError)
2370 {
2371 MADB_SetError(&Stmt->Error, MADB_ERR_22018, NULL, 0);
2372 ret= Stmt->Error.ReturnValue;
2373 }
2374 else
2375 ret= Stmt->Methods->Prepare(Stmt, StmtStr, (SQLINTEGER)StmtLength, FALSE);
2376 MADB_FREE(StmtStr);
2377
2378 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
2379 }
2380 /* }}} */
2381
2382 /* {{{ SQLPrimaryKeys */
2383 SQLRETURN SQL_API SQLPrimaryKeys(SQLHSTMT StatementHandle,
2384 SQLCHAR *CatalogName,
2385 SQLSMALLINT NameLength1,
2386 SQLCHAR *SchemaName,
2387 SQLSMALLINT NameLength2,
2388 SQLCHAR *TableName,
2389 SQLSMALLINT NameLength3)
2390 {
2391 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2392 SQLRETURN ret;
2393
2394 MDBUG_C_ENTER(Stmt->Connection, "SQLPrimaryKeys");
2395 MDBUG_C_DUMP(Stmt->Connection, StatementHandle, 0x);
2396 MDBUG_C_DUMP(Stmt->Connection, CatalogName, s);
2397 MDBUG_C_DUMP(Stmt->Connection, NameLength1, d);
2398 MDBUG_C_DUMP(Stmt->Connection, SchemaName, s);
2399 MDBUG_C_DUMP(Stmt->Connection, NameLength2, d);
2400 MDBUG_C_DUMP(Stmt->Connection, TableName, s);
2401 MDBUG_C_DUMP(Stmt->Connection, NameLength3, d);
2402
2403 if (!Stmt)
2404 ret= SQL_INVALID_HANDLE;
2405 else
2406 {
2407 MADB_CLEAR_ERROR(&Stmt->Error);
2408 ret= Stmt->Methods->PrimaryKeys(Stmt, (char *)CatalogName, NameLength1, (char *)SchemaName, NameLength2,
2409 (char *)TableName, NameLength3);
2410 }
2411
2412 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
2413 }
2414 /* }}} */
2415
2416 /* {{{ SQLPrimaryKeysW */
2417 SQLRETURN SQL_API SQLPrimaryKeysW(SQLHSTMT StatementHandle,
2418 SQLWCHAR *CatalogName,
2419 SQLSMALLINT NameLength1,
2420 SQLWCHAR *SchemaName,
2421 SQLSMALLINT NameLength2,
2422 SQLWCHAR *TableName,
2423 SQLSMALLINT NameLength3)
2424 {
2425 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2426 char *CpCatalog= NULL,
2427 *CpSchema= NULL,
2428 *CpTable= NULL;
2429 SQLULEN CpLength1, CpLength2, CpLength3;
2430 SQLRETURN ret;
2431
2432 if (!Stmt)
2433 return SQL_INVALID_HANDLE;
2434 MADB_CLEAR_ERROR(&Stmt->Error);
2435
2436 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
2437 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
2438 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
2439
2440 MDBUG_C_ENTER(Stmt->Connection, "SQLPrimaryKeysW");
2441 MDBUG_C_DUMP(Stmt->Connection, StatementHandle, 0x);
2442 MDBUG_C_DUMP(Stmt->Connection, CpCatalog, s);
2443 MDBUG_C_DUMP(Stmt->Connection, CpLength1, d);
2444 MDBUG_C_DUMP(Stmt->Connection, CpSchema, s);
2445 MDBUG_C_DUMP(Stmt->Connection, CpLength2, d);
2446 MDBUG_C_DUMP(Stmt->Connection, CpTable, s);
2447 MDBUG_C_DUMP(Stmt->Connection, CpLength3, d);
2448
2449 ret= Stmt->Methods->PrimaryKeys(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
2450 CpTable, (SQLSMALLINT)CpLength3);
2451 MADB_FREE(CpCatalog);
2452 MADB_FREE(CpSchema);
2453 MADB_FREE(CpTable);
2454
2455 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
2456 }
2457 /* }}} */
2458
2459 /* {{{ SQLProcedureColumns */
2460 SQLRETURN SQL_API SQLProcedureColumns(SQLHSTMT StatementHandle,
2461 SQLCHAR *CatalogName,
2462 SQLSMALLINT NameLength1,
2463 SQLCHAR *SchemaName,
2464 SQLSMALLINT NameLength2,
2465 SQLCHAR *ProcName,
2466 SQLSMALLINT NameLength3,
2467 SQLCHAR *ColumnName,
2468 SQLSMALLINT NameLength4)
2469 {
2470 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2471
2472 if (!Stmt)
2473 return SQL_INVALID_HANDLE;
2474 MADB_CLEAR_ERROR(&Stmt->Error);
2475
2476 return Stmt->Methods->ProcedureColumns(Stmt, (char *)CatalogName,NameLength1, (char *)SchemaName, NameLength2,
2477 (char *)ProcName, NameLength3, (char *)ColumnName, NameLength4);
2478
2479 }
2480 /* }}} */
2481
2482 /* {{{ SQLProcedureColumnsW */
2483 SQLRETURN SQL_API SQLProcedureColumnsW(SQLHSTMT StatementHandle,
2484 SQLWCHAR *CatalogName,
2485 SQLSMALLINT NameLength1,
2486 SQLWCHAR *SchemaName,
2487 SQLSMALLINT NameLength2,
2488 SQLWCHAR *ProcName,
2489 SQLSMALLINT NameLength3,
2490 SQLWCHAR *ColumnName,
2491 SQLSMALLINT NameLength4)
2492 {
2493 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2494 SQLRETURN ret;
2495 char *CpCatalog= NULL,
2496 *CpSchema= NULL,
2497 *CpProc= NULL,
2498 *CpColumn= NULL;
2499 SQLULEN CpLength1= 0, CpLength2= 0, CpLength3= 0, CpLength4= 0;
2500
2501 if (!Stmt)
2502 return SQL_INVALID_HANDLE;
2503 MADB_CLEAR_ERROR(&Stmt->Error);
2504
2505 if (CatalogName != NULL)
2506 {
2507 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
2508 }
2509 if (SchemaName != NULL)
2510 {
2511 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
2512 }
2513 if (ProcName != NULL)
2514 {
2515 CpProc= MADB_ConvertFromWChar(ProcName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
2516 }
2517 if (ColumnName != NULL)
2518 {
2519 CpColumn= MADB_ConvertFromWChar(ColumnName, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
2520 }
2521
2522 ret= Stmt->Methods->ProcedureColumns(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
2523 CpProc, (SQLSMALLINT)CpLength3, CpColumn, (SQLSMALLINT)CpLength4);
2524 MADB_FREE(CpCatalog);
2525 MADB_FREE(CpSchema);
2526 MADB_FREE(CpProc);
2527 MADB_FREE(CpColumn);
2528
2529 return ret;
2530 }
2531 /* }}} */
2532
2533 /* {{{ SQLProcedures */
2534 SQLRETURN SQL_API SQLProcedures(SQLHSTMT StatementHandle,
2535 SQLCHAR *CatalogName,
2536 SQLSMALLINT NameLength1,
2537 SQLCHAR *SchemaName,
2538 SQLSMALLINT NameLength2,
2539 SQLCHAR *ProcName,
2540 SQLSMALLINT NameLength3)
2541 {
2542 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2543
2544 if (!Stmt)
2545 return SQL_INVALID_HANDLE;
2546 MADB_CLEAR_ERROR(&Stmt->Error);
2547
2548 return Stmt->Methods->Procedures(Stmt, (char *)CatalogName, NameLength1, (char *)SchemaName,
2549 NameLength2, (char *)ProcName, NameLength3);
2550 }
2551 /* }}} */
2552
2553 /* {{{ SQLProceduresW */
2554 SQLRETURN SQL_API SQLProceduresW(SQLHSTMT StatementHandle,
2555 SQLWCHAR *CatalogName,
2556 SQLSMALLINT NameLength1,
2557 SQLWCHAR *SchemaName,
2558 SQLSMALLINT NameLength2,
2559 SQLWCHAR *ProcName,
2560 SQLSMALLINT NameLength3)
2561 {
2562 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2563 SQLRETURN ret;
2564 char *CpCatalog= NULL,
2565 *CpSchema= NULL,
2566 *CpProc= NULL;
2567 SQLULEN CpLength1, CpLength2, CpLength3;
2568
2569 if (!Stmt)
2570 return SQL_INVALID_HANDLE;
2571 MADB_CLEAR_ERROR(&Stmt->Error);
2572
2573 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
2574 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
2575 CpProc= MADB_ConvertFromWChar(ProcName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
2576
2577 ret= Stmt->Methods->Procedures(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
2578 CpProc, (SQLSMALLINT)CpLength3);
2579 MADB_FREE(CpCatalog);
2580 MADB_FREE(CpSchema);
2581 MADB_FREE(CpProc);
2582 return ret;
2583 }
2584 /* }}} */
2585
2586 /* {{{ SQLPutData */
2587 SQLRETURN SQL_API SQLPutData(SQLHSTMT StatementHandle,
2588 SQLPOINTER DataPtr,
2589 SQLLEN StrLen_or_Ind)
2590 {
2591 MADB_Stmt *Stmt=(MADB_Stmt *)StatementHandle;
2592 SQLRETURN ret;
2593
2594 if (!Stmt)
2595 return SQL_INVALID_HANDLE;
2596 MADB_CLEAR_ERROR(&Stmt->Error);
2597
2598 MDBUG_C_ENTER(Stmt->Connection, "SQLPutData");
2599 MDBUG_C_DUMP(Stmt->Connection, DataPtr, 0x);
2600 MDBUG_C_DUMP(Stmt->Connection, StrLen_or_Ind, d);
2601
2602 ret= Stmt->Methods->PutData(Stmt, DataPtr, StrLen_or_Ind);
2603
2604 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
2605 }
2606 /* }}} */
2607
2608 /* {{{ SQLRowCount */
2609 SQLRETURN SQL_API SQLRowCount(SQLHSTMT StatementHandle,
2610 SQLLEN *RowCountPtr)
2611 {
2612 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2613
2614 MADB_CHECK_STMT_HANDLE(Stmt, stmt);
2615 MADB_CLEAR_ERROR(&Stmt->Error);
2616
2617 return Stmt->Methods->RowCount(Stmt, RowCountPtr);
2618 }
2619 /* }}} */
2620
2621 /* {{{ SQLSetConnectAttr */
2622 SQLRETURN MA_SQLSetConnectAttr(SQLHDBC ConnectionHandle,
2623 SQLINTEGER Attribute,
2624 SQLPOINTER ValuePtr,
2625 SQLINTEGER StringLength)
2626 {
2627 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
2628 SQLRETURN ret;
2629
2630 if (!Dbc)
2631 return SQL_INVALID_HANDLE;
2632
2633 MDBUG_C_ENTER(Dbc, "SQLSetConnectAttr");
2634 MDBUG_C_DUMP(Dbc, Attribute, d);
2635 MDBUG_C_DUMP(Dbc, ValuePtr, 0x);
2636 MDBUG_C_DUMP(Dbc, StringLength, d);
2637
2638 ret= Dbc->Methods->SetAttr(Dbc, Attribute, ValuePtr, StringLength, FALSE);
2639
2640 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
2641 }
2642 /* }}} */
2643 SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC ConnectionHandle,
2644 SQLINTEGER Attribute,
2645 SQLPOINTER ValuePtr,
2646 SQLINTEGER StringLength)
2647 {
2648 if (ConnectionHandle == SQL_NULL_HDBC)
2649 return SQL_INVALID_HANDLE;
2650 MADB_CLEAR_ERROR(&((MADB_Dbc *)ConnectionHandle)->Error);
2651
2652 return MA_SQLSetConnectAttr(ConnectionHandle, Attribute, ValuePtr, StringLength);
2653 }
2654
2655 /* {{{ SQLSetConnectAttrW */
2656 SQLRETURN SQL_API SQLSetConnectAttrW(SQLHDBC ConnectionHandle,
2657 SQLINTEGER Attribute,
2658 SQLPOINTER ValuePtr,
2659 SQLINTEGER StringLength)
2660 {
2661 MADB_Dbc *Dbc= (MADB_Dbc *)ConnectionHandle;
2662 SQLRETURN ret;
2663 if (!Dbc)
2664 return SQL_INVALID_HANDLE;
2665 MADB_CLEAR_ERROR(&Dbc->Error);
2666
2667 MDBUG_C_ENTER(Dbc, "SetConnectAttrW");
2668 MDBUG_C_DUMP(Dbc, Dbc, 0x);
2669 MDBUG_C_DUMP(Dbc, Attribute, d);
2670 MDBUG_C_DUMP(Dbc, ValuePtr, 0x);
2671 MDBUG_C_DUMP(Dbc, StringLength, d);
2672 ret= Dbc->Methods->SetAttr(Dbc, Attribute, ValuePtr, StringLength, TRUE);
2673
2674 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
2675 }
2676 /* }}} */
2677
2678 /* {{{ SQLSetConnectOption */
2679 SQLRETURN SQL_API SQLSetConnectOption(SQLHDBC Hdbc, SQLUSMALLINT Option, SQLULEN Param)
2680 {
2681 SQLINTEGER StringLength= 0;
2682 SQLRETURN ret;
2683
2684 if (!Hdbc)
2685 return SQL_INVALID_HANDLE;
2686 MADB_CLEAR_ERROR(&((MADB_Dbc*)Hdbc)->Error);
2687
2688 /* todo: do we have more string options ? */
2689 if (Option == SQL_ATTR_CURRENT_CATALOG)
2690 StringLength= SQL_NTS;
2691 ret= MA_SQLSetConnectAttr(Hdbc, Option, (SQLPOINTER)Param, StringLength);
2692 return ret;
2693 }
2694 /* }}} */
2695
2696 /* {{{ SQLSetConnectOptionW */
2697 SQLRETURN SQL_API SQLSetConnectOptionW(SQLHDBC Hdbc, SQLUSMALLINT Option, SQLULEN Param)
2698 {
2699 SQLINTEGER StringLength= 0;
2700 SQLRETURN ret;
2701 MADB_Dbc *Dbc= (MADB_Dbc *)Hdbc;
2702
2703 if (!Dbc)
2704 return SQL_INVALID_HANDLE;
2705 MADB_CLEAR_ERROR(&Dbc->Error);
2706
2707 MDBUG_C_ENTER(Dbc, "SetSetConnectOptionW");
2708 MDBUG_C_DUMP(Dbc, Option, d);
2709 MDBUG_C_DUMP(Dbc, Param, u);
2710 /* todo: do we have more string options ? */
2711 if (Option == SQL_ATTR_CURRENT_CATALOG)
2712 StringLength= SQL_NTS;
2713
2714 ret= Dbc->Methods->SetAttr(Dbc, Option, (SQLPOINTER)Param, StringLength, TRUE);
2715
2716 MDBUG_C_RETURN(Dbc, ret, &Dbc->Error);
2717 }
2718 /* }}} */
2719
2720 /* {{{ SQLSetCursorName */
2721 SQLRETURN SQL_API SQLSetCursorName(SQLHSTMT StatementHandle,
2722 SQLCHAR *CursorName,
2723 SQLSMALLINT NameLength)
2724 {
2725 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2726 if (!Stmt)
2727 return SQL_INVALID_HANDLE;
2728 MADB_CLEAR_ERROR(&Stmt->Error);
2729
2730 return Stmt->Methods->SetCursorName(Stmt, (char *)CursorName, NameLength);
2731 }
2732 /* }}} */
2733
2734 /* {{{ SQLSetCursorNameW */
2735 SQLRETURN SQL_API SQLSetCursorNameW(SQLHSTMT StatementHandle,
2736 SQLWCHAR *CursorName,
2737 SQLSMALLINT NameLength)
2738 {
2739 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2740 char *CpName= NULL;
2741 SQLULEN Length;
2742 SQLRETURN rc;
2743
2744 if (!Stmt)
2745 {
2746 return SQL_INVALID_HANDLE;
2747 }
2748 MADB_CLEAR_ERROR(&Stmt->Error);
2749
2750 CpName= MADB_ConvertFromWChar(CursorName, NameLength, &Length, Stmt->Connection->ConnOrSrcCharset, NULL);
2751 rc= Stmt->Methods->SetCursorName(Stmt, (char *)CpName, (SQLINTEGER)Length);
2752
2753 MADB_FREE(CpName);
2754
2755 return rc;
2756 }
2757 /* }}} */
2758
2759 /* {{{ SQLSetDescField */
2760 SQLRETURN SQL_API SQLSetDescField(SQLHDESC DescriptorHandle,
2761 SQLSMALLINT RecNumber,
2762 SQLSMALLINT FieldIdentifier,
2763 SQLPOINTER ValuePtr,
2764 SQLINTEGER BufferLength)
2765 {
2766 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
2767 if (!Desc)
2768 return SQL_INVALID_HANDLE;
2769 MADB_CLEAR_ERROR(&Desc->Error);
2770
2771 return MADB_DescSetField(DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, FALSE);
2772 }
2773 /* }}} */
2774
2775 /* {{{ SQLSetDescFieldW */
2776 SQLRETURN SQL_API SQLSetDescFieldW(SQLHDESC DescriptorHandle,
2777 SQLSMALLINT RecNumber,
2778 SQLSMALLINT FieldIdentifier,
2779 SQLPOINTER ValuePtr,
2780 SQLINTEGER BufferLength)
2781 {
2782 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
2783 if (!Desc)
2784 return SQL_INVALID_HANDLE;
2785 MADB_CLEAR_ERROR(&Desc->Error);
2786
2787 return MADB_DescSetField(DescriptorHandle, RecNumber, FieldIdentifier, ValuePtr, BufferLength, TRUE);
2788 }
2789 /* }}} */
2790
2791 /* {{{ SQLSetDescRec */
2792 SQLRETURN SQL_API SQLSetDescRec(SQLHDESC DescriptorHandle,
2793 SQLSMALLINT RecNumber,
2794 SQLSMALLINT Type,
2795 SQLSMALLINT SubType,
2796 SQLLEN Length,
2797 SQLSMALLINT Precision,
2798 SQLSMALLINT Scale,
2799 SQLPOINTER DataPtr,
2800 SQLLEN *StringLengthPtr,
2801 SQLLEN *IndicatorPtr)
2802 {
2803 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
2804 MADB_NOT_IMPLEMENTED(Desc);
2805 }
2806 /* }}} */
2807
2808 /* {{{ SQLSetDescRecW */
2809 SQLRETURN SQL_API SQLSetDescRecW(SQLHDESC DescriptorHandle,
2810 SQLSMALLINT RecNumber,
2811 SQLSMALLINT Type,
2812 SQLSMALLINT SubType,
2813 SQLLEN Length,
2814 SQLSMALLINT Precision,
2815 SQLSMALLINT Scale,
2816 SQLPOINTER DataPtr,
2817 SQLLEN *StringLengthPtr,
2818 SQLLEN *IndicatorPtr)
2819 {
2820 MADB_Desc *Desc= (MADB_Desc *)DescriptorHandle;
2821 MADB_NOT_IMPLEMENTED(Desc);
2822 }
2823 /* }}} */
2824
2825 /* {{{ SQLSetEnvAttr */
2826 SQLRETURN SQL_API SQLSetEnvAttr(SQLHENV EnvironmentHandle,
2827 SQLINTEGER Attribute,
2828 SQLPOINTER ValuePtr,
2829 SQLINTEGER StringLength)
2830 {
2831 MADB_Env *Env= (MADB_Env *)EnvironmentHandle;
2832 SQLRETURN ret;
2833 MDBUG_ENTER("SQLSetEnvAttr");
2834 MDBUG_DUMP(Attribute, d);
2835 MDBUG_DUMP(ValuePtr, 0x);
2836 if (!Env)
2837 ret= SQL_INVALID_HANDLE;
2838 else
2839 {
2840 MADB_CLEAR_ERROR(&Env->Error);
2841 ret= MADB_EnvSetAttr(Env, Attribute, ValuePtr, StringLength);
2842 }
2843 MDBUG_DUMP(ret, d);
2844 MDBUG_RETURN(ret);
2845 }
2846 /* }}} */
2847
2848
2849 /* {{{ SQLSetPos */
2850 SQLRETURN SQL_API SQLSetPos(SQLHSTMT StatementHandle,
2851 SQLSETPOSIROW RowNumber,
2852 SQLUSMALLINT Operation,
2853 SQLUSMALLINT LockType)
2854 {
2855 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2856 SQLRETURN ret;
2857 if (!Stmt)
2858 return SQL_INVALID_HANDLE;
2859 MADB_CLEAR_ERROR(&Stmt->Error);
2860
2861 MDBUG_C_ENTER(Stmt->Connection, "SQLSetPos");
2862 MDBUG_C_DUMP(Stmt->Connection, RowNumber, d);
2863 MDBUG_C_DUMP(Stmt->Connection, Operation, u);
2864 MDBUG_C_DUMP(Stmt->Connection, LockType, d);
2865
2866 ret= Stmt->Methods->SetPos(Stmt, RowNumber, Operation, LockType, 0);
2867
2868 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
2869 }
2870 /* }}} */
2871
2872 /* {{{ SQLSetParam */
2873 SQLRETURN SQL_API SQLSetParam(SQLHSTMT stmt,
2874 SQLUSMALLINT par,
2875 SQLSMALLINT type,
2876 SQLSMALLINT sqltype,
2877 SQLULEN coldef,
2878 SQLSMALLINT scale,
2879 SQLPOINTER val,
2880 SQLLEN *nval)
2881 {
2882 if (!stmt)
2883 return SQL_INVALID_HANDLE;
2884 MADB_CLEAR_ERROR(&((MADB_Stmt*)stmt)->Error);
2885 return MA_SQLBindParameter(stmt, par, SQL_PARAM_INPUT_OUTPUT, type, sqltype, coldef,
2886 scale, val, SQL_SETPARAM_VALUE_MAX, nval);
2887 }
2888 /* }}} */
2889
2890 /* {{{ SQLBindParam - we need it for direct linking mainly */
2891 SQLRETURN SQL_API SQLBindParam(SQLHSTMT StatementHandle,
2892 SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType,
2893 SQLSMALLINT ParameterType, SQLULEN LengthPrecision,
2894 SQLSMALLINT ParameterScale, SQLPOINTER ParameterValue,
2895 SQLLEN *StrLen_or_Ind)
2896 {
2897 if (!StatementHandle)
2898 return SQL_INVALID_HANDLE;
2899 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
2900
2901 return MA_SQLBindParameter(StatementHandle, ParameterNumber, SQL_PARAM_INPUT, ValueType, ParameterType, LengthPrecision, ParameterScale,
2902 ParameterValue, SQL_SETPARAM_VALUE_MAX, StrLen_or_Ind);
2903
2904 }
2905 /* }}} */
2906
2907 /* {{{ SQLSetStmtAttr */
2908 SQLRETURN MA_SQLSetStmtAttr(SQLHSTMT StatementHandle,
2909 SQLINTEGER Attribute,
2910 SQLPOINTER ValuePtr,
2911 SQLINTEGER StringLength)
2912 {
2913 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2914 SQLRETURN ret;
2915
2916 if (!Stmt)
2917 return SQL_INVALID_HANDLE;
2918
2919 MDBUG_C_ENTER(Stmt->Connection, "SQLSetStmtAttr");
2920 MDBUG_C_DUMP(Stmt->Connection, Attribute, d);
2921 MDBUG_C_DUMP(Stmt->Connection, ValuePtr, 0x);
2922 MDBUG_C_DUMP(Stmt->Connection, StringLength, d);
2923
2924 ret= Stmt->Methods->SetAttr(Stmt, Attribute, ValuePtr, StringLength);
2925
2926 MDBUG_C_RETURN(Stmt->Connection, ret, &Stmt->Error);
2927 }
2928
2929 SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle,
2930 SQLINTEGER Attribute,
2931 SQLPOINTER ValuePtr,
2932 SQLINTEGER StringLength)
2933 {
2934 if (StatementHandle == SQL_NULL_HSTMT)
2935 {
2936 return SQL_INVALID_HANDLE;
2937 }
2938 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
2939
2940 return MA_SQLSetStmtAttr(StatementHandle, Attribute, ValuePtr, StringLength);
2941 }
2942 /* }}} */
2943
2944 /* {{{ SQLSetStmtAttrW */
2945 SQLRETURN SQL_API SQLSetStmtAttrW(SQLHSTMT StatementHandle,
2946 SQLINTEGER Attribute,
2947 SQLPOINTER ValuePtr,
2948 SQLINTEGER StringLength)
2949 {
2950 if (StatementHandle == SQL_NULL_HSTMT)
2951 {
2952 return SQL_INVALID_HANDLE;
2953 }
2954 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
2955
2956 return MA_SQLSetStmtAttr(StatementHandle, Attribute, ValuePtr, StringLength);
2957 }
2958 /* }}} */
2959
2960 /* {{{ SQLSetStmtOption */
2961 SQLRETURN SQL_API SQLSetStmtOption(SQLHSTMT StatementHandle,
2962 SQLUSMALLINT Option, SQLULEN Value)
2963 {
2964 if (StatementHandle == SQL_NULL_HSTMT)
2965 {
2966 return SQL_INVALID_HANDLE;
2967 }
2968 MADB_CLEAR_ERROR(&((MADB_Stmt*)StatementHandle)->Error);
2969 return MA_SQLSetStmtAttr(StatementHandle, Option, (SQLPOINTER)Value, SQL_NTS);
2970 }
2971 /* }}} */
2972
2973 /* {{{ SQLSpecialColumns */
2974 SQLRETURN SQL_API SQLSpecialColumns(SQLHSTMT StatementHandle,
2975 SQLUSMALLINT IdentifierType,
2976 SQLCHAR *CatalogName,
2977 SQLSMALLINT NameLength1,
2978 SQLCHAR *SchemaName,
2979 SQLSMALLINT NameLength2,
2980 SQLCHAR *TableName,
2981 SQLSMALLINT NameLength3,
2982 SQLUSMALLINT Scope,
2983 SQLUSMALLINT Nullable)
2984 {
2985 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
2986 if (!Stmt)
2987 return SQL_INVALID_HANDLE;
2988 MADB_CLEAR_ERROR(&Stmt->Error);
2989
2990 return Stmt->Methods->SpecialColumns(Stmt,IdentifierType, (char *)CatalogName, NameLength1,
2991 (char *)SchemaName, NameLength2,
2992 (char *)TableName, NameLength3, Scope, Nullable);
2993 }
2994 /* }}} */
2995
2996 /* {{{ SQLSpecialColumnsW */
2997 SQLRETURN SQL_API SQLSpecialColumnsW(SQLHSTMT StatementHandle,
2998 SQLUSMALLINT IdentifierType,
2999 SQLWCHAR *CatalogName,
3000 SQLSMALLINT NameLength1,
3001 SQLWCHAR *SchemaName,
3002 SQLSMALLINT NameLength2,
3003 SQLWCHAR *TableName,
3004 SQLSMALLINT NameLength3,
3005 SQLUSMALLINT Scope,
3006 SQLUSMALLINT Nullable)
3007 {
3008 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3009 SQLRETURN ret;
3010 char *CpCatalog= NULL,
3011 *CpSchema= NULL,
3012 *CpTable= NULL;
3013 SQLULEN CpLength1, CpLength2, CpLength3;
3014
3015 if (!Stmt)
3016 return SQL_INVALID_HANDLE;
3017 MADB_CLEAR_ERROR(&Stmt->Error);
3018
3019 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
3020 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
3021 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
3022
3023 ret= Stmt->Methods->SpecialColumns(Stmt,IdentifierType, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema,
3024 (SQLSMALLINT)CpLength2, CpTable, (SQLSMALLINT)CpLength3, Scope, Nullable);
3025 MADB_FREE(CpCatalog);
3026 MADB_FREE(CpSchema);
3027 MADB_FREE(CpTable);
3028 return ret;
3029 }
3030 /* }}} */
3031
3032 /* {{{ SQLStatistics */
3033 SQLRETURN SQL_API SQLStatistics(SQLHSTMT StatementHandle,
3034 SQLCHAR *CatalogName,
3035 SQLSMALLINT NameLength1,
3036 SQLCHAR *SchemaName,
3037 SQLSMALLINT NameLength2,
3038 SQLCHAR *TableName,
3039 SQLSMALLINT NameLength3,
3040 SQLUSMALLINT Unique,
3041 SQLUSMALLINT Reserved)
3042 {
3043 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3044
3045 if (!Stmt)
3046 return SQL_INVALID_HANDLE;
3047 MADB_CLEAR_ERROR(&Stmt->Error);
3048
3049 return Stmt->Methods->Statistics(Stmt, (char *)CatalogName, NameLength1, (char *)SchemaName, NameLength2,
3050 (char *)TableName, NameLength3, Unique, Reserved);
3051 }
3052 /* }}} */
3053
3054 /* {{{ SQLStatisticsW */
3055 SQLRETURN SQL_API SQLStatisticsW(SQLHSTMT StatementHandle,
3056 SQLWCHAR *CatalogName,
3057 SQLSMALLINT NameLength1,
3058 SQLWCHAR *SchemaName,
3059 SQLSMALLINT NameLength2,
3060 SQLWCHAR *TableName,
3061 SQLSMALLINT NameLength3,
3062 SQLUSMALLINT Unique,
3063 SQLUSMALLINT Reserved)
3064 {
3065 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3066 SQLRETURN ret;
3067 char *CpCatalog= NULL,
3068 *CpSchema= NULL,
3069 *CpTable= NULL;
3070 SQLULEN CpLength1, CpLength2, CpLength3;
3071
3072 if (!Stmt)
3073 return SQL_INVALID_HANDLE;
3074 MADB_CLEAR_ERROR(&Stmt->Error);
3075
3076 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
3077 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
3078 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
3079
3080 if (!Stmt)
3081 return SQL_INVALID_HANDLE;
3082 ret= Stmt->Methods->Statistics(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
3083 CpTable, (SQLSMALLINT)CpLength3, Unique, Reserved);
3084 MADB_FREE(CpCatalog);
3085 MADB_FREE(CpSchema);
3086 MADB_FREE(CpTable);
3087 return ret;
3088 }
3089 /* }}} */
3090
3091 /* {{{ SQLTablePrivileges */
3092 SQLRETURN SQL_API SQLTablePrivileges(SQLHSTMT StatementHandle,
3093 SQLCHAR *CatalogName,
3094 SQLSMALLINT NameLength1,
3095 SQLCHAR *SchemaName,
3096 SQLSMALLINT NameLength2,
3097 SQLCHAR *TableName,
3098 SQLSMALLINT NameLength3)
3099 {
3100 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3101
3102 if (!Stmt)
3103 return SQL_INVALID_HANDLE;
3104 MADB_CLEAR_ERROR(&Stmt->Error);
3105
3106 return Stmt->Methods->TablePrivileges(Stmt, (char *)CatalogName, NameLength1, (char *)SchemaName, NameLength2,
3107 (char *)TableName, NameLength3);
3108 }
3109 /* }}} */
3110
3111 /* {{{ SQLTablePrivilegesW */
3112 SQLRETURN SQL_API SQLTablePrivilegesW(SQLHSTMT StatementHandle,
3113 SQLWCHAR *CatalogName,
3114 SQLSMALLINT NameLength1,
3115 SQLWCHAR *SchemaName,
3116 SQLSMALLINT NameLength2,
3117 SQLWCHAR *TableName,
3118 SQLSMALLINT NameLength3)
3119 {
3120 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3121 SQLRETURN ret;
3122 char *CpCatalog= NULL,
3123 *CpTable= NULL;
3124 SQLULEN CpLength1= 0, CpLength3= 0;
3125
3126 if (!Stmt)
3127 return SQL_INVALID_HANDLE;
3128 MADB_CLEAR_ERROR(&Stmt->Error);
3129
3130 if (CatalogName != NULL)
3131 {
3132 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
3133 }
3134 if (TableName != NULL)
3135 {
3136 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
3137 }
3138
3139 ret= Stmt->Methods->TablePrivileges(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, NULL, 0, CpTable, (SQLSMALLINT)CpLength3);
3140
3141 MADB_FREE(CpCatalog);
3142 MADB_FREE(CpTable);
3143 return ret;
3144 }
3145 /* }}} */
3146
3147 /* {{{ SQLTables */
3148 SQLRETURN SQL_API SQLTables(SQLHSTMT StatementHandle,
3149 SQLCHAR *CatalogName,
3150 SQLSMALLINT NameLength1,
3151 SQLCHAR *SchemaName,
3152 SQLSMALLINT NameLength2,
3153 SQLCHAR *TableName,
3154 SQLSMALLINT NameLength3,
3155 SQLCHAR *TableType,
3156 SQLSMALLINT NameLength4)
3157 {
3158 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3159 if (!Stmt)
3160 return SQL_INVALID_HANDLE;
3161 MADB_CLEAR_ERROR(&Stmt->Error);
3162
3163 return Stmt->Methods->Tables(Stmt, (char *)CatalogName, NameLength1, (char *)SchemaName, NameLength2,
3164 (char *)TableName,NameLength3, (char *)TableType, NameLength4);
3165 }
3166 /* }}} */
3167
3168 /* {{{ SQLTablesW */
3169 SQLRETURN SQL_API SQLTablesW(SQLHSTMT StatementHandle,
3170 SQLWCHAR *CatalogName,
3171 SQLSMALLINT NameLength1,
3172 SQLWCHAR *SchemaName,
3173 SQLSMALLINT NameLength2,
3174 SQLWCHAR *TableName,
3175 SQLSMALLINT NameLength3,
3176 SQLWCHAR *TableType,
3177 SQLSMALLINT NameLength4)
3178 {
3179 MADB_Stmt *Stmt= (MADB_Stmt *)StatementHandle;
3180 char *CpCatalog= NULL,
3181 *CpSchema= NULL,
3182 *CpTable= NULL,
3183 *CpType= NULL;
3184 SQLULEN CpLength1= 0, CpLength2= 0, CpLength3= 0, CpLength4= 0;
3185 SQLRETURN ret;
3186
3187 if (!Stmt)
3188 return SQL_INVALID_HANDLE;
3189 MADB_CLEAR_ERROR(&Stmt->Error);
3190
3191 if (CatalogName)
3192 {
3193 CpCatalog= MADB_ConvertFromWChar(CatalogName, NameLength1, &CpLength1, Stmt->Connection->ConnOrSrcCharset, NULL);
3194 }
3195 if (SchemaName)
3196 {
3197 CpSchema= MADB_ConvertFromWChar(SchemaName, NameLength2, &CpLength2, Stmt->Connection->ConnOrSrcCharset, NULL);
3198 }
3199 if (TableName)
3200 {
3201 CpTable= MADB_ConvertFromWChar(TableName, NameLength3, &CpLength3, Stmt->Connection->ConnOrSrcCharset, NULL);
3202 }
3203 if (TableType)
3204 {
3205 CpType= MADB_ConvertFromWChar(TableType, NameLength4, &CpLength4, Stmt->Connection->ConnOrSrcCharset, NULL);
3206 }
3207
3208 ret= Stmt->Methods->Tables(Stmt, CpCatalog, (SQLSMALLINT)CpLength1, CpSchema, (SQLSMALLINT)CpLength2,
3209 CpTable, (SQLSMALLINT)CpLength3, CpType, (SQLSMALLINT)CpLength4);
3210 MADB_FREE(CpCatalog);
3211 MADB_FREE(CpSchema);
3212 MADB_FREE(CpTable);
3213 MADB_FREE(CpType);
3214 return ret;
3215 }
3216 /* }}} */
3217
3218 /* {{{ SQLSetScrollOptions */
3219 SQLRETURN SQL_API SQLSetScrollOptions(SQLHSTMT hstmt,
3220 SQLUSMALLINT Concurrency,
3221 SQLLEN crowKeySet,
3222 SQLUSMALLINT crowRowSet)
3223 {
3224 MADB_Stmt *Stmt= (MADB_Stmt *)hstmt;
3225 if (!Stmt)
3226 return SQL_INVALID_HANDLE;
3227 MADB_CLEAR_ERROR(&Stmt->Error);
3228
3229 return MADB_DescSetField(Stmt->Ard, 0, SQL_DESC_ARRAY_SIZE, (SQLPOINTER)(SQLULEN)crowKeySet, SQL_IS_USMALLINT, 0);
3230 }
3231 /* }}} */
3232
3233 /* {{{ SQLParamOptions */
3234 SQLRETURN SQL_API SQLParamOptions(
3235 SQLHSTMT hstmt,
3236 SQLULEN crow,
3237 SQLULEN *pirow)
3238 {
3239 MADB_Stmt *Stmt= (MADB_Stmt *)hstmt;
3240 SQLRETURN result;
3241 if (!Stmt)
3242 return SQL_INVALID_HANDLE;
3243 MADB_CLEAR_ERROR(&Stmt->Error);
3244
3245 result= MADB_DescSetField(Stmt->Apd, 0, SQL_DESC_ARRAY_SIZE, (SQLPOINTER)crow, SQL_IS_UINTEGER, 0);
3246
3247 if (SQL_SUCCEEDED(result))
3248 {
3249 result= MADB_DescSetField(Stmt->Ipd, 0, SQL_DESC_ROWS_PROCESSED_PTR, (SQLPOINTER)pirow, SQL_IS_POINTER, 0);
3250 }
3251
3252 return result;
3253 }
3254 /* }}} */
0 SET(ODBC_SOURCE_PKG_DIR ${CMAKE_SOURCE_DIR}/osxinstall)
1
2 # Get revision number
3 IF(WITH_REVNO)
4 EXECUTE_PROCESS(COMMAND git log HEAD^^..HEAD
5 COMMAND FINDSTR commit
6 OUTPUT_VARIABLE revno)
7 STRING(REPLACE "commit " "" revno ${revno})
8 STRING(REPLACE "\n" "" revno ${revno})
9 ENDIF()
10 IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
11 SET(PLATFORM "x86_64")
12 SET(PRODUCT_ARCH_BITS "64")
13 ELSE()
14 SET(PLATFORM "32bit")
15 SET(PRODUCT_ARCH_BITS "32")
16 endif()
17 SET(PRODUCT_NAME "MariaDB ODBC Driver")
18 SET(PRODUCT_MANUFACTURER "MariaDB")
19 SET(PRODUCT_VERSION "${MARIADB_ODBC_VERSION_MAJOR}.${MARIADB_ODBC_VERSION_MINOR}.${MARIADB_ODBC_VERSION_PATCH}")
20 SET(PRODUCT_SERIES "${MARIADB_ODBC_VERSION_MAJOR}.${MARIADB_ODBC_VERSION_MINOR}")
21 SET(PRODUCT_IDENTIFIER "com.mariadb.connector.odbc")
22
23 IF(${revno})
24 SET(PKG_PACKAGE "mariadb-connector-odbc-${PRODUCT_VERSION}-r${revno}-${PLATFORM}.pkg")
25 ELSE()
26 SET(PKG_PACKAGE "mariadb-connector-odbc-${PRODUCT_VERSION}-${PLATFORM}.pkg")
27 ENDIF()
28
29 MESSAGE(STATUS "PKG package file name ${PKG_PACKAGE}")
30
31 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/WELCOME.html.in
32 ${CMAKE_CURRENT_BINARY_DIR}/WELCOME.html @ONLY)
33 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/scripts/postinstall.in
34 ${CMAKE_CURRENT_BINARY_DIR}/scripts/postinstall @ONLY)
35
36 ADD_EXECUTABLE(install_driver install_driver.c)
37 TARGET_LINK_LIBRARIES(install_driver ${ODBC_INSTLIBS})#${PLATFORM_DEPENDENCIES})
38 # On Windows should look like
39 #TARGET_LINK_LIBRARIES(install_driver ${ODBC_INSTLIBS} legacy_stdio_definitions Shlwapi)
40
41
42 IF(USE_SYSTEM_INSTALLED_LIB)
43 ADD_CUSTOM_TARGET(copypkgfiles
44 COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/copy_package_files.sh $<TARGET_FILE_DIR:maodbc>
45 DEPENDS maodbc install_driver
46 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
47 ELSE()
48 ADD_CUSTOM_TARGET(copypkgfiles
49 COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/copy_package_files.sh $<TARGET_FILE_DIR:maodbc> $<TARGET_FILE_DIR:dialog>
50 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
51 ENDIF()
52
53 ADD_CUSTOM_TARGET(maodbcpkg
54 COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/build_package.sh ${PRODUCT_IDENTIFIER} ${PRODUCT_VERSION} ${PKG_PACKAGE}
55 DEPENDS copypkgfiles ${CMAKE_CURRENT_BINARY_DIR}/scripts/postinstall distribution.plist README.html WELCOME.html LICENSE.html
56 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
57
58 SET_TARGET_PROPERTIES(maodbcpkg PROPERTIES EXCLUDE_FROM_ALL OFF)
59
60 ADD_DEPENDENCIES(maodbcpkg copypkgfiles)
61 ADD_DEPENDENCIES(copypkgfiles maodbc)
62 IF(NOT USE_SYSTEM_INSTALLED_LIB)
63 ADD_DEPENDENCIES(copypkgfiles maodbc dialog caching_sha2_password auth_gssapi_client sha256_password mysql_clear_password)
64 ENDIF()
65
0 <html>
1 <head>
2 <style>
3 body {
4 font-family: -apple-system, BlinkMacSystemFont, sans-serif;
5 }
6 </style>
7 <title>MariaDB Connector/ODBC license</title>
8 </head>
9 <body>
10 <pre>
11 GNU LESSER GENERAL PUBLIC LICENSE
12 Version 2.1, February 1999
13
14 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
15 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 Everyone is permitted to copy and distribute verbatim copies
17 of this license document, but changing it is not allowed.
18
19 [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.]
20
21 Preamble
22
23 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.
24
25 This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
26
27 When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
28
29 To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
30 For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
31
32 We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
33
34 Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.
35
36 Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
37
38 When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
39
40 We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
41
42 For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
43
44 In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
45
46 Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
47
48 The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.
49
50
51 GNU LESSER GENERAL PUBLIC LICENSE
52 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
53
54 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
55
56 A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
57
58 The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)
59
60 "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
61
62 Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
63
64 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
65
66 You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
67
68
69 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
70
71 a) The modified work must itself be a software library.
72
73 b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
74
75 c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
76
77 d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
78
79 (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
80
81 These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
82
83 Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
84
85 In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
86
87 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in
88 these notices.
89
90 Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
91
92 This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
93
94 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
95
96 If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.
97
98 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.
99
100 However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
101
102 When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.
103
104 If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
105
106 Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
107
108 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.
109
110 You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
111
112 a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)
113
114 b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.
115
116 c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.
117
118 d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
119
120 e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.
121
122 For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.
123
124 It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.
125
126 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
127
128 a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.
129
130 b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.
131
132 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
133
134 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
135
136 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
137
138 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
139
140 If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
141
142 It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.
143
144 This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
145
146 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.
147
148 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
149
150 Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.
151
152 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.
153
154 NO WARRANTY
155
156 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
157
158 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
159 DAMAGES.
160
161 END OF TERMS AND CONDITIONS
162
163 How to Apply These Terms to Your New Libraries
164
165 If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
166
167 To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
168
169 <one line to give the library's name and a brief idea of what it does.> Copyright (C) <year> <name of author>
170
171 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
172
173 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
174
175 You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
176 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
177
178 Also add information on how to contact you by electronic and paper mail.
179
180 You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if
181 necessary. Here is a sample; alter the names:
182
183 Yoyodyne, Inc., hereby disclaims all copyright interest in the
184 library `Frob' (a library for tweaking knobs) written by James Random Hacker.
185
186 <signature of Ty Coon>, 1 April 1990
187 Ty Coon, President of Vice
188
189 That's all there is to it!
190
191
192 </pre>
193 </body>
194 </html>
0 <html>
1 <head>
2 <style>
3 body {
4 font-family: -apple-system, BlinkMacSystemFont, sans-serif;
5 }
6 </style>
7 <title>Readme for MariaDB Connector/ODBC</title>
8 </head>
9 <body>
10 <p>MariaDB Connector/ODBC files will be installed in /Library/MariaDB/MariaDB-Connector-ODBC.</p>
11 <p>The connector requires the libraries for OpenSSL and iODBC to be installed. With homebrew they are easy to install:</p>
12 <ul>
13 <li>brew install openssl</li>
14 <li>brew install libiodbc</li>
15 </ul>
16 </body>
17 </html>
0 <html>
1 <head>
2 <style>
3 body {
4 font-family: -apple-system, BlinkMacSystemFont, sans-serif;
5 }
6 </style>
7 <title>Welcome to MariaDB Connector/ODBC Installer</title>
8 </head>
9 <body>
10 <p>This is going to install MariaDB Connector/ODBC(Unicode) @PRODUCT_ARCH_BITS@bit version @PRODUCT_VERSION@ - a database driver that uses the industry standard Open Database Connectivity (ODBC) API.</p>
11 </body>
12 </html>
0 #!/bin/bash
1 # ************************************************************************************
2 # Copyright (C) 2019 MariaDB Corporation AB
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Library General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Library General Public License for more details.
13 #
14 # You should have received a copy of the GNU Library General Public
15 # License along with this library; if not see <http://www.gnu.org/licenses>
16 # or write to the Free Software Foundation, Inc.,
17 # 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
18 # *************************************************************************************/
19
20 pkgbuild --root ROOT --scripts scripts --identifier $1 --version $2 libmaodbc.pkg
21 productbuild --distribution distribution.plist --resources . --package-path libmaodbc.pkg $3
0 #!/bin/bash
1 # ************************************************************************************
2 # Copyright (C) 2019 MariaDB Corporation AB
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Library General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Library General Public License for more details.
13 #
14 # You should have received a copy of the GNU Library General Public
15 # License along with this library; if not see <http://www.gnu.org/licenses>
16 # or write to the Free Software Foundation, Inc.,
17 # 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
18 # *************************************************************************************/
19
20 LibPath="Library/MariaDB/MariaDB-Connector-ODBC"
21
22 rm -rf ./ROOT
23
24 mkdir -p ./ROOT/${LibPath}/bin
25 cp $1/libmaodbc.dylib ./ROOT/${LibPath}/
26 cp ./install_driver ./ROOT/${LibPath}/bin
27
28 if [ $2 ]; then
29 mkdir ./ROOT/${LibPath}/plugin
30 cp $2/dialog.so ./ROOT/${LibPath}/plugin/
31 cp $2/auth_gssapi_client.so ./ROOT/${LibPath}/plugin/
32 cp $2/caching_sha2_password.so ./ROOT/${LibPath}/plugin/
33 cp $2/mysql_clear_password.so ./ROOT/${LibPath}/plugin/
34 cp $2/sha256_password.so ./ROOT/${LibPath}/plugin/
35 fi
36
0 <?xml version="1.0" encoding="utf-8"?>
1 <installer-gui-script minSpecVersion="1">
2 <title>MariaDB Connector/ODBC</title>
3 <welcome file="WELCOME.html" />
4 <license file="LICENSE.html" />
5 <readme file="README.html" />
6 <pkg-ref id="com.mariadb.connector.odbc"/>
7 <options customize="never" require-scripts="false"/>
8 <choices-outline>
9 <line choice="default">
10 <line choice="com.mariadb.connector.odbc"/>
11 </line>
12 </choices-outline>
13 <choice id="default"/>
14 <choice id="com.mariadb.connector.odbc" visible="false">
15 <pkg-ref id="com.mariadb.connector.odbc"/>
16 </choice>
17 <pkg-ref id="com.mariadb.connector.odbc" version="3.1.0" onConclusion="none">libmaodbc.pkg</pkg-ref>
18 </installer-gui-script>
0 /************************************************************************************
1 Copyright (C) 2019 MariaDB Corporation AB
2
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public
5 License as published by the Free Software Foundation; either
6 version 2.1 of the License, or (at your option) any later version.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public
14 License along with this library; if not see <http://www.gnu.org/licenses>
15 or write to the Free Software Foundation, Inc.,
16 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
17 *************************************************************************************/
18
19 #define SQL_NOUNICODEMAP
20 #include <odbcinst.h>
21 #include <stdio.h>
22 #include <string.h>
23
24 #ifdef _WIN32
25 # include <windows.h>
26 # include <Shlwapi.h>
27 #else
28
29 int _snprintf(char *buffer, size_t count, const char *format, ...)
30 {
31 va_list list;
32 va_start(list, format);
33 int result= vsnprintf(buffer, count, format, list);
34
35 va_end(list);
36
37 /* _snprintf returns negative number if buffer is not big enough */
38 if (result > count)
39 {
40 return count - result - 1;
41 }
42 return result;
43 }
44 #endif
45
46
47 int Usage()
48 {
49 printf("Usage: install_driver <driver_location> [<driver_name>]\n");
50 return 1;
51 }
52
53
54 int main(int argc, char** argv)
55 {
56 unsigned int UsageCount, ErrorCode;
57 char DriverDescr[1024], ErrorText[128], OutLocation[512], DriverDir[512];
58 const char *DriverLocation, *DriverName, *DriverFileName, *DriverDescription= "MariaDB Connector/ODBC";
59
60 if (argc < 2 || strcmp(argv[1], "--help") == 0)
61 {
62 return Usage();
63 }
64
65 DriverLocation= argv[1];
66
67 #ifdef _WIN32
68 strcpy(DriverDir, DriverLocation);
69 PathRemoveFileSpec(DriverDir);
70 #else
71 {
72 char *SlashLocation= strrchr(DriverLocation, '/');
73 if (SlashLocation != NULL)
74 {
75 strncpy(DriverDir, DriverLocation, SlashLocation - DriverLocation);
76 DriverDir[SlashLocation - DriverLocation]= '\0';
77 }
78 else
79 {
80 strcpy(DriverDir, ".");
81 }
82 }
83 #endif
84
85 if (argc > 2)
86 {
87 DriverName= argv[2];
88 }
89 else
90 {
91 DriverName= DriverLocation;
92 }
93
94 if (argc > 3)
95 {
96 DriverDescription= argv[3];
97 }
98
99 if (strlen(DriverLocation) > strlen(DriverDir))
100 {
101 DriverFileName= DriverLocation + strlen(DriverDir) + 1;
102 }
103 else
104 {
105 DriverFileName= DriverName;
106 }
107
108 /* Our setup library does not have ConfigDriver. Thus there is no sense */
109 /*SQLConfigDriver(NULL, ODBC_REMOVE_DRIVER, DriverName, NULL, NULL, 0, NULL);*/
110 SQLRemoveDriver(DriverName, FALSE, &UsageCount);
111 printf("Installing driver %s in %s as %s\n", DriverFileName, DriverDir, DriverName);
112 _snprintf(DriverDescr, sizeof(DriverDescr), "%s%cDriver=%s%cDescription=%s%cThreading=0%c", DriverName, '\0', DriverLocation, '\0', DriverDescription, '\0', '\0');
113
114
115 if (SQLInstallDriverEx(DriverDescr, DriverDir, OutLocation, sizeof(OutLocation), NULL, ODBC_INSTALL_COMPLETE, NULL) == FALSE)
116 {
117 SQLInstallerError(1, &ErrorCode, ErrorText, (unsigned short)sizeof(ErrorText), NULL);
118 printf("An error occured while registering driver: [%u] %s\n", ErrorCode, ErrorText);
119
120 return 1;
121 }
122
123 return 0;
124 }
0 #!/bin/bash
1 # ************************************************************************************
2 # Copyright (C) 2019 MariaDB Corporation AB
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Library General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # Library General Public License for more details.
13 #
14 # You should have received a copy of the GNU Library General Public
15 # License along with this library; if not see <http://www.gnu.org/licenses>
16 # or write to the Free Software Foundation, Inc.,
17 # 51 Franklin St., Fifth Floor, Boston, MA 02110, USA
18 # *************************************************************************************/
19
20 touch /tmp/maodbc_postinstall.log
21
22 echo "Registering MariaDB ODBC driver" > /tmp/maodbc_postinstall.log
23
24 if [ $2 ]; then
25 target=$2
26 case "$target" in
27 */)
28 ;;
29 *)
30 target="${target}/"
31 ;;
32 esac
33 echo "Driver installation target - $target" >> /tmp/maodbc_postinstall.log
34 fi
35
36 set -a
37 ODBCINSTINI="${target}Library/ODBC/odbcinst.ini"
38 instinidir="$(dirname -- "$ODBCINSTINI")"
39
40 echo "Using $ODBCINSTINI, dirname - ${instinidir}" >> /tmp/maodbc_postinstall.log
41
42 if [ ! -f $ODBCINSTINI ] ; then
43 echo "$ODBCINSTINI does not exist" >> /tmp/maodbc_postinstall.log
44 mkdir -p "$instinidir" && touch "$ODBCINSTINI"
45
46 if [ ! -f $ODBCINSTINI ] ; then
47 echo "$ODBCINSTINI still does not exist" >> /tmp/maodbc_postinstall.log
48 echo "$ODBCINSTINI still does not exist"
49 # mkdir -p "$instinidir"
50 # touch "$ODBCINSTINI"
51 exit 1
52 fi
53 chmod 664 $ODBCINSTINI
54
55 if [ ! -f ${target}Library/ODBC/odbc.ini ] ; then
56 echo "${target}Library/ODBC/odbc.ini does not exist - creating it" >> /tmp/maodbc_postinstall.log
57 touch "${target}Library/ODBC/odbc.ini"
58 chgrp admin ${target}Library/ODBC/odbc.ini
59 chmod 664 ${target}Library/ODBC/odbc.ini
60 echo "[ODBC Data Sources]" > ${target}Library/ODBC/odbc.ini
61 fi
62
63 echo "Writing common options and driver entry" >> /tmp/maodbc_postinstall.log
64 echo "[ODBC]" > $ODBCINSTINI
65 echo "Trace = no" >> $ODBCINSTINI
66 echo "TraceFile = /tmp/iodbc_trace.log" >> $ODBCINSTINI
67 echo "" >> $ODBCINSTINI
68 echo "[ODBC Drivers]" >> $ODBCINSTINI
69 echo "MariaDB ODBC @PRODUCT_SERIES@ Unicode Driver = Installed" >> $ODBCINSTINI
70 echo "" >> $ODBCINSTINI
71 echo "[MariaDB ODBC @PRODUCT_SERIES@ Unicode Driver]" >> $ODBCINSTINI
72 echo "Driver = ${target}Library/MariaDB/MariaDB-Connector-ODBC/libmaodbc.dylib" >> $ODBCINSTINI
73 echo "Description = MariaDB Connector/ODBC(Unicode) @PRODUCT_VERSION@ @PRODUCT_ARCH_BITS@bit" >> $ODBCINSTINI
74 echo "Threading = 0" >> $ODBCINSTINI
75 echo "" >> $ODBCINSTINI
76 echo "Registration has been successfully finished" >> /tmp/maodbc_postinstall.log
77
78 exit 0
79 fi
80
81 ${target}Library/MariaDB/MariaDB-Connector-ODBC/bin/install_driver "${target}Library/MariaDB/MariaDB-Connector-ODBC/libmaodbc.dylib" "MariaDB ODBC @PRODUCT_SERIES@ Unicode Driver" "MariaDB Connector/ODBC(Unicode) @PRODUCT_VERSION@ @PRODUCT_ARCH_BITS@bit" >> /tmp/maodbc_postinstall.log
82
83 echo "Registration has been successfully finished" >> /tmp/maodbc_postinstall.log
84
85 exit 0
0 //{{NO_DEPENDENCIES}}
1 // Microsoft Visual C++ generated include file.
2 // Used by maodbca.rc
3
4 // Nächste Standardwerte für neue Objekte
5 //
6 #ifdef APSTUDIO_INVOKED
7 #ifndef APSTUDIO_READONLY_SYMBOLS
8 #define _APS_NEXT_RESOURCE_VALUE 101
9 #define _APS_NEXT_COMMAND_VALUE 40001
10 #define _APS_NEXT_CONTROL_VALUE 1001
11 #define _APS_NEXT_SYMED_VALUE 101
12 #endif
13 #endif
0 SET(ODBC_SOURCE_WIX_DIR ${CMAKE_SOURCE_DIR}/wininstall)
1
2 # Get revision number
3 IF(WITH_REVNO)
4 EXECUTE_PROCESS(COMMAND git log HEAD^^..HEAD
5 COMMAND FINDSTR commit
6 OUTPUT_VARIABLE revno)
7 STRING(REPLACE "commit " "" revno ${revno})
8 STRING(REPLACE "\n" "" revno ${revno})
9 ENDIF()
10
11 IF(NOT WIX_DIR)
12 SET(WIX_DIR "$ENV{WIX}/bin/")
13 MESSAGE(STATUS "WiX directory: ${WIX_DIR}")
14 ENDIF()
15 SET(PRODUCT_NAME "MariaDB ODBC Driver")
16 SET(PRODUCT_MANUFACTURER "MariaDB")
17 SET(PRODUCT_VERSION "${MARIADB_ODBC_VERSION_MAJOR}.${MARIADB_ODBC_VERSION_MINOR}.${MARIADB_ODBC_VERSION_PATCH}")
18
19 IF(WITH_SIGNCODE)
20 ENDIF()
21
22 IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
23 SET(PRODUCT_NAME "${PRODUCT_NAME} 64-bit")
24 SET(PLATFORM "win64")
25 SET(IS_WIN64 "yes")
26 SET(WIXPLATFORM "x64")
27 SET(FOLDER "ProgramFiles64Folder")
28 SET(GUID_REGISTRY "E35BF41F-89A1-4691-8F62-09922C04C13B")
29 SET(GUID_SETUP "BF255F46-18CA-4244-9A17-6B33BDAAFBF4")
30 SET(GUID_DRIVER "3535FD95-1F44-454E-A6E4-81F865E8C57F")
31 SET(GUID_DEBUG "4FA6E79A-4630-4CB8-A4E1-00A4740E9280")
32 SET(GUID_PLUGINS "9D1B41AA-CE86-4c6d-93C8-FDCD40D5D2E9")
33 SET(GUID_PLUGINS_DEBUG "63541EC9-9C2B-4763-8C18-03313DAE6F8E")
34 ELSE()
35 SET(PLATFORM "win32")
36 SET(IS_WIN64 "no")
37 SET(WIXPLATFORM "x86")
38 SET(FOLDER "ProgramFilesFolder")
39 SET(GUID_REGISTRY "ACFC9B33-5D1F-4EA2-A4DB-1E37A2BAF86B")
40 SET(GUID_SETUP "16E13D0B-7BFE-4BC4-A524-940716EE749F")
41 SET(GUID_DRIVER "8BD16D93-30E0-4DF0-8B40-9A5A3D967DD6")
42 SET(GUID_DEBUG "2EA8B4DD-F470-4362-8D87-59090D255981")
43 SET(GUID_PLUGINS "B6355F5E-FA0B-427a-AC77-BC145887D11B")
44 SET(GUID_PLUGINS_DEBUG "B2CB2291-249C-4258-83CB-A3E9C4DC9CFE")
45 ENDIF()
46 CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/wininstall/mariadb_odbc.xml.in
47 ${CMAKE_BINARY_DIR}/wininstall/mariadb_odbc.xml)
48 IF(${revno})
49 SET(MSI_PACKAGE "mariadb-connector-odbc-${PRODUCT_VERSION}-r${revno}-${PLATFORM}.msi")
50 ELSE()
51 SET(MSI_PACKAGE "mariadb-connector-odbc-${PRODUCT_VERSION}-${PLATFORM}.msi")
52 ENDIF()
53
54 SET(ENV{MARIADB_ODBC_MSI_PACKAGE} "${MSI_PACKAGE}" PARENT_SCOPE)
55
56 IF(WITH_SIGNCODE)
57 IF(EXISTS "/tools/sign.bat")
58 ADD_CUSTOM_TARGET(SIGNMSI
59 DEPENDS ${MSI_PACKAGE}
60 COMMAND /tools/sign.bat ${MSI_PACKAGE})
61 ELSE()
62 ADD_CUSTOM_TARGET(SIGNMSI
63 DEPENDS ${MSI_PACKAGE}
64 COMMAND signtool sign ${SIGN_OPTIONS} ${MSI_PACKAGE})
65 ENDIF()
66 ADD_DEPENDENCIES(SIGNMSI ${MSI_PACKAGE})
67 SET_TARGET_PROPERTIES(SIGNMSI PROPERTIES EXCLUDE_FROM_ALL OFF)
68 ENDIF()
69
70 MESSAGE(STATUS "MSI package name ${MSI_PACKAGE}")
71
72 ADD_CUSTOM_TARGET(
73 ${MSI_PACKAGE}
74 COMMAND ${WIX_DIR}light.exe -ext WixUIExtension mariadb_odbc.wixobj -o ${MSI_PACKAGE})
75
76 SET_TARGET_PROPERTIES(${MSI_PACKAGE} PROPERTIES EXCLUDE_FROM_ALL OFF)
77
78 ADD_CUSTOM_TARGET(
79 ODBC_WIX
80 DEPENDS mariadb_odbc.xml
81 COMMAND ${WIX_DIR}candle.exe mariadb_odbc.xml -o mariadb_odbc.wixobj)
82
83 ADD_DEPENDENCIES(${MSI_PACKAGE} ODBC_WIX)
84 ADD_DEPENDENCIES(ODBC_WIX maodbc maodbcs)
85 IF(NOT USE_SYSTEM_INSTALLED_LIB)
86 ADD_DEPENDENCIES(ODBC_WIX maodbc maodbcs dialog caching_sha2_password auth_gssapi_client sha256_password mysql_clear_password)
87 ENDIF()
88
0 <Include>
1 <?define binaries_dir="@DRIVER_LIB_DIR@" ?>
2 <?define plugins_source_dir="@PLUGINS_LIB_DIR@" ?>
3 <?define plugins_subdir_name="@PLUGINS_SUBDIR_NAME@" ?>
4 </Include>
0 {\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff31507\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi31507\deflang1031\deflangfe1031\themelang1031\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f2\fbidi \fmodern\fcharset0\fprq1{\*\panose 02070309020205020404}Courier New;}
1 {\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\f37\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
2 {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria;}
3 {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}
4 {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;}
5 {\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f322\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f323\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
6 {\f325\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f326\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f327\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f328\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
7 {\f329\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f330\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f342\fbidi \fmodern\fcharset238\fprq1 Courier New CE;}{\f343\fbidi \fmodern\fcharset204\fprq1 Courier New Cyr;}
8 {\f345\fbidi \fmodern\fcharset161\fprq1 Courier New Greek;}{\f346\fbidi \fmodern\fcharset162\fprq1 Courier New Tur;}{\f347\fbidi \fmodern\fcharset177\fprq1 Courier New (Hebrew);}{\f348\fbidi \fmodern\fcharset178\fprq1 Courier New (Arabic);}
9 {\f349\fbidi \fmodern\fcharset186\fprq1 Courier New Baltic;}{\f350\fbidi \fmodern\fcharset163\fprq1 Courier New (Vietnamese);}{\f662\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f663\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;}
10 {\f665\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f666\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f669\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f670\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);}
11 {\f692\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\f693\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\f695\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\f696\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
12 {\f699\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\f700\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
13 {\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
14 {\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
15 {\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
16 {\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
17 {\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
18 {\fhimajor\f31528\fbidi \froman\fcharset238\fprq2 Cambria CE;}{\fhimajor\f31529\fbidi \froman\fcharset204\fprq2 Cambria Cyr;}{\fhimajor\f31531\fbidi \froman\fcharset161\fprq2 Cambria Greek;}{\fhimajor\f31532\fbidi \froman\fcharset162\fprq2 Cambria Tur;}
19 {\fhimajor\f31535\fbidi \froman\fcharset186\fprq2 Cambria Baltic;}{\fhimajor\f31536\fbidi \froman\fcharset163\fprq2 Cambria (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
20 {\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
21 {\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
22 {\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}
23 {\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}
24 {\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}
25 {\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}
26 {\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}
27 {\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}
28 {\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;}{\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}
29 {\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;}{\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}
30 {\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}
31 {\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}
32 {\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
33 \red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp
34 \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa200\sl276\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\stylesheet{\ql \li0\ri0\sa200\sl276\slmult1
35 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 \snext0 \sqformat \spriority0 Normal;}
36 {\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\*
37 \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa200\sl276\slmult1
38 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 \snext11 \ssemihidden \sunhideused
39 Normal Table;}{\s15\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031
40 \snext15 \sqformat \spriority1 \styrsid7013135 No Spacing;}}{\*\rsidtbl \rsid1254708\rsid7013135}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator Windows User}
41 {\creatim\yr2013\mo10\dy26\hr9\min47}{\revtim\yr2013\mo10\dy26\hr9\min55}{\version2}{\edmins0}{\nofpages9}{\nofwords3590}{\nofchars22619}{\nofcharsws26157}{\vern49167}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}
42 \paperw12240\paperh15840\margl1417\margr1417\margt1417\margb1134\gutter0\ltrsect
43 \widowctrl\ftnbj\aenddoc\hyphhotz425\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120
44 \dghorigin1701\dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot7013135 \fet0{\*\wgrffmtfilter 2450}\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}
45 {\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}
46 {\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9
47 \pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0
48 \fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af2\afs28 \ltrch\fcs0 \b\fs28\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
49 GNU LESSER GENERAL PUBLIC LICENSE
50 \par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 Version 2.1, February 1999
51 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
52 \par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
53 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
54 \par \hich\af31506\dbch\af31505\loch\f31506 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
55 \par \hich\af31506\dbch\af31505\loch\f31506 Everyone is permitted to copy and distribute verbatim copies
56 \par \hich\af31506\dbch\af31505\loch\f31506 of this license document, but changing it is not allowed.
57 \par
58 \par \hich\af31506\dbch\af31505\loch\f31506 [This is the first released version of the Lesser GPL. \hich\af31506\dbch\af31505\loch\f31506 It also counts as the successor of the GNU Library Public License, version 2, \hich\af31506\dbch\af31505\loch\f31506
59 hence the version number 2.1.]
60 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
61 \par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \b\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 Preamble
62 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
63 \par }\pard\plain \ltrpar\s15\ql \li0\ri0\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid7013135 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0
64 \fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af31507 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
65 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to sh\hich\af31506\dbch\af31505\loch\f31506
66 are and change free software--to make sure the software is free for all its users.
67 \par }\pard\plain \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af31507\afs22\alang1025 \ltrch\fcs0 \fs22\lang1031\langfe1031\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1031\langfenp1031 {\rtlch\fcs1 \af2 \ltrch\fcs0
68 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
69 \par \hich\af31506\dbch\af31505\loch\f31506 This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other au\hich\af31506\dbch\af31505\loch\f31506
70 thors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
71 \par
72 \par \hich\af31506\dbch\af31505\loch\f31506 When we sp\hich\af31506\dbch\af31505\loch\f31506
73 eak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source
74 \hich\af31506\dbch\af31505\loch\f31506 c\hich\af31506\dbch\af31505\loch\f31506 ode or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.
75 \par
76 \par \hich\af31506\dbch\af31505\loch\f31506 To protect your rights, we need to make restrictions that forbid distributors to deny y\hich\af31506\dbch\af31505\loch\f31506
77 ou these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
78 \par \hich\af31506\dbch\af31505\loch\f31506 For example, if you distribute copies of the library, whether gratis\hich\af31506\dbch\af31505\loch\f31506
79 or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so tha
80 \hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.
81 \par
82 \par \hich\af31506\dbch\af31505\loch\f31506 We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer y\hich\af31506\dbch\af31505\loch\f31506
83 ou this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else
84 \hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506
85 nd passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.
86 \par
87 \par \hich\af31506\dbch\af31505\loch\f31506 Finally, software patents pose a constant threat to t\hich\af31506\dbch\af31505\loch\f31506
88 he existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of
89 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 the library must be consistent with the full freedom of use specified in this license.
90 \par
91 \par \hich\af31506\dbch\af31505\loch\f31506 Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to c\hich\af31506\dbch\af31505\loch\f31506
92 ertain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.
93 \par
94 \par \hich\af31506\dbch\af31505\loch\f31506 When a program is linked with a library, whether \hich\af31506\dbch\af31505\loch\f31506
95 statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteri
96 \hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506 of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.
97 \par
98 \par \hich\af31506\dbch\af31505\loch\f31506
99 We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs.
100 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506
101 These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.
102 \par
103 \par \hich\af31506\dbch\af31505\loch\f31506 For example, on rare occasions, there may be a special need to encourag\hich\af31506\dbch\af31505\loch\f31506
104 e the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free librarie
105 \hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 . In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
106 \par
107 \par \hich\af31506\dbch\af31505\loch\f31506 In other cases, permission to use a particular library in non-free programs enables a greater number of people to u\hich\af31506\dbch\af31505\loch\f31506
108 se a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.
109 \par
110 \par \hich\af31506\dbch\af31505\loch\f31506 Although the Lesser General \hich\af31506\dbch\af31505\loch\f31506
111 Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
112 \par
113 \par \hich\af31506\dbch\af31505\loch\f31506 The precise terms and con\hich\af31506\dbch\af31505\loch\f31506
114 ditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be comb
115 \hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 ned with the library in order to run.
116 \par \page
117 \par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2\afs24 \ltrch\fcs0 \b\fs24\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
118 GNU LESSER GENERAL PUBLIC LICENSE
119 \par \hich\af31506\dbch\af31505\loch\f31506 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
120 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
121 \par \hich\af31506\dbch\af31505\loch\f31506 0. This License Agreement applies to any software library or other program which contains a no\hich\af31506\dbch\af31505\loch\f31506
122 tice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".
123 \par
124 \par \hich\af31506\dbch\af31505\loch\f31506 A "library" means a collection of softwa\hich\af31506\dbch\af31505\loch\f31506
125 re functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.
126 \par
127 \par \hich\af31506\dbch\af31505\loch\f31506 The "Library", below, refers to any such software library or work which has been distributed un\hich\af31506\dbch\af31505\loch\f31506
128 der these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardl
129 \hich\af31506\dbch\af31505\loch\f31506 y\hich\af31506\dbch\af31505\loch\f31506 into another language. (Hereinafter, translation is included without limitation in the term "modification".)
130 \par
131 \par \hich\af31506\dbch\af31505\loch\f31506 "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all t\hich\af31506\dbch\af31505\loch\f31506
132 he source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.
133 \par
134 \par \hich\af31506\dbch\af31505\loch\f31506 Activities other than copying, distribution and modification are not covered by thi\hich\af31506\dbch\af31505\loch\f31506
135 s License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a too
136 \hich\af31506\dbch\af31505\loch\f31506 l\hich\af31506\dbch\af31505\loch\f31506 for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.
137 \par
138 \par \hich\af31506\dbch\af31505\loch\f31506 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided tha\hich\af31506\dbch\af31505\loch\f31506
139 t you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along w
140 \hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 th the Library.
141 \par
142 \par \hich\af31506\dbch\af31505\loch\f31506 You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
143 \par \page
144 \par \hich\af31506\dbch\af31505\loch\f31506 2. You may modify your copy or copies of the Library or any portion of it, thus forming a w\hich\af31506\dbch\af31505\loch\f31506
145 ork based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
146 \par
147 \par \hich\af31506\dbch\af31505\loch\f31506 a) The modified work must itself be a software library.
148 \par
149 \par \hich\af31506\dbch\af31505\loch\f31506 b) You mus\hich\af31506\dbch\af31505\loch\f31506 t cause the files modified to carry prominent notices stating that you changed the files and the date of any change.
150 \par
151 \par \hich\af31506\dbch\af31505\loch\f31506 c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.
152 \par
153 \par \hich\af31506\dbch\af31505\loch\f31506 d) If a\hich\af31506\dbch\af31505\loch\f31506
154 facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that
155 ,\hich\af31506\dbch\af31505\loch\f31506 in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.
156 \par
157 \par \hich\af31506\dbch\af31505\loch\f31506 (For example, a function in a library to compute square roots has a purpose that is entirel\hich\af31506\dbch\af31505\loch\f31506
158 y well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute sq
159 \hich\af31506\dbch\af31505\loch\f31506 u\hich\af31506\dbch\af31505\loch\f31506 are roots.)
160 \par
161 \par \hich\af31506\dbch\af31505\loch\f31506
162 These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms,
163 \hich\af31506\dbch\af31505\loch\f31506
164 do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permi
165 \hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 sions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
166 \par
167 \par \hich\af31506\dbch\af31505\loch\f31506 Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to e\hich\af31506\dbch\af31505\loch\f31506
168 xercise the right to control the distribution of derivative or collective works based on the Library.
169 \par
170 \par \hich\af31506\dbch\af31505\loch\f31506 In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or\hich\af31506\dbch\af31505\loch\f31506
171 distribution medium does not bring the other work under the scope of this License.
172 \par
173 \par \hich\af31506\dbch\af31505\loch\f31506 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the \hich\af31506\dbch\af31505\loch\f31506
174 notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify tha
175 \hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 version instead if you wish.) Do not make any other change in
176 \par \hich\af31506\dbch\af31505\loch\f31506 these notices.
177 \par
178 \par \hich\af31506\dbch\af31505\loch\f31506 Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works m\hich\af31506\dbch\af31505\loch\f31506
179 ade from that copy.
180 \par
181 \par \hich\af31506\dbch\af31505\loch\f31506 This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
182 \par
183 \par \hich\af31506\dbch\af31505\loch\f31506 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or exe\hich\af31506\dbch\af31505\loch\f31506
184 cutable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for softwa
185 \hich\af31506\dbch\af31505\loch\f31506 r\hich\af31506\dbch\af31505\loch\f31506 e interchange.
186 \par
187 \par \hich\af31506\dbch\af31505\loch\f31506
188 If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though th
189 \hich\af31506\dbch\af31505\loch\f31506 ird parties are not compelled to copy the source along with the object code.
190 \par
191 \par \hich\af31506\dbch\af31505\loch\f31506
192 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the L
193 \hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 brary, and therefore falls outside the scope of this License.
194 \par
195 \par \hich\af31506\dbch\af31505\loch\f31506 However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work t
196 \hich\af31506\dbch\af31505\loch\f31506 hat uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.
197 \par
198 \par \hich\af31506\dbch\af31505\loch\f31506 When a "work that uses the Library" uses material from a header file that is part of the Library, the object code \hich\af31506\dbch\af31505\loch\f31506
199 for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true
200 \hich\af31506\dbch\af31505\loch\f31506 i\hich\af31506\dbch\af31505\loch\f31506 s not precisely defined by law.
201 \par
202 \par \hich\af31506\dbch\af31505\loch\f31506
203 If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, rega
204 \hich\af31506\dbch\af31505\loch\f31506 rdless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)
205 \par
206 \par \hich\af31506\dbch\af31505\loch\f31506 Otherwise, if the work is a derivative of the Library, you may distribute the object code for the\hich\af31506\dbch\af31505\loch\f31506
207 work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.
208 \par
209 \par \hich\af31506\dbch\af31505\loch\f31506 6. As an exception to the Sections above, you may also combine or link a "work that use\hich\af31506\dbch\af31505\loch\f31506
210 s the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debug
211 \hich\af31506\dbch\af31505\loch\f31506 g\hich\af31506\dbch\af31505\loch\f31506 ing such modifications.
212 \par
213 \par \hich\af31506\dbch\af31505\loch\f31506
214 You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution display
215 \hich\af31506\dbch\af31505\loch\f31506 s copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:
216 \par
217 \par \hich\af31506\dbch\af31505\loch\f31506 a) Accompany the work with the complete corresponding\hich\af31506\dbch\af31505\loch\f31506
218 machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work th
219 \hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506
220 t uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions file
221 \hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 in the Library will not necessarily be able to recompile the application to use the modified definitions.)
222 \par
223 \par \hich\af31506\dbch\af31505\loch\f31506 b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the l\hich\af31506\dbch\af31505\loch\f31506
224 ibrary already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-c
225 \hich\af31506\dbch\af31505\loch\f31506 o\hich\af31506\dbch\af31505\loch\f31506 mpatible with the version that the work was made with.
226 \par
227 \par \hich\af31506\dbch\af31505\loch\f31506 c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing
228 \hich\af31506\dbch\af31505\loch\f31506 this distribution.
229 \par
230 \par \hich\af31506\dbch\af31505\loch\f31506 d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.
231 \par
232 \par \hich\af31506\dbch\af31505\loch\f31506 e) Verify that the user has already received a copy o\hich\af31506\dbch\af31505\loch\f31506 f these materials or that you have already sent this user a copy.
233 \par
234 \par \hich\af31506\dbch\af31505\loch\f31506 For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special e
235 \hich\af31506\dbch\af31505\loch\f31506
236 xception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that co
237 \hich\af31506\dbch\af31505\loch\f31506 m\hich\af31506\dbch\af31505\loch\f31506 ponent itself accompanies the executable.
238 \par
239 \par \hich\af31506\dbch\af31505\loch\f31506 It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them a
240 \hich\af31506\dbch\af31505\loch\f31506 nd the Library together in an executable that you distribute.
241 \par
242 \par \hich\af31506\dbch\af31505\loch\f31506
243 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution
244 \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:
245 \par
246 \par \hich\af31506\dbch\af31505\loch\f31506 a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other libr\hich\af31506\dbch\af31505\loch\f31506
247 ary facilities. This must be distributed under the terms of the Sections above.
248 \par
249 \par \hich\af31506\dbch\af31505\loch\f31506 b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined fo\hich\af31506\dbch\af31505\loch\f31506
250 rm of the same work.
251 \par
252 \par \hich\af31506\dbch\af31505\loch\f31506
253 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and wil
254 \hich\af31506\dbch\af31505\loch\f31506
255 l automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.
256 \par
257 \par \hich\af31506\dbch\af31505\loch\f31506 9. You are not requir\hich\af31506\dbch\af31505\loch\f31506
258 ed to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modif
259 \hich\af31506\dbch\af31505\loch\f31506 y\hich\af31506\dbch\af31505\loch\f31506
260 ing or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.
261 \par
262 \par \hich\af31506\dbch\af31505\loch\f31506 10. Each time you redist\hich\af31506\dbch\af31505\loch\f31506
263 ribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further re
264 \hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 trictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.
265 \par
266 \par \hich\af31506\dbch\af31505\loch\f31506 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other \hich\af31506\dbch\af31505\loch\f31506
267 reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so
268 \hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506
269 s to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Lib
270 \hich\af31506\dbch\af31505\loch\f31506 r\hich\af31506\dbch\af31505\loch\f31506
271 ary by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.
272 \par
273 \par \hich\af31506\dbch\af31505\loch\f31506 If any portion of this section is held invalid or unenforce\hich\af31506\dbch\af31505\loch\f31506
274 able under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.
275 \par
276 \par \hich\af31506\dbch\af31505\loch\f31506 It is not the purpose of this section to induce you to infringe any patents or other property \hich\af31506\dbch\af31505\loch\f31506
277 right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions
278 \hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506
279 o the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose
280 \hich\af31506\dbch\af31505\loch\f31506 t\hich\af31506\dbch\af31505\loch\f31506 hat choice.
281 \par
282 \par \hich\af31506\dbch\af31505\loch\f31506 This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
283 \par
284 \par \hich\af31506\dbch\af31505\loch\f31506 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted int\hich\af31506\dbch\af31505\loch\f31506
285 erfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such c
286 \hich\af31506\dbch\af31505\loch\f31506 a\hich\af31506\dbch\af31505\loch\f31506 se, this License incorporates the limitation as if written in the body of this License.
287 \par
288 \par \hich\af31506\dbch\af31505\loch\f31506 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar i\hich\af31506\dbch\af31505\loch\f31506
289 n spirit to the present version, but may differ in detail to address new problems or concerns.
290 \par
291 \par \hich\af31506\dbch\af31505\loch\f31506 Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", y\hich\af31506\dbch\af31505\loch\f31506
292 ou have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the
293 \hich\af31506\dbch\af31505\loch\f31506 F\hich\af31506\dbch\af31505\loch\f31506 ree Software Foundation.
294 \par
295 \par \hich\af31506\dbch\af31505\loch\f31506
296 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free So
297 \hich\af31506\dbch\af31505\loch\f31506
298 ftware Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of
299 \hich\af31506\dbch\af31505\loch\f31506 s\hich\af31506\dbch\af31505\loch\f31506 oftware generally.
300 \par
301 \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af2 \ltrch\fcs0 \b\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 NO WARRANTY
302 \par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
303 \par \hich\af31506\dbch\af31505\loch\f31506 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTH\hich\af31506\dbch\af31505\loch\f31506
304 ERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULA
305 \hich\af31506\dbch\af31505\loch\f31506 R\hich\af31506\dbch\af31505\loch\f31506
306 PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
307 \par
308 \par \hich\af31506\dbch\af31505\loch\f31506 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGRE\hich\af31506\dbch\af31505\loch\f31506
309 ED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR I
310 \hich\af31506\dbch\af31505\loch\f31506 N\hich\af31506\dbch\af31505\loch\f31506
311 ABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEE
312 \hich\af31506\dbch\af31505\loch\f31506 N\hich\af31506\dbch\af31505\loch\f31506 ADVISED OF THE POSSIBILITY OF SUCH
313 \par \hich\af31506\dbch\af31505\loch\f31506 DAMAGES.
314 \par
315 \par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 END OF TERMS AND CONDITIONS
316
317 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
318 \par }\pard \ltrpar\qc \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0\pararsid7013135 {\rtlch\fcs1 \af2 \ltrch\fcs0 \b\lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
319 How to Apply These Terms to Your New Libraries
320 \par }\pard \ltrpar\ql \li0\ri0\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
321 \par \hich\af31506\dbch\af31505\loch\f31506 If you develop a new library, and you want it to be of the greatest possible use to the public, we \hich\af31506\dbch\af31505\loch\f31506
322 recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License).
323 \par
324 \par \hich\af31506\dbch\af31505\loch\f31506 To apply these terms, attach the foll\hich\af31506\dbch\af31505\loch\f31506
325 owing notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
326
327 \par
328 \par \hich\af31506\dbch\af31505\loch\f31506 \hich\af31506\dbch\af31505\loch\f31506 <one line to give the library's name and a brief idea of what it does.> }{\rtlch\fcs1 \af2 \ltrch\fcs0 \insrsid1254708\charrsid7013135
329 \hich\af31506\dbch\af31505\loch\f31506 Copyright (C) <year> <name of author>
330 \par
331 \par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506
332 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as publishe\hich\af31506\dbch\af31505\loch\f31506
333 d by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
334 \par
335 \par \hich\af31506\dbch\af31505\loch\f31506 This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\hich\af31506\dbch\af31505\loch\f31506
336 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
337 \par
338 \par \hich\af31506\dbch\af31505\loch\f31506 You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
339 \par \hich\af31506\dbch\af31505\loch\f31506 Foundation, Inc\hich\af31506\dbch\af31505\loch\f31506 ., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
340 \par
341 \par \hich\af31506\dbch\af31505\loch\f31506 Also add information on how to contact you by electronic and paper mail.
342 \par
343 \par \hich\af31506\dbch\af31505\loch\f31506 You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaim\hich\af31506\dbch\af31505\loch\f31506 er" for the library, if
344 \par \hich\af31506\dbch\af31505\loch\f31506 necessary. Here is a sample; alter the names:
345 \par
346 \par \hich\af31506\dbch\af31505\loch\f31506 Yoyodyne, Inc., hereby disclaims all copyright interest in the
347 \par \hich\af31506\dbch\af31505\loch\f31506 library `Frob' (a library for tweaking knobs) written by James Random Hacker.
348 \par
349 \par \hich\af31506\dbch\af31505\loch\f31506 <signature of Ty Coon>, 1 April 1990
350 \par \hich\af31506\dbch\af31505\loch\f31506 }{\rtlch\fcs1 \af2 \ltrch\fcs0 \insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 Ty Coon, President of Vice
351 \par
352 \par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135 \hich\af31506\dbch\af31505\loch\f31506 That's all there is to it!
353 \par }{\rtlch\fcs1 \af2 \ltrch\fcs0 \lang1033\langfe1031\langnp1033\insrsid1254708\charrsid7013135
354 \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a
355 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad
356 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6
357 b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0
358 0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6
359 a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f
360 c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512
361 0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462
362 a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865
363 6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b
364 4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b
365 4757e8d3f729e245eb2b260a0238fd010000ffff0300504b03041400060008000000210030dd4329a8060000a41b0000160000007468656d652f7468656d652f
366 7468656d65312e786d6cec594f6fdb3614bf0fd87720746f6327761a07758ad8b19b2d4d1bc46e871e698996d850a240d2497d1bdae38001c3ba618715d86d87
367 615b8116d8a5fb34d93a6c1dd0afb0475292c5585e9236d88aad3e2412f9e3fbff1e1fa9abd7eec70c1d1221294fda5efd72cd4324f1794093b0eddd1ef62fad
368 79482a9c0498f184b4bd2991deb58df7dfbb8ad755446282607d22d771db8b944ad79796a40fc3585ee62949606ecc458c15bc8a702910f808e8c66c69b9565b
369 5d8a314d3c94e018c8de1a8fa94fd05093f43672e23d06af89927ac06762a049136785c10607758d9053d965021d62d6f6804fc08f86e4bef210c352c144dbab
370 999fb7b4717509af678b985ab0b6b4ae6f7ed9ba6c4170b06c788a705430adf71bad2b5b057d03606a1ed7ebf5babd7a41cf00b0ef83a6569632cd467faddec9
371 699640f6719e76b7d6ac355c7c89feca9cccad4ea7d36c65b258a206641f1b73f8b5da6a6373d9c11b90c537e7f08dce66b7bbeae00dc8e257e7f0fd2badd586
372 8b37a088d1e4600ead1ddaef67d40bc898b3ed4af81ac0d76a197c86826828a24bb318f3442d8ab518dfe3a20f000d6458d104a9694ac6d88728eee2782428d6
373 0cf03ac1a5193be4cbb921cd0b495fd054b5bd0f530c1931a3f7eaf9f7af9e3f45c70f9e1d3ff8e9f8e1c3e3073f5a42ceaa6d9c84e5552fbffdeccfc71fa33f
374 9e7ef3f2d117d57859c6fffac327bffcfc793510d26726ce8b2f9ffcf6ecc98baf3efdfdbb4715f04d814765f890c644a29be408edf3181433567125272371be
375 15c308d3f28acd249438c19a4b05fd9e8a1cf4cd296699771c393ac4b5e01d01e5a30a787d72cf1178108989a2159c77a2d801ee72ce3a5c545a6147f32a9979
376 3849c26ae66252c6ed637c58c5bb8b13c7bfbd490a75330f4b47f16e441c31f7184e140e494214d273fc80900aedee52ead87597fa824b3e56e82e451d4c2b4d
377 32a423279a668bb6690c7e9956e90cfe766cb37b077538abd27a8b1cba48c80acc2a841f12e698f13a9e281c57911ce298950d7e03aba84ac8c154f8655c4f2a
378 f074481847bd804859b5e696007d4b4edfc150b12addbecba6b18b148a1e54d1bc81392f23b7f84137c2715a851dd0242a633f900710a218ed715505dfe56e86
379 e877f0034e16bafb0e258ebb4faf06b769e888340b103d331115bebc4eb813bf83291b63624a0d1475a756c734f9bbc2cd28546ecbe1e20a3794ca175f3fae90
380 fb6d2dd99bb07b55e5ccf68942bd0877b23c77b908e8db5f9db7f024d9239010f35bd4bbe2fcae387bfff9e2bc289f2fbe24cfaa301468dd8bd846dbb4ddf1c2
381 ae7b4c191ba8292337a469bc25ec3d411f06f53a73e224c5292c8de0516732307070a1c0660d125c7d44553488700a4d7bddd3444299910e254ab984c3a219ae
382 a4adf1d0f82b7bd46cea4388ad1c12ab5d1ed8e1153d9c9f350a3246aad01c6873462b9ac05999ad5cc988826eafc3acae853a33b7ba11cd1445875ba1b236b1
383 399483c90bd560b0b0263435085a21b0f22a9cf9356b38ec6046026d77eba3dc2dc60b17e92219e180643ed27acffba86e9c94c7ca9c225a0f1b0cfae0788ad5
384 4adc5a9aec1b703b8b93caec1a0bd8e5de7b132fe5113cf312503b998e2c2927274bd051db6b35979b1ef271daf6c6704e86c73805af4bdd476216c26593af84
385 0dfb5393d964f9cc9bad5c313709ea70f561ed3ea7b053075221d51696910d0d339585004b34272bff7213cc7a510a5454a3b349b1b206c1f0af490176745d4b
386 c663e2abb2b34b23da76f6352ba57ca2881844c1111ab189d8c7e07e1daaa04f40255c77988aa05fe06e4e5bdb4cb9c5394bbaf28d98c1d971ccd20867e556a7
387 689ec9166e0a522183792b8907ba55ca6e943bbf2a26e52f48957218ffcf54d1fb09dc3eac04da033e5c0d0b8c74a6b43d2e54c4a10aa511f5fb021a07533b20
388 5ae07e17a621a8e082dafc17e450ffb739676998b48643a4daa7211214f623150942f6a02c99e83b85583ddbbb2c4996113211551257a656ec1139246ca86be0
389 aadedb3d1441a89b6a929501833b197fee7b9641a3503739e57c732a59b1f7da1cf8a73b1f9bcca0945b874d4393dbbf10b1680f66bbaa5d6f96e77b6f59113d
390 316bb31a795600b3d256d0cad2fe354538e7566b2bd69cc6cbcd5c38f0e2bcc63058344429dc2121fd07f63f2a7c66bf76e80d75c8f7a1b622f878a18941d840
391 545fb28d07d205d20e8ea071b283369834296bdaac75d256cb37eb0bee740bbe278cad253b8bbfcf69eca23973d939b97891c6ce2cecd8da8e2d343578f6648a
392 c2d0383fc818c798cf64e52f597c740f1cbd05df0c264c49134cf09d4a60e8a107260f20f92d47b374e32f000000ffff0300504b030414000600080000002100
393 0dd1909fb60000001b010000270000007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f7
394 8277086f6fd3ba109126dd88d0add40384e4350d363f2451eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89
395 d93b64b060828e6f37ed1567914b284d262452282e3198720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd500
396 1996509affb3fd381a89672f1f165dfe514173d9850528a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0f
397 bfff0000001c0200001300000000000000000000000000000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6
398 a7e7c0000000360100000b00000000000000000000000000300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a
399 0000001c00000000000000000000000000190200007468656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d00140006000800000021
400 0030dd4329a8060000a41b00001600000000000000000000000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d001400060008
401 00000021000dd1909fb60000001b0100002700000000000000000000000000b20900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000ad0a00000000}
402 {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d
403 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169
404 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363
405 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e}
406 {\*\latentstyles\lsdstimax267\lsdlockeddef0\lsdsemihiddendef1\lsdunhideuseddef1\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;
407 \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4;
408 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;
409 \lsdpriority39 \lsdlocked0 toc 1;\lsdpriority39 \lsdlocked0 toc 2;\lsdpriority39 \lsdlocked0 toc 3;\lsdpriority39 \lsdlocked0 toc 4;\lsdpriority39 \lsdlocked0 toc 5;\lsdpriority39 \lsdlocked0 toc 6;\lsdpriority39 \lsdlocked0 toc 7;
410 \lsdpriority39 \lsdlocked0 toc 8;\lsdpriority39 \lsdlocked0 toc 9;\lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdpriority1 \lsdlocked0 Default Paragraph Font;
411 \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority22 \lsdlocked0 Strong;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;
412 \lsdsemihidden0 \lsdunhideused0 \lsdpriority59 \lsdlocked0 Table Grid;\lsdunhideused0 \lsdlocked0 Placeholder Text;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;
413 \lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid;
414 \lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1;
415 \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2;
416 \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading;
417 \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 1;
418 \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;
419 \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 1;\lsdunhideused0 \lsdlocked0 Revision;
420 \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;
421 \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;
422 \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 1;
423 \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 2;
424 \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;
425 \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 2;
426 \lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;
427 \lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 2;
428 \lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 3;
429 \lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;
430 \lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;
431 \lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 3;
432 \lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;
433 \lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 4;
434 \lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;
435 \lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;
436 \lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 4;
437 \lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 5;
438 \lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;
439 \lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 5;
440 \lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;
441 \lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 5;
442 \lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdsemihidden0 \lsdunhideused0 \lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority61 \lsdlocked0 Light List Accent 6;
443 \lsdsemihidden0 \lsdunhideused0 \lsdpriority62 \lsdlocked0 Light Grid Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;
444 \lsdsemihidden0 \lsdunhideused0 \lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority66 \lsdlocked0 Medium List 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;
445 \lsdsemihidden0 \lsdunhideused0 \lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority70 \lsdlocked0 Dark List Accent 6;
446 \lsdsemihidden0 \lsdunhideused0 \lsdpriority71 \lsdlocked0 Colorful Shading Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdsemihidden0 \lsdunhideused0 \lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;
447 \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis;
448 \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;
449 \lsdsemihidden0 \lsdunhideused0 \lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdpriority37 \lsdlocked0 Bibliography;\lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;}}{\*\datastore 010500000200000018000000
450 4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000
451 d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
452 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
453 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
454 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
455 fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
456 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
457 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
458 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
459 ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000050f6
460 efc420d2ce01feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000
461 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000
462 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000
463 0000000000000000000000000000000000000000000000000105000000000000}}
0 <?xml version="1.0" encoding="UTF-8"?>
1 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
2 <?include @ODBC_SOURCE_WIX_DIR@/binaries_dir.xml ?>
3 <Product Id="*" Name="@PRODUCT_NAME@" Language="1033"
4 Version="@PRODUCT_VERSION@"
5 Manufacturer="@PRODUCT_MANUFACTURER@" UpgradeCode="b43bad5d-118f-4368-8977-e60fd4dd4317">
6 <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Platform="@WIXPLATFORM@"/>
7
8 <MajorUpgrade DowngradeErrorMessage="A newer version of @PRODUCT_NAME@ is already installed." />
9 <MediaTemplate EmbedCab="yes"/>
10
11 <UIRef Id="WixUI_Mondo" />
12 <WixVariable Id="WixUILicenseRtf" Value="@ODBC_SOURCE_WIX_DIR@/license.rtf" />
13 <WixVariable Id="WixUIBannerBmp" Value="@ODBC_SOURCE_WIX_DIR@/WixUIBannerBmp.jpg" />
14 <WixVariable Id="WixUIDialogBmp" Value="@ODBC_SOURCE_WIX_DIR@/WixUIDialogBmp.jpg" />
15
16 <Feature Id="ProductFeature" Title="@PRODUCT_NAME@ @PRODUCT_VERSION@" Level="1">
17 <ComponentRef Id="RegistryKeys" />
18 <ComponentRef Id="Setup" />
19 <ComponentRef Id="Driver" />
20 <ComponentRef Id="CcPlugins" />
21 </Feature>
22 <Feature Id="DebugFeature" Title="Debug Information" Level="2">
23 <ComponentRef Id="Debug" />
24 </Feature>
25 <Feature Id="PluginsFeature" Title="Authentification Plugins" Level="2">
26 <ComponentRef Id="CcPlugins" />
27 <ComponentRef Id="PluginsDebug" />
28 </Feature>
29 </Product>
30
31 <Fragment>
32 <Directory Id="TARGETDIR" Name="SourceDir">
33 <Directory Id="@FOLDER@">
34 <Directory Id="MariaDB" Name="@PRODUCT_MANUFACTURER@">
35 <Directory Id="INSTALLFOLDER" Name="@PRODUCT_NAME@">
36 <Directory Id="PLUGINSFOLDER" Name="$(var.plugins_subdir_name)">
37 </Directory>
38 </Directory>
39 </Directory>
40 </Directory>
41 </Directory>
42 </Fragment>
43
44 <Fragment>
45 <!--<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">-->
46 <Component Id="RegistryKeys" Guid="@GUID_REGISTRY@" DiskId="1" Directory="INSTALLFOLDER" Win64="@IS_WIN64@">
47 <RegistryKey Id="Version" Root="HKLM" Key="SOFTWARE\@PRODUCT_MANUFACTURER@\@PRODUCT_NAME@" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
48 <RegistryValue Name="Version" Type="string" Value="@PRODUCT_VERSION@"/>
49 </RegistryKey>
50 </Component>
51 <Component Id="Setup" Guid="@GUID_SETUP@" DiskId="1" Directory="INSTALLFOLDER" Win64="@IS_WIN64@">
52 <File Id="mariadb_odbc_setup" Name="maodbcs.dll" DiskId="1" Source="$(var.binaries_dir)/maodbcs.dll" />
53 <File Id="mariadb_odbc_setup_lib" Name="maodbcs.lib" DiskId="1" Source="$(var.binaries_dir)/maodbcs.lib" />
54 </Component>
55 <Component Id="Driver" Guid="@GUID_DRIVER@" SharedDllRefCount="yes" Directory="INSTALLFOLDER" Win64="@IS_WIN64@">
56 <File Id="mariadb_odbc_dll" Name="maodbc.dll" KeyPath="yes" DiskId="1" Source="$(var.binaries_dir)/maodbc.dll">
57 <ODBCDriver Id="madb_odbc_driver" Name="MariaDB ODBC @MARIADB_ODBC_VERSION_MAJOR@.@MARIADB_ODBC_VERSION_MINOR@ Driver" SetupFile="mariadb_odbc_setup" />
58 </File>
59 <File Id="mariadb_odbc_lib" Name="maodbc.lib" DiskId="1" Source="$(var.binaries_dir)/maodbc.lib" />
60 </Component>
61 <Component Id="Debug" Guid="@GUID_DEBUG@" Directory="INSTALLFOLDER" DiskId="1" Win64="@IS_WIN64@">
62 <File Id="mariadb_odbc_dll_pdb" Name="maodbc.pdb" KeyPath="yes" DiskId="1" Source="$(var.binaries_dir)/maodbc.pdb" />
63 <File Id="mariadb_odbc_setup_pdb" Name="maodbcs.pdb" DiskId="1" Source="$(var.binaries_dir)/maodbcs.pdb" />
64 <CreateFolder />
65 </Component>
66 <Component Id="CcPlugins" Guid="@GUID_PLUGINS@" Directory="PLUGINSFOLDER" DiskId="1" Win64="@IS_WIN64@">
67 <File Id="caching_sha2_password.dll" Name="caching_sha2_password.dll" DiskId="1" Source="$(var.plugins_source_dir)/caching_sha2_password.dll" />
68 <File Id="dialog_dll" Name="dialog.dll" KeyPath="yes" DiskId="1" Source="$(var.plugins_source_dir)/dialog.dll" />
69 <File Id="auth_gssapi_client_dll" Name="auth_gssapi_client.dll" DiskId="1" Source="$(var.plugins_source_dir)/auth_gssapi_client.dll" />
70 <File Id="mysql_clear_password_dll" Name="mysql_clear_password.dll" DiskId="1" Source="$(var.plugins_source_dir)/mysql_clear_password.dll" />
71 <File Id="sha256_password_dll" Name="sha256_password.dll" DiskId="1" Source="$(var.plugins_source_dir)/sha256_password.dll" />
72 </Component>
73 <Component Id="PluginsDebug" Guid="@GUID_PLUGINS_DEBUG@" Directory="PLUGINSFOLDER" DiskId="1" Win64="@IS_WIN64@">
74 <File Id="dialog_pdb" Name="dialog.pdb" DiskId="1" Source="$(var.plugins_source_dir)/dialog.pdb" />
75 <File Id="auth_gssapi_client_pdb" Name="auth_gssapi_client.pdb" DiskId="1" Source="$(var.plugins_source_dir)/auth_gssapi_client.pdb" />
76 <File Id="mysql_clear_password_pdb" Name="mysql_clear_password.pdb" DiskId="1" Source="$(var.plugins_source_dir)/mysql_clear_password.pdb" />
77 <File Id="sha256_password_pdb" Name="sha256_password.pdb" DiskId="1" Source="$(var.plugins_source_dir)/sha256_password.pdb" />
78 <CreateFolder />
79 </Component>
80 <!-- </ComponentGroup> -->
81 </Fragment>
82 </Wix>