pax_global_header00006660000000000000000000000064151046643730014523gustar00rootroot0000000000000052 comment=27928bc299c7d132008406fa86c0982e1481f4ff odpi-5.6.4/000077500000000000000000000000001510466437300124725ustar00rootroot00000000000000odpi-5.6.4/.gitattributes000066400000000000000000000001411510466437300153610ustar00rootroot00000000000000* text=auto *.c text *.h text *.md text *.py text *.rst text *.txt text odpi-5.6.4/.github/000077500000000000000000000000001510466437300140325ustar00rootroot00000000000000odpi-5.6.4/.github/ISSUE_TEMPLATE/000077500000000000000000000000001510466437300162155ustar00rootroot00000000000000odpi-5.6.4/.github/ISSUE_TEMPLATE/announcements.md000066400000000000000000000004301510466437300214110ustar00rootroot00000000000000--- name: Announcements about: Use this if you are sharing something interesting title: '' labels: announcement assignees: '' --- odpi-5.6.4/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000023671510466437300207170ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: bug assignees: '' --- 1. What version of ODPI-C are you using (see dpi.h)? 2. What OS (and version) is your application on? 3. What compiler (and version) did you use? 4. What is your version of the Oracle Client (e.g. Instant Client)? How was it installed? Where it is installed? 5. What is your Oracle Database version? 6. What is the `PATH` environment variable (on Windows) or `LD_LIBRARY_PATH` (on Linux) set to? 7. What environment variables did you set? How *exactly* did you set them? 8. What problem or error(s) you are seeing? 9. Do you have a runnable code snippet to describe the problem? odpi-5.6.4/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000000341510466437300202020ustar00rootroot00000000000000blank_issues_enabled: false odpi-5.6.4/.github/ISSUE_TEMPLATE/documentation-and-example-improvements.md000066400000000000000000000010521510466437300263250ustar00rootroot00000000000000--- name: Documentation and Example Improvements about: Use this to suggest changes to documentation and examples title: '' labels: enhancement assignees: '' --- 1. What is the link to the documentation section that needs improving? 2. Describe the confusion 3. Suggest changes that would help odpi-5.6.4/.github/ISSUE_TEMPLATE/enhancement-requests.md000066400000000000000000000011441510466437300226750ustar00rootroot00000000000000--- name: Enhancement Requests about: Use this for enhancement requests title: '' labels: enhancement assignees: '' --- 1. Describe your new request in detail 2. Give supporting information about tools and operating systems. Give relevant product version numbers odpi-5.6.4/.github/ISSUE_TEMPLATE/general-questions-and-runtime-problems.md000066400000000000000000000025021510466437300262450ustar00rootroot00000000000000--- name: Questions and Runtime Problems about: For general ODPI-C questions title: '' labels: question assignees: '' --- 1. What version of ODPI-C are you using (see dpi.h)? 2. What OS (and version) is your application on? 3. What compiler (and version) did you use? 4. What is your version of the Oracle Client (e.g. Instant Client)? How was it installed? Where it is installed? 5. What is your Oracle Database version? 6. What is the `PATH` environment variable (on Windows) or `LD_LIBRARY_PATH` (on Linux) set to? 7. What environment variables did you set? How *exactly* did you set them? 8. What problem or error(s) you are seeing? 9. Do you have a runnable code snippet to describe the problem? odpi-5.6.4/.github/ISSUE_TEMPLATE/installation-questions.md000066400000000000000000000023531510466437300232730ustar00rootroot00000000000000--- name: Installation Problems about: Use this for installation questions title: '' labels: install & configuration assignees: '' --- 1. What version of ODPI-C are you using (see dpi.h)? 2. What OS (and version) is your application on? 3. What compiler (and version) did you use? 4. What is your version of the Oracle Client (e.g. Instant Client)? How was it installed? Where it is installed? 5. What is your Oracle Database version? 6. What is the `PATH` environment variable (on Windows) or `LD_LIBRARY_PATH` (on Linux) set to? 7. What environment variables did you set? How *exactly* did you set them? 8. What problem or error(s) you are seeing? odpi-5.6.4/.github/pull_request_template.md000066400000000000000000000002231510466437300207700ustar00rootroot00000000000000Sorry, Pull Requests for ODPI-C cannot be accepted. Please report bugs and ask questions using GitHub issues https://github.com/oracle/odpi/issues odpi-5.6.4/.github/stale.yml000066400000000000000000000015341510466437300156700ustar00rootroot00000000000000# https://probot.github.io/apps/stale/ # Number of days of inactivity before an issue becomes stale daysUntilStale: 30 # Number of days of inactivity before a stale issue is closed daysUntilClose: 7 # Issues with these labels will never be considered stale exemptLabels: - pinned - enhancement - bug - announcement - OCA accepted # Label to use when marking an issue as stale staleLabel: inactive # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as inactive because it has not been updated recently. It will be closed if no further activity occurs. Thank you for your contributions. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: > This issue has been automatically closed because it has not been updated for a month. odpi-5.6.4/.gitignore000066400000000000000000000000541510466437300144610ustar00rootroot00000000000000build lib doc/build test/build __pycache__/ odpi-5.6.4/.readthedocs.yaml000066400000000000000000000004441510466437300157230ustar00rootroot00000000000000# required version: 2 build: os: ubuntu-20.04 tools: python: "3.9" # Build documentation in the doc/src directory with Sphinx sphinx: configuration: doc/src/conf.py # declare Python requirements required to build docs python: install: - requirements: doc/requirements.txt odpi-5.6.4/CONTRIBUTING.md000066400000000000000000000002261510466437300147230ustar00rootroot00000000000000Sorry, Pull Requests for ODPI-C cannot be accepted. Please report bugs and ask questions using [GitHub issues](https://github.com/oracle/odpi/issues) odpi-5.6.4/LICENSE.txt000066400000000000000000000273461510466437300143310ustar00rootroot00000000000000Copyright (c) 2016, 2025 Oracle and/or its affiliates. This program is free software: you can modify it and/or redistribute it under the terms of: (i) the Universal Permissive License v 1.0 or at your option, any later version (); and/or (ii) the Apache License v 2.0. () The Universal Permissive License (UPL), Version 1.0 =================================================== Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both (a) the Software, and (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a "Larger Work" to which the Software is contributed by such licensors), without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms. This license is subject to the following condition: The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Apache License ============== Version 2.0, January 2004 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. **Definitions**. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. **Grant of Copyright License.** Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. **Grant of Patent License.** Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. **Redistribution.** You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. **Submission of Contributions.** Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. **Trademarks.** This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. **Disclaimer of Warranty.** Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. **Limitation of Liability.** In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. **Accepting Warranty or Additional Liability.** While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS odpi-5.6.4/Makefile000066400000000000000000000125441510466437300141400ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2016, 2025, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # Sample Makefile showing how ODPI-C can be built as a shared library on # platforms other than Windows. For Windows, see Makefile.win32. # # See https://oracle.github.io/odpi/doc/installation.html # for the platforms and compilers known to work. #------------------------------------------------------------------------------ vpath %.c src vpath %.h include src PREFIX ?= /usr/local INSTALL_LIB_DIR = $(PREFIX)/lib INSTALL_INC_DIR = $(PREFIX)/include INSTALL_SHARE_DIR = $(PREFIX)/share/odpi BUILD_DIR = build LIB_DIR = lib SAMPLES_DIR = samples TESTS_DIR = test CC ?= gcc AWK ?= awk MAJOR_VERSION := $(shell $(AWK) '/define.*DPI_MAJOR_VERSION/ {print $$3}' \ include/dpi.h ) MINOR_VERSION := $(shell $(AWK) '/define.*DPI_MINOR_VERSION/ {print $$3}' \ include/dpi.h ) PATCH_LEVEL := $(shell $(AWK) '/define.*DPI_PATCH_LEVEL/ {print $$3}' \ include/dpi.h ) INSTALL ?= install CFLAGS ?= -O2 -g -Wall -Wextra -fPIC EXTRA_CFLAGS ?= INCLUDES ?= -Iinclude LIBS ?= -ldl -lpthread LDFLAGS ?= -shared EXTRA_LDFLAGS ?= VERSION_LIB_NAME = $(LIB_NAME).$(MAJOR_VERSION) FULL_LIB_NAME = $(VERSION_LIB_NAME).$(MINOR_VERSION).$(PATCH_LEVEL) ifeq ($(shell uname -s), Darwin) LIB_NAME = libodpic.dylib LIB_OUT_OPTS = -dynamiclib \ -install_name $(shell pwd)/$(LIB_DIR)/$(LIB_NAME) \ -o $(LIB_DIR)/$(FULL_LIB_NAME) else LIB_NAME = libodpic.so LIB_OUT_OPTS = -o $(LIB_DIR)/$(FULL_LIB_NAME) LDFLAGS += -Wl,-soname,$(LIB_NAME).$(MAJOR_VERSION) endif SRCS = dpiConn.c dpiContext.c dpiData.c dpiEnv.c dpiError.c dpiGen.c \ dpiGlobal.c dpiLob.c dpiObject.c dpiObjectAttr.c dpiObjectType.c \ dpiPool.c dpiStmt.c dpiUtils.c dpiVar.c dpiOracleType.c dpiSubscr.c \ dpiDeqOptions.c dpiEnqOptions.c dpiMsgProps.c dpiRowid.c dpiOci.c \ dpiDebug.c dpiHandlePool.c dpiHandleList.c dpiSodaColl.c \ dpiSodaCollCursor.c dpiSodaDb.c dpiSodaDoc.c dpiSodaDocCursor.c \ dpiQueue.c dpiJson.c dpiStringList.c dpiVector.c OBJS = $(SRCS:%.c=$(BUILD_DIR)/%.o) SAMPLES_FILES := $(SAMPLES_DIR)/Makefile $(SAMPLES_DIR)/README.md \ $(wildcard $(SAMPLES_DIR)/*.c) $(wildcard $(SAMPLES_DIR)/*.h) \ $(wildcard $(SAMPLES_DIR)/sql/*.sql) SAMPLES_TARGETS := $(SAMPLES_FILES:%=$(INSTALL_SHARE_DIR)/%) INSTALL_SAMPLES_SQL_DIR := $(INSTALL_SHARE_DIR)/$(SAMPLES_DIR)/sql TESTS_FILES := $(TESTS_DIR)/Makefile $(TESTS_DIR)/README.md \ $(wildcard $(TESTS_DIR)/*.c) $(wildcard $(TESTS_DIR)/*.h) \ $(wildcard $(TESTS_DIR)/sql/*.sql) TESTS_TARGETS := $(TESTS_FILES:%=$(INSTALL_SHARE_DIR)/%) INSTALL_TESTS_SQL_DIR := $(INSTALL_SHARE_DIR)/$(TESTS_DIR)/sql INSTALL_TARGETS = $(INSTALL_INC_DIR)/dpi.h \ $(INSTALL_LIB_DIR)/$(LIB_NAME) $(INSTALL_LIB_DIR)/$(FULL_LIB_NAME) \ $(INSTALL_LIB_DIR)/$(VERSION_LIB_NAME) $(INSTALL_SHARE_DIR) all: $(LIB_DIR)/$(FULL_LIB_NAME) $(LIB_DIR)/$(VERSION_LIB_NAME) \ $(LIB_DIR)/$(LIB_NAME) clean: rm -rf $(BUILD_DIR) $(LIB_DIR) $(BUILD_DIR): mkdir -p $(BUILD_DIR) $(LIB_DIR): mkdir -p $(LIB_DIR) $(BUILD_DIR)/%.o: %.c dpi.h dpiImpl.h dpiErrorMessages.h $(CC) -c $(INCLUDES) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LIB_DIR)/$(FULL_LIB_NAME): $(BUILD_DIR) $(LIB_DIR) $(OBJS) $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LIB_OUT_OPTS) $(OBJS) $(LIBS) $(LIB_DIR)/$(VERSION_LIB_NAME): $(LIB_DIR)/$(FULL_LIB_NAME) ln -sf $(FULL_LIB_NAME) $@ $(LIB_DIR)/$(LIB_NAME): $(LIB_DIR)/$(VERSION_LIB_NAME) ln -sf $(VERSION_LIB_NAME) $@ $(INSTALL_LIB_DIR): mkdir -p $@ $(INSTALL_INC_DIR): mkdir -p $@ $(INSTALL_SAMPLES_SQL_DIR): mkdir -p $@ $(INSTALL_TESTS_SQL_DIR): mkdir -p $@ $(INSTALL_INC_DIR)/%.h: %.h $(INSTALL) $< $@ $(INSTALL_LIB_DIR)/$(FULL_LIB_NAME): $(LIB_DIR)/$(LIB_NAME) $(INSTALL) $< $@ if test "`uname -s`" = Darwin; then \ install_name_tool -id $(INSTALL_LIB_DIR)/$(VERSION_LIB_NAME) $@; fi $(INSTALL_LIB_DIR)/$(VERSION_LIB_NAME): $(INSTALL_LIB_DIR)/$(FULL_LIB_NAME) ln -sf $(FULL_LIB_NAME) $@ $(INSTALL_LIB_DIR)/$(LIB_NAME): $(INSTALL_LIB_DIR)/$(VERSION_LIB_NAME) ln -sf $(VERSION_LIB_NAME) $@ $(INSTALL_SHARE_DIR)/%: % $(INSTALL) $< $@ install: $(INSTALL_SAMPLES_SQL_DIR) $(INSTALL_TESTS_SQL_DIR) \ $(INSTALL_INC_DIR) $(INSTALL_LIB_DIR) $(INSTALL_TARGETS) \ $(INSTALL_SHARE_DIR)/README.md $(INSTALL_SHARE_DIR)/LICENSE.txt \ $(SAMPLES_TARGETS) $(TESTS_TARGETS) uninstall: rm -rf $(INSTALL_TARGETS) odpi-5.6.4/Makefile.win32000066400000000000000000000062601510466437300150770ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2017, 2024, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # # Sample nmake Makefile showing how ODPI-C can be built as a Windows DLL and # import library. # # This file is expected to be processed by nmake as in the following: # nmake /f Makefile.win32 # # Installation instructions: # https://oracle.github.io/odpi/doc/installation.html # #------------------------------------------------------------------------------ SRC_DIR = src INCLUDE_DIR = include BUILD_DIR = build LIB_DIR = lib DLL_NAME = $(LIB_DIR)\odpic.dll LIB_NAME = $(LIB_DIR)\odpic.lib OBJS = $(BUILD_DIR)\dpiConn.obj $(BUILD_DIR)\dpiContext.obj \ $(BUILD_DIR)\dpiData.obj $(BUILD_DIR)\dpiEnv.obj \ $(BUILD_DIR)\dpiError.obj $(BUILD_DIR)\dpiGen.obj \ $(BUILD_DIR)\dpiGlobal.obj $(BUILD_DIR)\dpiLob.obj \ $(BUILD_DIR)\dpiObject.obj $(BUILD_DIR)\dpiObjectAttr.obj \ $(BUILD_DIR)\dpiObjectType.obj $(BUILD_DIR)\dpiPool.obj \ $(BUILD_DIR)\dpiStmt.obj $(BUILD_DIR)\dpiUtils.obj \ $(BUILD_DIR)\dpiVar.obj $(BUILD_DIR)\dpiOracleType.obj \ $(BUILD_DIR)\dpiSubscr.obj $(BUILD_DIR)\dpiDeqOptions.obj \ $(BUILD_DIR)\dpiEnqOptions.obj $(BUILD_DIR)\dpiMsgProps.obj \ $(BUILD_DIR)\dpiRowid.obj $(BUILD_DIR)\dpiOci.obj \ $(BUILD_DIR)\dpiDebug.obj $(BUILD_DIR)\dpiHandlePool.obj \ $(BUILD_DIR)\dpiHandleList.obj $(BUILD_DIR)\dpiSodaColl.obj \ $(BUILD_DIR)\dpiSodaCollCursor.obj $(BUILD_DIR)\dpiSodaDb.obj \ $(BUILD_DIR)\dpiSodaDoc.obj $(BUILD_DIR)\dpiSodaDocCursor.obj \ $(BUILD_DIR)\dpiQueue.obj $(BUILD_DIR)\dpiJson.obj \ $(BUILD_DIR)\dpiStringList.obj $(BUILD_DIR)\dpiVector.obj all: $(BUILD_DIR) $(LIB_DIR) $(DLL_NAME) $(LIB_NAME) clean: @if exist $(BUILD_DIR) rmdir /S /Q $(BUILD_DIR) @if exist $(LIB_DIR) rmdir /S /Q $(LIB_DIR) $(BUILD_DIR) $(LIB_DIR): @if not exist $(BUILD_DIR) mkdir $(BUILD_DIR) @if not exist $(LIB_DIR) mkdir $(LIB_DIR) {$(SRC_DIR)}.c{$(BUILD_DIR)}.obj: cl /nologo /c /Fo$(BUILD_DIR)\ /I$(INCLUDE_DIR) /DDPI_EXPORTS $< $(DLL_NAME) $(LIB_NAME): $(OBJS) link /nologo /dll /OUT:$(DLL_NAME) $(OBJS) odpi-5.6.4/NOTICE.txt000066400000000000000000000000701510466437300142110ustar00rootroot00000000000000Copyright (c) 2016, 2023, Oracle and/or its affiliates. odpi-5.6.4/README.md000066400000000000000000000060071510466437300137540ustar00rootroot00000000000000# ODPI-C Oracle Database Programming Interface for C (ODPI-C) is an open source library of C code that simplifies access to Oracle Database for applications written in C or C++. It is a wrapper over [Oracle Call Interface (OCI)](http://www.oracle.com/technetwork/database/features/oci/index.html) that makes applications and language interfaces easier to develop. ODPI-C supports basic and advanced features of Oracle Database and Oracle Client. See the [homepage](https://oracle.github.io/odpi/) for a list. ## Installation See [ODPI-C Installation](https://oracle.github.io/odpi/doc/installation.html). ## Documentation See the [ODPI-C Documentation](https://oracle.github.io/odpi/doc/index.html) and [Release Notes](https://oracle.github.io/odpi/doc/releasenotes.html). ## Samples See [/samples](https://github.com/oracle/odpi/tree/main/samples). ## Help Please report bugs and ask questions using [GitHub issues](https://github.com/oracle/odpi/issues). ## Tests See [/test](https://github.com/oracle/odpi/tree/main/test). ## Contributing See [CONTRIBUTING](https://github.com/oracle/odpi/blob/main/CONTRIBUTING.md). ## Drivers Using ODPI-C Oracle Drivers: * [python-oracledb](https://oracle.github.io/python-oracledb) Python interface (previously known as cx_Oracle). * [node-oracledb](https://oracle.github.io/node-oracledb) Node.js module. Third-party Drivers: * [godror](https://github.com/godror/godror) Go Driver. * [odpic-raw](https://github.com/leptonyu/odpic-raw) Haskell Raw Bindings. * [oracle-simple](https://github.com/haskell-oracle/oracle-simple) Haskell driver. * [ruby-ODPI ](https://github.com/kubo/ruby-odpi) Ruby Interface. * [rust-oracle ](https://github.com/kubo/rust-oracle) Driver for Rust. * [Oracle.jl](https://github.com/felipenoris/Oracle.jl) Driver for Julia. * [oranif](https://github.com/KonnexionsGmbH/oranif) Driver for Erlang. * [nimodpi](https://github.com/mikra01/nimodpi) Driver for Nim. * [Tcl](https://github.com/bagnongithub/oratcl) Driver for Tcl. ## Security Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process. ## License Copyright (c) 2016, 2025, Oracle and/or its affiliates. This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. If you elect to accept the software under the Apache License, Version 2.0, the following applies: Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. odpi-5.6.4/SECURITY.md000066400000000000000000000031611510466437300142640ustar00rootroot00000000000000# Reporting security vulnerabilities Oracle values the independent security research community and believes that responsible disclosure of security vulnerabilities helps us ensure the security and privacy of all our users. Please do NOT raise a GitHub Issue to report a security vulnerability. If you believe you have found a security vulnerability, please submit a report to [secalert_us@oracle.com][1] preferably with a proof of concept. Please review some additional information on [how to report security vulnerabilities to Oracle][2]. We encourage people who contact Oracle Security to use email encryption using [our encryption key][3]. We ask that you do not use other channels or contact the project maintainers directly. Non-vulnerability related security issues such as great new ideas for security features are welcome on GitHub Issues. ## Security updates, alerts and bulletins Our project will typically release security fixes in conjunction with each patch release. Oracle security information, including past advisories, is available on the [security alerts][4] page. ## Security-related information We will provide security related information such as a threat model, considerations for secure use, or any known security issues in our documentation. Please note that labs and sample code are intended to demonstrate a concept and may not be sufficiently hardened for production use. [1]: mailto:secalert_us@oracle.com [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html [3]: https://www.oracle.com/security-alerts/encryptionkey.html [4]: https://www.oracle.com/security-alerts/ odpi-5.6.4/doc/000077500000000000000000000000001510466437300132375ustar00rootroot00000000000000odpi-5.6.4/doc/Makefile000066400000000000000000000030371510466437300147020ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ # Makefile to generate ODPI-C documentation using Sphinx SPHINXOPTS = SPHINXBUILD = sphinx-build SOURCEDIR = src BUILDDIR = build .PHONY: html html: @$(SPHINXBUILD) -M html $(SOURCEDIR) $(BUILDDIR) $(SPHINXOPTS) .PHONY: epub epub: @$(SPHINXBUILD) -M epub $(SOURCEDIR) $(BUILDDIR) $(SPHINXOPTS) .PHONY: pdf pdf: @$(SPHINXBUILD) -M latexpdf $(SOURCEDIR) $(BUILDDIR) $(SPHINXOPTS) .PHONY: clean clean: rm -rf $(BUILDDIR)/* odpi-5.6.4/doc/README.md000066400000000000000000000014061510466437300145170ustar00rootroot00000000000000The generated ODPI-C documentation is at https://oracle.github.io/odpi/doc/index.html This directory contains the documentation source. It is written using reST (re-Structured Text) format source files which are processed using Sphinx and turned into HTML, PDF or ePub documents. If you wish to build these yourself, you need to install Sphinx. Sphinx is available on many Linux distributions as a pre-built package. You can also install Sphinx on all platforms using the Python package manager "pip". For more information on Sphinx, please visit this page: http://www.sphinx-doc.org Once Sphinx is installed, the supplied Makefile can be used to build the different targets. The generated ODPI-C documentation found on GitHub can be built using the command "make html". odpi-5.6.4/doc/requirements.txt000066400000000000000000000000461510466437300165230ustar00rootroot00000000000000sphinx>=4.2.0 sphinx-rtd-theme>=0.5.2 odpi-5.6.4/doc/src/000077500000000000000000000000001510466437300140265ustar00rootroot00000000000000odpi-5.6.4/doc/src/.static/000077500000000000000000000000001510466437300153735ustar00rootroot00000000000000odpi-5.6.4/doc/src/.static/custom.css000066400000000000000000000004131510466437300174150ustar00rootroot00000000000000/* Added code to display tables without horizontal scrollbars */ .wy-table-responsive table td, .wy-table-responsive table th { white-space: normal; } /* Added code to override the default content width in ReadtheDocs */ .wy-nav-content { max-width: none; } odpi-5.6.4/doc/src/_ext/000077500000000000000000000000001510466437300147655ustar00rootroot00000000000000odpi-5.6.4/doc/src/_ext/parameters_table.py000066400000000000000000000042651510466437300206600ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2023, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # parameters_table.py # # Defines a directive (parameters-table) that creates a table with a specific # configuration on top of the extended "list-table-with-summary" directive. #------------------------------------------------------------------------------ from docutils.statemachine import ViewList import table_with_summary class ParametersTable(table_with_summary.ListTableWithSummary): def run(self): self.options["summary"] = \ "The first column displays the name of the parameter. The " \ "second column displays the parameter's mode. The third column " \ "displays the description of the parameter." self.options["header-rows"] = 1 self.options["class"] = ["wy-table-responsive"] self.options["widths"] = [10, 5, 35] headings = ViewList(['* - Parameter', ' - Mode', ' - Description']) self.content = headings + self.content return super().run() def setup(app): app.add_directive('parameters-table', ParametersTable) odpi-5.6.4/doc/src/_ext/table_with_summary.py000066400000000000000000000070121510466437300212360ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # table_with_summary.py # # Defines a directive (list-table-with-summary) that adds support for a summary # option on top of the regular "list-table" directive. #------------------------------------------------------------------------------ import sphinx from docutils.parsers.rst import directives from docutils.parsers.rst.directives import tables from packaging import version class ListTableWithSummary(tables.ListTable): option_spec = {'summary': directives.unchanged} option_spec.update(tables.ListTable.option_spec) def run(self): result = super().run() summary = self.options.get('summary') if summary: table_node = result[0] table_node["summary"] = summary return result class HTMLTranslator(sphinx.writers.html5.HTML5Translator): def visit_paragraph(self, node): children = node.children if len(children) == 1 and children[0].astext() == "No relevant notes": atts = {"style": "clip: rect(1px, 1px, 1px, 1px);" "clip-path: inset(50%);" "height: 1px;" "overflow: hidden;" "position: absolute;" "white-space: nowrap;" "width: 1px;" } self.body.append(self.starttag(node, 'p', '', **atts)) else: super().visit_paragraph(node) def visit_table(self, node): if version.parse(sphinx.__version__) > version.parse('4.2.0'): self._table_row_indices = [0] else: self._table_row_index = 0 atts = {} classes = [cls.strip(' \t\n') \ for cls in self.settings.table_style.split(',')] classes.insert(0, "docutils") # compat # set align-default if align not specified to give a default style classes.append('align-%s' % node.get('align', 'default')) if 'width' in node: atts['style'] = 'width: %s' % node['width'] if 'summary' in node: atts['summary'] = node['summary'] tag = self.starttag(node, 'table', CLASS=' '.join(classes), **atts) self.body.append(tag) def setup(app): app.add_directive('list-table-with-summary', ListTableWithSummary) app.set_translator("html", HTMLTranslator, override=True) odpi-5.6.4/doc/src/conf.py000077500000000000000000000066011510466437300153330ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- #------------------------------------------------------------------------------ # Copyright (c) 2016, 2025, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #------------------------------------------------------------------------------ import os import sys # If your extensions are in another directory, add it here. sys.path.append(os.path.abspath("_ext")) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ["table_with_summary", "parameters_table", 'sphinx_rtd_theme'] # the location of templates that are being used, relative to this directory templates_path = ['.templates'] # the suffix used for all source files source_suffix = '.rst' # the name of the root document root_doc = master_doc = 'index' # general information about the project project = 'ODPI-C' copyright = '2016, 2025, Oracle and/or its affiliates. All rights reserved.' author = 'Oracle' # the version info for the project, acts as replacement for |version| and # |release|, also used in various other places throughout the built documents # # the short X.Y version version = '5.6' # the full version, including alpha/beta/rc tags release = '5.6.4' # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # Options for HTML output # ----------------------- # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. # html_style = 'default.css' # The theme to use for readthedocs. html_theme = 'sphinx_rtd_theme' # the name for this set of documents. html_title = 'ODPI-C v' + release # the location for static files (such as style sheets) relative to this # directory; these are copied after the builtin static files and will overwrite # them html_static_path = ['.static'] # the location of the favicon to use for all pages # html_favicon = "_themes/oracle/static/favicon.ico" # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, the reST sources are included in the HTML build as _sources/. html_copy_source = False # Output file base name for HTML help builder. htmlhelp_basename = 'oracledbdoc' numfig = True # default domain is C primary_domain = "c" # Display tables with no horizontal scrollbar def setup(app): app.add_css_file('custom.css') odpi-5.6.4/doc/src/enums/000077500000000000000000000000001510466437300151555ustar00rootroot00000000000000odpi-5.6.4/doc/src/enums/dpiAuthMode.rst000066400000000000000000000031351510466437300201140ustar00rootroot00000000000000.. _dpiAuthMode: ODPI-C Enumeration dpiAuthMode ------------------------------ This enumeration identifies the mode to use when authorizing connections to the database. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiAuthMode enumeration. The second column displays the description of the dpiAuthMode enumeration value. * - Value - Description * - DPI_MODE_AUTH_DEFAULT - Default value used when creating connections. * - DPI_MODE_AUTH_PRELIM - Used together with DPI_MODE_AUTH_SYSDBA or DPI_MODE_AUTH_SYSOPER to authenticate for certain administrative tasks (such as starting up or shutting down the database). * - DPI_MODE_AUTH_SYSASM - Authenticates with SYSASM access. The use of this value requires Oracle Client 12.1 or higher. * - DPI_MODE_AUTH_SYSBKP - Authenticates with SYSBACKUP access. The use of this value requires Oracle Client 12.1 or higher. * - DPI_MODE_AUTH_SYSDBA - Authenticates with SYSDBA access. * - DPI_MODE_AUTH_SYSDGD - Authenticates with SYSDG access. The use of this value requires Oracle Client 12.1 or higher. * - DPI_MODE_AUTH_SYSKMT - Authenticates with SYSKM access. The use of this value requires Oracle Client 12.1 or higher. * - DPI_MODE_AUTH_SYSOPER - Authenticates with SYSOPER access. * - DPI_MODE_AUTH_SYSRAC - Authenticates with SYSRAC access. The use of this value requires Oracle Client 12.2 or higher. odpi-5.6.4/doc/src/enums/dpiConnCloseMode.rst000066400000000000000000000017031510466437300210750ustar00rootroot00000000000000.. _dpiConnCloseMode: ODPI-C Enumeration dpiConnCloseMode ----------------------------------- This enumeration identifies the mode to use when closing connections to the database. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiConnCloseMode enumeration. The second column displays the description of the dpiConnCloseMode enumeration value. * - Value - Description * - DPI_MODE_CONN_CLOSE_DEFAULT - Default value used when closing connections. * - DPI_MODE_CONN_CLOSE_DROP - Causes the session to be dropped from the session pool instead of simply returned to the pool for future use. * - DPI_MODE_CONN_CLOSE_RETAG - Causes the session to be tagged with the tag information given when the connection is closed. A value of NULL for the tag will cause the tag to be cleared. odpi-5.6.4/doc/src/enums/dpiCreateMode.rst000066400000000000000000000020071510466437300204130ustar00rootroot00000000000000.. _dpiCreateMode: ODPI-C Enumeration dpiCreateMode -------------------------------- This enumeration identifies the mode to use when creating connections to the database. Note that the OCI objects mode is always enabled. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiCreateMode enumeration. The second column displays the description of the dpiCreateMode enumeration value. * - Value - Description * - DPI_MODE_CREATE_DEFAULT - Default value used when creating connections. * - DPI_MODE_CREATE_EVENTS - Enables events mode which is required for the use of advanced queuing (AQ) and continuous query notification (CQN). * - DPI_MODE_CREATE_THREADED - Enables threaded mode. Internal OCI structures not exposed to the user are protected from concurrent access by multiple threads. Error information is also managed in thread local storage. odpi-5.6.4/doc/src/enums/dpiDeqMode.rst000066400000000000000000000021201510466437300177150ustar00rootroot00000000000000.. _dpiDeqMode: ODPI-C Enumeration dpiDeqMode ----------------------------- This enumeration identifies the modes that are possible when dequeuing messages from a queue. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiDeqMode enumeration. The second column displays the description of the dpiDeqMode enumeration value. * - Value - Description * - DPI_MODE_DEQ_BROWSE - Read the message without acquiring a lock on the message (equivalent to a SELECT statement). * - DPI_MODE_DEQ_LOCKED - Read the message and obtain a write lock on the message (equivalent to a SELECT FOR UPDATE statement). * - DPI_MODE_DEQ_REMOVE - Read the message and update or delete it. This is the default mode. Note that the message may be retained in the queue table based on retention properties. * - DPI_MODE_DEQ_REMOVE_NO_DATA - Confirms receipt of the message but does not deliver the actual message content. odpi-5.6.4/doc/src/enums/dpiDeqNavigation.rst000066400000000000000000000021141510466437300211330ustar00rootroot00000000000000.. _dpiDeqNavigation: ODPI-C Enumeration dpiDeqNavigation ----------------------------------- This enumeration identifies the method used for determining which message is to be dequeued from a queue. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiDeqNavigation enumeration. The second column displays the description of the dpiDeqNavigation enumeration value. * - Value - Description * - DPI_DEQ_NAV_FIRST_MSG - Retrieves the first available message that matches the search criteria. This resets the position to the beginning of the queue. * - DPI_DEQ_NAV_NEXT_MSG - Retrieves the next available message that matches the search criteria. This is the default method. * - DPI_DEQ_NAV_NEXT_TRANSACTION - Skips the remainder of the current transaction group (if any) and retrieves the first message of the next transaction group. This option can only be used if message grouping is enabled for the queue. odpi-5.6.4/doc/src/enums/dpiEventType.rst000066400000000000000000000024361510466437300203340ustar00rootroot00000000000000.. _dpiEventType: ODPI-C Enumeration dpiEventType ------------------------------- This enumeration identifies the types of events that can take place. The event type is part of the messages that are sent to subscriptions. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiEventType enumeration. The second column displays the description of the dpiEventType enumeration value. * - Value - Description * - DPI_EVENT_AQ - Indicates that a queue has messages available to dequeue. * - DPI_EVENT_DEREG - Indicates that a subscription is no longer registered with the database and will no longer generate events. * - DPI_EVENT_NONE - Indicates that no event has taken place. * - DPI_EVENT_OBJCHANGE - Indicates that an object change has taken place. * - DPI_EVENT_QUERYCHANGE - Indicates that a query change has taken place. * - DPI_EVENT_SHUTDOWN - Indicates that a database is being shut down. * - DPI_EVENT_SHUTDOWN_ANY - Indicates that an instance of Oracle Real Application Clusters (RAC) is being shut down. * - DPI_EVENT_STARTUP - Indicates that a database is being started up. odpi-5.6.4/doc/src/enums/dpiExecMode.rst000066400000000000000000000034121510466437300200750ustar00rootroot00000000000000.. _dpiExecMode: ODPI-C Enumeration dpiExecMode ------------------------------ This enumeration identifies the available modes for executing statements using :func:`dpiStmt_execute()` and :func:`dpiStmt_executeMany()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiExecMode enumeration. The second column displays the description of the dpiExecMode enumeration value. * - Value - Description * - DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS - Enable getting row counts for each DML operation when performing an array DML execution. The actual row counts can be retrieved using the function :func:`dpiStmt_getRowCounts()`. * - DPI_MODE_EXEC_BATCH_ERRORS - Enable batch error mode. This permits an an array DML operation to succeed even if some of the individual operations fail. The errors can be retrieved using the function :func:`dpiStmt_getBatchErrors()`. * - DPI_MODE_EXEC_COMMIT_ON_SUCCESS - If execution completes successfully, the current active transaction is committed. * - DPI_MODE_EXEC_DEFAULT - Default mode for execution. Metadata is made available after queries are executed. * - DPI_MODE_EXEC_DESCRIBE_ONLY - Do not execute the statement but simply acquire the metadata for the query. * - DPI_MODE_EXEC_PARSE_ONLY - Do not execute the statement but only parse it and return any parse errors. Note that using this mode with a DDL statement will result in the statement being executed. * - DPI_MODE_EXEC_SUSPEND_ON_SUCCESS - Suspends the active sessionless transaction once the execution completes successfully. odpi-5.6.4/doc/src/enums/dpiFetchMode.rst000066400000000000000000000027401510466437300202450ustar00rootroot00000000000000.. _dpiFetchMode: ODPI-C Enumeration dpiFetchMode ------------------------------- This enumeration identifies the mode to use when scrolling the cursor to a new location using the function :func:`dpiStmt_scroll()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiFetchMode enumeration. The second column displays the description of the dpiFetchMode enumeration value. * - Value - Description * - DPI_MODE_FETCH_ABSOLUTE - Scroll the cursor to the row identified by the offset parameter using absolute positioning. * - DPI_MODE_FETCH_FIRST - Scroll the cursor to the first row in the result set. The offset is ignored when using this mode. * - DPI_MODE_FETCH_LAST - Scroll the cursor to the last row in the result set. The offset is ignored when using this mode. * - DPI_MODE_FETCH_NEXT - Scroll the cursor to the next row in the result set. The offset is ignored when using this mode. * - DPI_MODE_FETCH_PRIOR - Scroll the cursor to the previous row in the result set. The offset is ignored when using this mode. * - DPI_MODE_FETCH_RELATIVE - Scroll the cursor to the row identified by the offset parameter using relative positioning. A positive number will move forward in the result set while a negative number will move backwards in the result set. odpi-5.6.4/doc/src/enums/dpiJsonOptions.rst000066400000000000000000000016361510466437300206770ustar00rootroot00000000000000.. _dpiJsonOptions: ODPI-C Enumeration dpiJsonOptions --------------------------------- This enumeration identifies the options that can be used when calling :func:`dpiJson_getValue()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiJsonOptions enumeration. The second column displays the description of the dpiJsonOptions enumeration value. * - Value - Description * - DPI_JSON_OPT_DATE_AS_DOUBLE - Convert values that are stored as Oracle dates and timestamps in the JSON value into double values (number of milliseconds since January 1, 1970). * - DPI_JSON_OPT_DEFAULT - Default value. * - DPI_JSON_OPT_NUMBER_AS_STRING - Convert values that are stored as Oracle numbers in the JSON value into strings in order to retain precision. odpi-5.6.4/doc/src/enums/dpiMessageDeliveryMode.rst000066400000000000000000000015571510466437300223110ustar00rootroot00000000000000.. _dpiMessageDeliveryMode: ODPI-C Enumeration dpiMessageDeliveryMode ----------------------------------------- This enumeration identifies the delivery mode used for filtering messages when dequeuing messages from a queue. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiMessageDeliveryMode enumeration. The second column displays the description of the dpiMessageDeliveryMode enumeration value. * - Value - Description * - DPI_MODE_MSG_BUFFERED - Dequeue only buffered messages from the queue. * - DPI_MODE_MSG_PERSISTENT - Dequeue only persistent messages from the queue. This is the default mode. * - DPI_MODE_MSG_PERSISTENT_OR_BUFFERED - Dequeue both persistent and buffered messages from the queue. odpi-5.6.4/doc/src/enums/dpiMessageState.rst000066400000000000000000000015221510466437300207710ustar00rootroot00000000000000.. _dpiMessageState: ODPI-C Enumeration dpiMessageState ---------------------------------- This enumeration identifies the possible states for messages in a queue. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :width: 100% :summary: The first column displays the value of the dpiMessageState enumeration. The second column displays the description of the dpiMessageState enumeration value. * - Value - Description * - DPI_MSG_STATE_EXPIRED - The message has been moved to the exception queue. * - DPI_MSG_STATE_PROCESSED - The message has already been processed and is retained. * - DPI_MSG_STATE_READY - The message is ready to be processed. * - DPI_MSG_STATE_WAITING - The message is waiting for the delay time to expire. odpi-5.6.4/doc/src/enums/dpiNativeTypeNum.rst000066400000000000000000000055141510466437300211610ustar00rootroot00000000000000.. _dpiNativeTypeNum: ODPI-C Enumeration dpiNativeTypeNum ----------------------------------- This enumeration identifies the type of data that is being transferred to and from the database. It is used in the structures :ref:`dpiDataTypeInfo`, :ref:`dpiShardingKeyColumn` and :ref:`dpiJsonNode`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiNativeTypeNum enumeration. The second column displays the description of the dpiNativeTypeNum enumeration value. * - Value - Description * - DPI_NATIVE_TYPE_BOOLEAN - Data is passed as a boolean value in :member:`dpiDataBuffer.asBoolean`. * - DPI_NATIVE_TYPE_BYTES - Data is passed as a byte string in :member:`dpiDataBuffer.asBytes`. * - DPI_NATIVE_TYPE_DOUBLE - Data is passed as a double precision floating point number in :member:`dpiDataBuffer.asDouble`. * - DPI_NATIVE_TYPE_FLOAT - Data is passed as a single precision floating point number in :member:`dpiDataBuffer.asFloat`. * - DPI_NATIVE_TYPE_INT64 - Data is passed as a 64-bit integer in :member:`dpiDataBuffer.asInt64`. * - DPI_NATIVE_TYPE_INTERVAL_DS - Data is passed as an interval (days to seconds) in :member:`dpiDataBuffer.asIntervalDS`. * - DPI_NATIVE_TYPE_INTERVAL_YM - Data is passed as an interval (years to months) in :member:`dpiDataBuffer.asIntervalYM`. * - DPI_NATIVE_TYPE_JSON - Data is passed as a JSON node in :member:`dpiDataBuffer.asJsonNode`. * - DPI_NATIVE_TYPE_JSON_ARRAY - Data is passed as a JSON array in :member:`dpiDataBuffer.asJsonArray`. * - DPI_NATIVE_TYPE_JSON_OBJECT - Data is passed as a JSON object in :member:`dpiDataBuffer.asJsonObject`. * - DPI_NATIVE_TYPE_LOB - Data is passed as a reference to a LOB in :member:`dpiDataBuffer.asLOB`. * - DPI_NATIVE_TYPE_NULL - No data is being passed. This is used to identify the JSON singleton null value. * - DPI_NATIVE_TYPE_OBJECT - Data is passed as a reference to an object in :member:`dpiDataBuffer.asObject`. * - DPI_NATIVE_TYPE_ROWID - Data is passed as a reference to a rowid in :member:`dpiDataBuffer.asRowid`. * - DPI_NATIVE_TYPE_STMT - Data is passed as a reference to a statement in :member:`dpiDataBuffer.asStmt`. * - DPI_NATIVE_TYPE_TIMESTAMP - Data is passed as a timestamp in :member:`dpiDataBuffer.asTimestamp`. * - DPI_NATIVE_TYPE_UINT64 - Data is passed as an unsigned 64-bit integer in :member:`dpiDataBuffer.asUint64`. * - DPI_NATIVE_TYPE_VECTOR - Data is passed as a reference to a vector in :member:`dpiDataBuffer.asVector`. odpi-5.6.4/doc/src/enums/dpiOpCode.rst000066400000000000000000000033021510466437300175530ustar00rootroot00000000000000.. _dpiOpCode: ODPI-C Enumeration dpiOpCode ---------------------------- This enumeration identifies the types of operations that can take place during object change and query change notification. It is used both as a filter when determining which operations to consider when sending notifications as well as identifying the operation that took place on a particular table or row when a notification is sent. Multiple values can be OR'ed together to specify multiple types of operations at the same time. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiOpCode enumeration. The second column displays the description of the dpiOpCode enumeration value. * - Value - Description * - DPI_OPCODE_ALL_OPS - Indicates that notifications should be sent for all operations on the table or query. * - DPI_OPCODE_ALL_ROWS - Indicates that all rows have been changed in the table or query (or too many rows were changed or row information was not requested). * - DPI_OPCODE_ALTER - Indicates that the registered table or query has been altered. * - DPI_OPCODE_DELETE - Indicates that a delete operation has taken place in the table or query. * - DPI_OPCODE_DROP - Indicates that the registered table or query has been dropped. * - DPI_OPCODE_INSERT - Indicates that an insert operation has taken place in the table or query. * - DPI_OPCODE_UPDATE - Indicates that an update operation has taken place in the table or query. * - DPI_OPCODE_UNKNOWN - An unknown operation has taken place. odpi-5.6.4/doc/src/enums/dpiOracleTypeNum.rst000066400000000000000000000164761510466437300211510ustar00rootroot00000000000000.. _dpiOracleTypeNum: ODPI-C Enumeration dpiOracleTypeNum ----------------------------------- This enumeration identifies the types of Oracle data that can be used for binding data as arguments to a statement, fetching data from the database, or getting and setting object attributes and element values. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiOracleTypeNum enumeration. The second column displays the description of the dpiOracleTypeNum enumeration value. * - Value - Description * - DPI_ORACLE_TYPE_BFILE - Default type used for BFILE columns in the database. Only a locator is transferred to/from Oracle, which can subsequently be used via dpiLob references to read/write from that locator. * - DPI_ORACLE_TYPE_BLOB - Default type used for BLOB columns in the database. Only a locator is transferred to/from Oracle, which can subsequently be used via dpiLob references to read/write from that locator. * - DPI_ORACLE_TYPE_BOOLEAN - Used within PL/SQL for boolean values. This is only available in 12.1. Earlier releases simply use the integer values 0 and 1 to represent a boolean value. Data is transferred to/from Oracle as an integer. * - DPI_ORACLE_TYPE_CHAR - Default type used for CHAR columns in the database. Data is transferred to/from Oracle as byte strings in the encoding used for CHAR data. * - DPI_ORACLE_TYPE_CLOB - Default type used for CLOB columns in the database. Only a locator is transferred to/from Oracle, which can subsequently be used via dpiLob references to read/write from that locator. * - DPI_ORACLE_TYPE_DATE - Default type used for DATE columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_INTERVAL_DS - Default type used for INTERVAL DAY TO SECOND columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_INTERVAL_YM - Default type used for INTERVAL YEAR TO MONTH columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_JSON - Default type used for JSON columns in the database (available in Oracle Database 20 and higher). Data is transferred to/from Oracle using the structure :ref:`dpiJsonNode `. * - DPI_ORACLE_TYPE_JSON_ARRAY - Type used for identifying nodes that are JSON arrays. Data is transferred to/from Oracle using the structure :ref:`dpiJsonArray `. * - DPI_ORACLE_TYPE_JSON_ID - Type used for identifying nodes that are JSON IDs. Data is transferred to/from Oracle as raw byte strings. * - DPI_ORACLE_TYPE_JSON_OBJECT - Type used for identifying nodes that are JSON objects. Data is transferred to/from Oracle using the structure :ref:`dpiJsonObject `. * - DPI_ORACLE_TYPE_LONG_NVARCHAR - This value cannot be represented in an Oracle database but is used when fetching NCLOB data as a string. Data is transferred to/from Oracle as byte strings in the encoding used for NCHAR data. * - DPI_ORACLE_TYPE_LONG_RAW - Default type used for LONG RAW columns in the database. Data is transferred to/from Oracle as raw byte strings. * - DPI_ORACLE_TYPE_LONG_VARCHAR - Default type used for LONG columns in the database. Data is transferred to/from Oracle as byte strings in the encoding used for CHAR data. * - DPI_ORACLE_TYPE_NATIVE_DOUBLE - Default type used for BINARY_DOUBLE columns in the database. Data is transferred to/from Oracle as the C double type. * - DPI_ORACLE_TYPE_NATIVE_FLOAT - Default type used for BINARY_FLOAT columns in the database. Data is transferred to/from Oracle as the C float type. * - DPI_ORACLE_TYPE_NATIVE_INT - Type available for binding native integers directly in PL/SQL (such as PLS_INTEGER). Data is transferred to/from Oracle as 64-bit integers. * - DPI_ORACLE_TYPE_NATIVE_UINT - Type available for binding native integers directly in PL/SQL (such as PLS_INTEGER). Data is transferred to/from Oracle as 64-bit unsigned integers. * - DPI_ORACLE_TYPE_NCHAR - Default type used for NCHAR columns in the database. Data is transferred to/from Oracle as byte strings in the encoding used for NCHAR data. * - DPI_ORACLE_TYPE_NCLOB - Default type used for NCLOB columns in the database. Only a locator is transferred to/from Oracle, which can subsequently be used via dpiLob references to read/write from that locator. * - DPI_ORACLE_TYPE_NUMBER - Default type used for NUMBER columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_NVARCHAR - Default type used for NVARCHAR2 columns in the database. Data is transferred to/from Oracle as byte strings in the encoding used for NCHAR data. * - DPI_ORACLE_TYPE_OBJECT - Default type used for named type columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_RAW - Default type used for RAW columns in the database. Data is transferred to/from Oracle as raw byte strings. * - DPI_ORACLE_TYPE_ROWID - Default type used for the pseudocolumn "ROWID". Data is transferred to/from Oracle as byte strings, in the encoding used for CHAR data. * - DPI_ORACLE_TYPE_STMT - Used within PL/SQL for REF CURSOR or within SQL for querying a CURSOR. Only a handle is transferred to/from Oracle, which can subsequently be used via dpiStmt for querying. * - DPI_ORACLE_TYPE_TIMESTAMP - Default type used for TIMESTAMP columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_TIMESTAMP_LTZ - Default type used for TIMESTAMP WITH LOCAL TIME ZONE columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_TIMESTAMP_TZ - Default type used for TIMESTAMP WITH TIME ZONE columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_UROWID - This value is currently a synonym for DPI_ORACLE_TYPE_ROWID. It is intended to be the default type for UROWID columns in the database when it is possible to distinguish betweeen ROWID and UROWID. Data is transferred to/from Oracle as byte strings, in the encoding used for CHAR data. * - DPI_ORACLE_TYPE_VARCHAR - Default type used for VARCHAR2 columns in the database. Data is transferred to/from Oracle as byte strings in the encoding used for CHAR data. * - DPI_ORACLE_TYPE_VECTOR - Default type used for VECTOR columns in the database. Data is transferred to/from Oracle in Oracle's internal format. * - DPI_ORACLE_TYPE_XMLTYPE - Default type used for SYS.XMLTYPE columns in the database. Data is transferred to/from Oracle as byte strings in the encoding used for CHAR data. odpi-5.6.4/doc/src/enums/dpiPoolCloseMode.rst000066400000000000000000000014201510466437300211050ustar00rootroot00000000000000.. _dpiPoolCloseMode: ODPI-C Enumeration dpiPoolCloseMode ----------------------------------- This enumeration identifies the mode to use when closing pools. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiPoolCloseMode enumeration. The second column displays the description of the dpiPoolCloseMode enumeration value. * - Value - Description * - DPI_MODE_POOL_CLOSE_DEFAULT - Default value used when closing pools. If there are any active sessions in the pool an error will be raised. * - DPI_MODE_POOL_CLOSE_FORCE - Causes all of the active connections in the pool to be closed before closing the pool itself. odpi-5.6.4/doc/src/enums/dpiPoolGetMode.rst000066400000000000000000000026621510466437300205700ustar00rootroot00000000000000.. _dpiPoolGetMode: ODPI-C Enumeration dpiPoolGetMode --------------------------------- This enumeration identifies the mode to use when getting sessions from a session pool. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiPoolGetMode enumeration. The second column displays the description of the dpiPoolGetMode enumeration value. * - Value - Description * - DPI_MODE_POOL_GET_FORCEGET - Specifies that a new session should be created if all of the sessions in the pool are busy, even if this exceeds the maximum sessions allowable for the session pool (see :member:`dpiPoolCreateParams.maxSessions`). * - DPI_MODE_POOL_GET_NOWAIT - Specifies that the caller should return immediately, regardless of whether a session is available in the pool. If a session is not available an error is returned. * - DPI_MODE_POOL_GET_TIMEDWAIT - Specifies that the caller should block until a session is available from the pool, but only for the specified length of time defined in :member:`dpiPoolCreateParams.waitTimeout`. If a session is not available within the specified period of time an error is returned. * - DPI_MODE_POOL_GET_WAIT - Specifies that the caller should block until a session is available from the pool. odpi-5.6.4/doc/src/enums/dpiPurity.rst000066400000000000000000000014371510466437300177050ustar00rootroot00000000000000.. _dpiPurity: ODPI-C Enumeration dpiPurity ---------------------------- This enumeration identifies the purity of the sessions that are acquired when using connection classes during connection creation. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiPurity enumeration. The second column displays the description of the dpiPurity enumeration value. * - Value - Description * - DPI_PURITY_DEFAULT - Default value used when creating connections. * - DPI_PURITY_NEW - A connection is required that has not been tainted with any prior session state. * - DPI_PURITY_SELF - A connection is permitted to have prior session state. odpi-5.6.4/doc/src/enums/dpiServerType.rst000066400000000000000000000016511510466437300205170ustar00rootroot00000000000000.. _dpiServerType: ODPI-C Enumeration dpiServerType -------------------------------- This enumeration identifies the type of server process associated with a connection. It is only available with Oracle Client libraries 23.4 or higher. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiServerType enumeration. The second column displays the description of the dpiServerType enumeration value. * - Value - Description * - DPI_SERVER_TYPE_DEDICATED - A dedicated server process is being used with the connection. * - DPI_SERVER_TYPE_POOLED - A pooled server process (DRCP) is being used with the connection. * - DPI_SERVER_TYPE_SHARED - A shared server process is being used with the connection. * - DPI_SERVER_TYPE_UNKNOWN - The type of server process is unknown. odpi-5.6.4/doc/src/enums/dpiShutdownMode.rst000066400000000000000000000031261510466437300210260ustar00rootroot00000000000000.. _dpiShutdownMode: ODPI-C Enumeration dpiShutdownMode ---------------------------------- This enumeration identifies the mode to use when shutting down a database using :func:`dpiConn_shutdownDatabase()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 10 35 :summary: The first column displays the value of the dpiShutdownMode enumeration. The second column displays the description of the dpiShutdownMode enumeration value. * - Value - Description * - DPI_MODE_SHUTDOWN_ABORT - All uncommitted transactions are terminated and are not rolled back. This is the fastest way to shut down the database but the next database startup may require instance recovery. * - DPI_MODE_SHUTDOWN_DEFAULT - Further connections to the database are prohibited. Wait for users to disconnect from the database. * - DPI_MODE_SHUTDOWN_FINAL - Shuts down the database. This mode should only be used in the second call to :func:`dpiConn_shutdownDatabase()`. * - DPI_MODE_SHUTDOWN_IMMEDIATE - All uncommitted transactions are terminated and rolled back and all connections to the database are closed immediately. * - DPI_MODE_SHUTDOWN_TRANSACTIONAL - Further connections to the database are prohibited and no new transactions are allowed to be started. Wait for active transactions to complete. * - DPI_MODE_SHUTDOWN_TRANSACTIONAL_LOCAL - Behaves the same way as DPI_MODE_SHUTDOWN_TRANSACTIONAL but only waits for local transactions to complete. odpi-5.6.4/doc/src/enums/dpiSodaFlags.rst000066400000000000000000000020751510466437300202530ustar00rootroot00000000000000.. _dpiSodaFlags: ODPI-C Enumeration dpiSodaFlags ------------------------------- This enumeration identifies the flags that can be used with SODA functions. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiSodaFlags enumeration. The second column displays the description of the dpiSodaFlags enumeration value. * - Value - Description * - DPI_SODA_FLAGS_ATOMIC_COMMIT - If the function completes successfully the current transaction is committed. If it does not complete successfully, no changes to the database are made and the existing transaction is left untouched. * - DPI_SODA_FLAGS_CREATE_COLL_MAP - Create collection in MAP mode. This mode is only supported in :func:`dpiSodaDb_createCollection()`. * - DPI_SODA_FLAGS_DEFAULT - Default value. * - DPI_SODA_FLAGS_INDEX_DROP_FORCE - Forcibly drop the index. This mode is only supported in :func:`dpiSodaColl_dropIndex()`. odpi-5.6.4/doc/src/enums/dpiStartupMode.rst000066400000000000000000000017141510466437300206560ustar00rootroot00000000000000.. _dpiStartupMode: ODPI-C Enumeration dpiStartupMode --------------------------------- This enumeration identifies the mode to use when starting up a database using :func:`dpiConn_startupDatabase()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiStartupMode enumeration. The second column displays the description of the dpiStartupMode enumeration value. * - Value - Description * - DPI_MODE_STARTUP_DEFAULT - Default mode for startup which permits database access to all users. * - DPI_MODE_STARTUP_FORCE - Shuts down a running instance (using ABORT) before starting a new one. This mode should only be used in unusual circumstances. * - DPI_MODE_STARTUP_RESTRICT - Only allows database access to users with both the CREATE SESSION and RESTRICTED SESSION privileges (normally the DBA). odpi-5.6.4/doc/src/enums/dpiStatementType.rst000066400000000000000000000047341510466437300212220ustar00rootroot00000000000000.. _dpiStatementType: ODPI-C Enumeration dpiStatementType ----------------------------------- This enumeration identifies the type of statement that has been prepared. It is available as part of the structure :ref:`dpiStmtInfo`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiStatementType enumeration. The second column displays the description of the dpiStatementType enumeration value. * - Value - Description * - DPI_STMT_TYPE_ALTER - Identifies an alter statement. The member :member:`dpiStmtInfo.isDDL` will be set to 1. * - DPI_STMT_TYPE_BEGIN - Identifies an anonymous PL/SQL block starting with the keyword begin. The member :member:`dpiStmtInfo.isPLSQL` will be set to 1. * - DPI_STMT_TYPE_CALL - Identifies a CALL statement used for calling stored procedures and functions. The member :member:`dpiStmtInfo.isPLSQL` will be set to 1. * - DPI_STMT_TYPE_COMMIT - Identifies a commit statement. * - DPI_STMT_TYPE_CREATE - Identifies a create statement. The member :member:`dpiStmtInfo.isDDL` will be set to 1. * - DPI_STMT_TYPE_DECLARE - Identifies an anonymous PL/SQL block starting with the keyword declare. The member :member:`dpiStmtInfo.isPLSQL` will be set to 1. * - DPI_STMT_TYPE_DELETE - Identifies a delete statement. The member :member:`dpiStmtInfo.isDML` will be set to 1. * - DPI_STMT_TYPE_DROP - Identifies a drop statement. The member :member:`dpiStmtInfo.isDDL` will be set to 1. * - DPI_STMT_TYPE_EXPLAIN_PLAN - Identifies an explain plan statement. The member :member:`dpiStmtInfo.isDML` will be set to 1. * - DPI_STMT_TYPE_INSERT - Identifies an insert statement. The member :member:`dpiStmtInfo.isDML` will be set to 1. * - DPI_STMT_TYPE_MERGE - Identifies a merge statement. The member :member:`dpiStmtInfo.isDML` will be set to 1. * - DPI_STMT_TYPE_ROLLBACK - Identifies a rollback statement. * - DPI_STMT_TYPE_SELECT - Identifies a select statement. The member :member:`dpiStmtInfo.isQuery` will be set to 1. * - DPI_STMT_TYPE_UPDATE - Identifies an update statement. The member :member:`dpiStmtInfo.isDML` will be set to 1. * - DPI_STMT_TYPE_UNKNOWN - Indicates that the statement type is unknown. odpi-5.6.4/doc/src/enums/dpiSubscrGroupingClass.rst000066400000000000000000000014641510466437300223530ustar00rootroot00000000000000.. _dpiSubscrGroupingClass: ODPI-C Enumeration dpiSubscrGroupingClass ----------------------------------------- This enumeration identifies the grouping class. Instead of individual events being delivered to the callback, events are grouped before being sent to the callback. This enumeration is used in the :ref:`dpiSubscrCreateParams` structure. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiSubscrGroupingClass enumeration. The second column displays the description of the dpiSubscrGroupingClass enumeration value. * - Value - Description * - DPI_SUBSCR_GROUPING_CLASS_TIME - Events are grouped by the period of time in which they are received. odpi-5.6.4/doc/src/enums/dpiSubscrGroupingType.rst000066400000000000000000000014221510466437300222210ustar00rootroot00000000000000.. _dpiSubscrGroupingType: ODPI-C Enumeration dpiSubscrGroupingType ---------------------------------------- This enumeration identifies the grouping type. It is used in the :ref:`dpiSubscrCreateParams` structure. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiSubscrGroupingType enumeration. The second column displays the description of the dpiSubscrGroupingType enumeration value. * - Value - Description * - DPI_SUBSCR_GROUPING_TYPE_LAST - The last event in the group is sent. * - DPI_SUBSCR_GROUPING_TYPE_SUMMARY - A summary of all events in the group is sent. This is also the default value. odpi-5.6.4/doc/src/enums/dpiSubscrNamespace.rst000066400000000000000000000015051510466437300214630ustar00rootroot00000000000000.. _dpiSubscrNamespace: ODPI-C Enumeration dpiSubscrNamespace ------------------------------------- This enumeration identifies the namespaces supported by subscriptions. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiSubscrNamespace enumeration. The second column displays the description of the dpiSubscrNamespace enumeration value. * - Value - Description * - DPI_SUBSCR_NAMESPACE_AQ - Identifies the namespace used for receiving notifications when messages are available to be dequeued in advanced queueing (AQ). * - DPI_SUBSCR_NAMESPACE_DBCHANGE - Identifies the namespace used for receiving notifications for database object changes and query changes (CQN). odpi-5.6.4/doc/src/enums/dpiSubscrProtocol.rst000066400000000000000000000021051510466437300213650ustar00rootroot00000000000000.. _dpiSubscrProtocol: ODPI-C Enumeration dpiSubscrProtocol ------------------------------------ This enumeration identifies the protocol used for sending notifications to subscriptions. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiSubscrProtocol enumeration. The second column displays the description of the dpiSubscrProtocol enumeration value. * - Value - Description * - DPI_SUBSCR_PROTO_CALLBACK - Notifications are sent by calling the callback specified when the subscription was registered. * - DPI_SUBSCR_PROTO_HTTP - Notifications are sent to the URL specified when the subscription was registered. * - DPI_SUBSCR_PROTO_MAIL - Notifications are sent by sending an e-mail to the e-mail address specified when the subscription was registered. * - DPI_SUBSCR_PROTO_PLSQL - Notifications are sent by calling the PL/SQL procedure specified when the subscription was registered. odpi-5.6.4/doc/src/enums/dpiSubscrQOS.rst000066400000000000000000000026671510466437300202430ustar00rootroot00000000000000.. _dpiSubscrQOS: ODPI-C Enumeration dpiSubscrQOS ------------------------------- This enumeration identifies the quality of service flags for sending notifications to subscriptions. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiSubscrQOS enumeration. The second column displays the description of the dpiSubscrQOS enumeration value. * - Value - Description * - DPI_SUBSCR_QOS_BEST_EFFORT - Perform query notification in best effort mode which may result in notifications being sent when the query has not in fact changed. This is needed for complex queries that cannot be registered in guaranteed mode. * - DPI_SUBSCR_QOS_DEREG_NFY - When the notification has been received, the subscription is removed. * - DPI_SUBSCR_QOS_QUERY - Perform query notification instead of database change notification. Notification is done in guaranteed mode which guarantees that the query has in fact changed. * - DPI_SUBSCR_QOS_RELIABLE - Notifications are sent reliably. If the database fails, the notifications are not lost. This is not supported for nonpersistent queues or buffered messaging. * - DPI_SUBSCR_QOS_ROWIDS - Information on the rows affected by the database or query change is sent along with the notification. odpi-5.6.4/doc/src/enums/dpiTpcBeginFlags.rst000066400000000000000000000015061510466437300210560ustar00rootroot00000000000000.. _dpiTpcBeginFlags: ODPI-C Enumeration dpiTpcBeginFlags ----------------------------------- This enumeration identifies the flags that can be used when calling :func:`dpiConn_tpcBegin()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :width: 100% :summary: The first column displays the value of the dpiTpcBeginFlags enumeration. The second column displays the description of the dpiTpcBeginFlags enumeration value. * - Value - Description * - DPI_TPC_BEGIN_JOIN - Joins an existing global transaction. * - DPI_TPC_BEGIN_NEW - Creates a new global transaction. * - DPI_TPC_BEGIN_PROMOTE - Promotes a local transaction to a global transaction. * - DPI_TPC_BEGIN_RESUME - Resumes an existing global transaction. odpi-5.6.4/doc/src/enums/dpiTpcEndFlags.rst000066400000000000000000000012561510466437300205420ustar00rootroot00000000000000.. _dpiTpcEndFlags: ODPI-C Enumeration dpiTpcEndFlags --------------------------------- This enumeration identifies the flags that can be used when calling :func:`dpiConn_tpcEnd()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :width: 100% :summary: The first column displays the value of the dpiTpcEndFlags enumeration. The second column displays the description of the dpiTpcEndFlags enumeration value. * - Value - Description * - DPI_TPC_END_NORMAL - Normal ending of the transaction. * - DPI_TPC_END_SUSPEND - Transaction is suspended and may be resumed at some later point. odpi-5.6.4/doc/src/enums/dpiVectorFlags.rst000066400000000000000000000012511510466437300206220ustar00rootroot00000000000000.. _dpiVectorFlags: ODPI-C Enumeration dpiVectorFlags ---------------------------------- This enumeration identifies the possible values for :member:`dpiDataTypeInfo.vectorFlags`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiVectorFlags enumeration. The second column displays the description of the dpiVectorFlags enumeration value. * - Value - Description * - DPI_VECTOR_FLAGS_FLEXIBLE_DIM - The vector column uses a flexible number of dimensions. * - DPI_VECTOR_FLAGS_SPARSE - The vector column contains sparse vectors odpi-5.6.4/doc/src/enums/dpiVectorFormat.rst000066400000000000000000000017651510466437300210300ustar00rootroot00000000000000.. _dpiVectorFormat: ODPI-C Enumeration dpiVectorFormat ---------------------------------- This enumeration identifies the storage format for a vector's dimensions. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiVectorFormat enumeration. The second column displays the description of the dpiVectorFormat enumeration value. * - Value - Description * - DPI_VECTOR_FORMAT_BINARY - The vector dimension storage format is single bits, represented in groups of 8 as single byte unsigned integers. * - DPI_VECTOR_FORMAT_FLOAT32 - The vector dimension storage format is single-precision floating point numbers. * - DPI_VECTOR_FORMAT_FLOAT64 - The vector dimension storage format is double-precision floating point numbers. * - DPI_VECTOR_FORMAT_INT8 - The vector dimension storage format is single byte signed integers. odpi-5.6.4/doc/src/enums/dpiVisibility.rst000066400000000000000000000013461510466437300205370ustar00rootroot00000000000000.. _dpiVisibility: ODPI-C Enumeration dpiVisibility -------------------------------- This enumeration identifies the visibility of messages in advanced queuing. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 35 :summary: The first column displays the value of the dpiVisibility enumeration. The second column displays the description of the dpiVisibility enumeration value. * - Value - Description * - DPI_VISIBILITY_IMMEDIATE - The message is not part of the current transaction but constitutes a transaction of its own. * - DPI_VISIBILITY_ON_COMMIT - The message is part of the current transaction. This is the default value. odpi-5.6.4/doc/src/enums/index.rst000066400000000000000000000026611510466437300170230ustar00rootroot00000000000000******************* ODPI-C Enumerations ******************* This chapter details the enumerations available in the ODPI-C library. .. toctree:: :maxdepth: 1 :hidden: dpiAuthMode dpiConnCloseMode dpiCreateMode dpiDeqMode dpiDeqNavigation dpiEventType dpiExecMode dpiFetchMode dpiJsonOptions dpiMessageDeliveryMode dpiMessageState dpiNativeTypeNum dpiOpCode dpiOracleTypeNum dpiPoolCloseMode dpiPoolGetMode dpiPurity dpiServerType dpiShutdownMode dpiSodaFlags dpiStartupMode dpiStatementType dpiSubscrGroupingClass dpiSubscrGroupingType dpiSubscrNamespace dpiSubscrProtocol dpiSubscrQOS dpiTpcBeginFlags dpiTpcEndFlags dpiVectorFlags dpiVectorFormat dpiVisibility odpi-5.6.4/doc/src/functions/000077500000000000000000000000001510466437300160365ustar00rootroot00000000000000odpi-5.6.4/doc/src/functions/dpiConn.rst000066400000000000000000002275411510466437300201750ustar00rootroot00000000000000.. _dpiConnFunctions: ODPI-C Connection Functions --------------------------- Connection handles are used to represent connections to the database. These can be standalone connections created by calling the function :func:`dpiConn_create()` or acquired from a session pool by calling the function :func:`dpiPool_acquireConnection()`. They can be closed by calling the function :func:`dpiConn_close()` or releasing the last reference to the connection by calling the function :func:`dpiConn_release()`. Connection handles are used to create all handles other than session pools and context handles. .. function:: int dpiConn_addRef(dpiConn* conn) Adds a reference to the connection. This is intended for situations where a reference to the connection needs to be maintained independently of the reference returned when the connection was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - The connection to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_beginSessionlessTransaction(dpiConn* conn, \ dpiSessionlessTransactionId* transactionId, uint32_t timeout, \ int deferRoundTrip) Begins a new sessionless transaction on the next server round-trip. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the sessionless transaction is to begin. If the reference is NULL or invalid, an error is returned. * - ``transactionId`` - IN/OUT - A unique identifier for the sessionless transaction. If the length of this parameter is zero, then the transactionId is assigned a random library-generated value. Both the length and value attributes of the transactionId are updated accordingly. * - ``timeout`` - IN - The duration in seconds that this transaction can be resumed after it is suspended. If the timeout expires and the transaction was not resumed, it will roll back. This value cannot be set to 0 and will remain unchanged until the transaction completes. * - ``deferRoundTrip`` - IN - Whether to defer a round trip to the server or not. If the value is true (non-zero) the next round trip to the server will send the request instead. .. function:: int dpiConn_breakExecution(dpiConn* conn) Performs an immediate (asynchronous) termination of any currently executing function on the server associated with the connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the break is to take place. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_changePassword(dpiConn* conn, \ const char* userName, uint32_t userNameLength, \ const char* oldPassword, uint32_t oldPasswordLength, \ const char* newPassword, uint32_t newPasswordLength) Changes the password of the specified user. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the password is to be changed. If the reference is NULL or invalid, an error is returned. * - ``userName`` - IN - The name of the user whose password is to be changed, as a byte string in the encoding used for CHAR data. * - ``userNameLength`` - IN - The length of the user name parameter, in bytes. * - ``oldPassword`` - IN - The old password of the user whose password is to be changed, as a byte string in the encoding used for CHAR data. * - ``oldPasswordLength`` - IN - The length of the old password parameter, in bytes. * - ``newPassword`` - IN - The new password of the user whose password is to be changed, as a byte string in the encoding used for CHAR data. * - ``newPasswordLength`` - IN - The length of the new password parameter, in bytes. .. function:: int dpiConn_close(dpiConn* conn, dpiConnCloseMode mode, \ const char* tag, uint32_t tagLength) Closes the connection and makes it unusable for further activity. Any open statements and LOBs associated with the connection will also be closed and made unusable for further activity. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection which is to be closed. If the reference is NULL or invalid, an error is returned. * - ``mode`` - IN - One or more of the values from the enumeration :ref:`dpiConnCloseMode`, OR'ed together. * - ``tag`` - IN - A byte string in the encoding used for CHAR data, indicating what tag should be set on the connection when it is released back to the pool. NULL is also acceptable when indicating that the tag should be cleared. This value is ignored unless the close mode includes the value DPI_MODE_CONN_CLOSE_RETAG. * - ``tagLength`` - IN - The length of the tag parameter, in bytes, or 0 if the tag parameter is NULL. .. function:: int dpiConn_commit(dpiConn* conn) Commits the current active transaction. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection which holds the transaction which is to be committed. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_create(const dpiContext* context, \ const char* userName, uint32_t userNameLength, \ const char* password, uint32_t passwordLength, \ const char* connectString, uint32_t connectStringLength, \ dpiCommonCreateParams* commonParams, \ dpiConnCreateParams* createParams, dpiConn** conn) Creates a standalone connection to a database or acquires a connection from a session pool and returns a reference to the connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. If a failure occurs, the errorInfo structure is filled in with error information. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``userName`` - IN - The name of the user used for authenticating the user, as a byte string in the encoding used for CHAR data. NULL is also acceptable if external authentication is being requested or if credentials were specified when the pool was created. * - ``userNameLength`` - IN - The length of the userName parameter, in bytes, or 0 if the userName parameter is NULL. * - ``password`` - IN - The password to use for authenticating the user, as a byte string in the encoding used for CHAR data. NULL is also acceptable if external authentication is being requested or if credentials were specified when the pool was created. * - ``passwordLength`` - IN - The length of the password parameter, in bytes, or 0 if the password parameter is NULL. * - ``connectString`` - IN - The connect string identifying the database to which a connection is to be established, as a byte string in the encoding used for CHAR data. NULL is also acceptable for local connections (identified by the environment variable $ORACLE_SID) or when a connection is being acquired from a session pool. This value is ignored when a connection is being acquired from a session pool. * - ``connectStringLength`` - IN - The length of the connectString parameter, in bytes, or 0 if the connectString parameter is NULL. * - ``commonParams`` - IN - A pointer to a :ref:`dpiCommonCreateParams` structure which is used to specify context parameters for connection creation. NULL is also acceptable in which case all default parameters will be used when creating the connection. This value is ignored when acquiring a connection from a session pool. * - ``createParams`` - IN - A pointer to a :ref:`dpiConnCreateParams` structure which is used to specify parameters for connection creation. NULL is also acceptable in which case all default parameters will be used when creating the connection. If the member :member:`~dpiConnCreateParams.pool` is not NULL, a connection will be acquired from the pool (as if the function :func:`dpiPool_acquireConnection()` had been called); otherwise, a standalone connection will be created. * - ``conn`` - OUT - A pointer to a reference to the connection that is created. Call :func:`dpiConn_release()` when the reference is no longer needed. .. function:: int dpiConn_deqObject(dpiConn* conn, const char* queueName, \ uint32_t queueNameLength, dpiDeqOptions* options, \ dpiMsgProps* props, dpiObject* payload, const char** msgId, \ uint32_t* msgIdLength) Dequeues a message from a queue. This function is deprecated and will be removed in version 4. One of the functions :func:`dpiQueue_deqOne()` or :func:`dpiQueue_deqMany()` should be used instead. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the message is to be dequeued. If the reference is NULL or invalid, an error is returned. * - ``queueName`` - IN - The name of the queue from which the message is to be dequeued, as a byte string in the encoding used for CHAR data. * - ``queueNameLength`` - IN - The length of the queueName parameter, in bytes. * - ``options`` - IN - A reference to the dequeue options that should be used when dequeuing the message from the queue. * - ``props`` - IN - A reference to the message properties that will be populated with information from the message that is dequeued. * - ``payload`` - IN - A reference to the object which will be populated with the message that is dequeued. * - ``msgId`` - OUT - A pointer to a byte string which will be populated with the id of the message that is dequeued, or NULL if no message is available. If there is a message id, the pointer will remain valid until the next call to :func:`dpiConn_enqObject()` or :func:`dpiConn_deqObject()`. * - ``msgIdLength`` - OUT - A pointer to the length of the msgId parameter, or 0 if the msgId parameter is NULL. .. function:: int dpiConn_enqObject(dpiConn* conn, const char* queueName, \ uint32_t queueNameLength, dpiEnqOptions* options, \ dpiMsgProps* props, dpiObject* payload, const char** msgId, \ uint32_t* msgIdLength) Enqueues a message to a queue. This function is deprecated and will be removed in version 4. One of the functions :func:`dpiQueue_enqOne()` or :func:`dpiQueue_enqMany()` should be used instead. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection to which the message is to be enqueued. If the reference is NULL or invalid, an error is returned. * - ``queueName`` - IN - The name of the queue to which the message is to be enqueued, as a byte string in the encoding used for CHAR data. * - ``queueNameLength`` - IN - The length of the queueName parameter, in bytes. * - ``options`` - IN - A reference to the enqueue options that should be used when enqueuing the message to the queue. * - ``props`` - IN - A reference to the message properties that will affect the message that is enqueued. * - ``payload`` - IN - a reference to the object which will be enqueued. * - ``msgId`` - OUT - A pointer to a byte string which will be populated with the id of the message that is enqueued upon successful completion of this function. The pointer will remain valid until the next call to :func:`dpiConn_enqObject()` or :func:`dpiConn_deqObject()`. * - ``msgIdLength`` - OUT - A pointer to the length of the msgId parameter which will be populated upon successful completion of this function. .. function:: int dpiConn_getCallTimeout(dpiConn* conn, uint32_t* value) Returns the current call timeout (in milliseconds) used for round-trips to the database made with this connection. A value of 0 means that no timeouts will take place. This value can be set using the function :func:`dpiConn_setCallTimeout()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the current call timeout is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the call timeout value, which will be populated upon successful completion of this function. .. function:: int dpiConn_getCurrentSchema(dpiConn* conn, \ const char** value, uint32_t* valueLength) Returns the current schema that is being used by the connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the current schema is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the current schema, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held and the current schema is not changed by some means. * - ``valueLength`` - OUT - A pointer to the length of the current schema, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getDbDomain(dpiConn* conn, \ const char** value, uint32_t* valueLength) Returns the Oracle Database Domain name associated with the connection. This is the same value returned by the SQL expression ``SELECT value FROM V$PARAMETER WHERE NAME = 'db_domain'``. This function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the database domain name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the database domain name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held. * - ``valueLength`` - OUT - A pointer to the length of the database domain name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getDbName(dpiConn* conn, const char** value, \ uint32_t* valueLength) Returns the Oracle Database name associated with the connection. This is the same value returned by the SQL expression ``SELECT NAME FROM V$DATABASE``. This function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the database name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the database name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held. * - ``valueLength`` - OUT - A pointer to the length of the database name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getEdition(dpiConn* conn, const char** value, \ uint32_t* valueLength) Returns the edition that is being used by the connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the edition is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the edition, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held and the edition is not changed by some means. * - ``valueLength`` - OUT - A pointer to the length of the edition, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getEncodingInfo(dpiConn* conn, \ dpiEncodingInfo* info) Returns the encoding information used by the connection. This will be equivalent to the values passed when the standalone connection or session pool was created, or the values retrieved from the environment variables NLS_LANG and NLS_NCHAR. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection whose encoding information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a :ref:`dpiEncodingInfo` structure which will be populated with the encoding information used by the connection. .. function:: int dpiConn_getExternalName(dpiConn* conn, \ const char** value, uint32_t* valueLength) Returns the external name that is being used by the connection. This value is used when logging distributed transactions. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the external name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the external name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held and the external name is not changed by some means. * - ``valueLength`` - OUT - A pointer to the length of the external name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getHandle(dpiConn* conn, void** handle) Returns the OCI service context handle in use by the connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection whose service context handle is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``handle`` - OUT - A pointer which will be populated with the service context handle of the connection upon successful completion of the function. This handle can be used within OCI calls independently of the library, but care must be taken not to cause problems due to shared use. .. function:: int dpiConn_getInfo(dpiConn* conn, dpiConnInfo* info) Returns information about the connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a structure of type :ref:`dpiConnInfo` which will be filled in with information about the connection upon successful completion of the function. The pointers in the structure will remain valid as long as the connection itself is open. When using a pooled server process, however, the information in the structure may become stale when a new session is associated with the connection. .. function:: int dpiConn_getInstanceName(dpiConn* conn, \ const char** value, uint32_t* valueLength) Returns the Oracle Database instance name associated with the connection. This is the same value returned by the SQL expression ``sys_context('userenv', 'instance_name')``. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the instance name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the instance name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held. * - ``valueLength`` - OUT - A pointer to the length of the instance name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getInternalName(dpiConn* conn, \ const char** value, uint32_t* valueLength) Returns the internal name that is being used by the connection. This value is used when logging distributed transactions. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the internal name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the internal name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held and the internal name is not changed by some means. * - ``valueLength`` - OUT - A pointer to the length of the internal name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getIsHealthy(dpiConn *conn, int *isHealthy) Checks if a connection is usable. Connections may become unusable in several cases, such as if the network socket is broken, if an Oracle error indicates the connection is unusable or after receiving a planned down notification from the database. This function is best used before starting a new database request on an existing standalone connection. Pooled connections internally perform this check before returning a connection to the application. Avoid using this function when database requests are in progress. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. If DPI_FAILURE is returned, the connection should be not be used by the application and a new connection should be established instead. This function performs a local check. To fully check a connection's health, use :func:`dpiConn_ping()`. .. parameters-table:: * - ``conn`` - IN - A reference to the connection for which the status is to be checked. If the reference is NULL or invalid, an error is returned. * - ``isHealthy`` - OUT - A pointer to an integer defining whether the connection is healthy (1) or not (0), which will be populated upon successful completion of this function. .. function:: int dpiConn_getLTXID(dpiConn* conn, const char** value, \ uint32_t* valueLength) Returns the logical transaction id for the connection. This value is used in Transaction Guard to determine if the last failed call was completed and if the transaction was committed using the procedure call dbms_app_cont.get_ltxid_outcome(). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the logical transaction id is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the logical transaction id, as a byte string, which will be populated upon successful completion of this function. The bytes returned will remain valid as long as a reference to the connection is held and the logical transaction id is not changed by some means. * - ``valueLength`` - OUT - A pointer to the length of the logical transaction id, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getMaxOpenCursors(dpiConn* conn, \ uint32_t* maxOpenCursors) Returns the maximum number of cursors that can be opened. This is the same value returned by the SQL expression ``SELECT VALUE FROM V$PARAMETER WHERE NAME = 'open_cursors'``. This method requires Oracle Client libraries 12.1 (or higher). This function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the maximum number of open cursors is to be retrieved. If the reference is NULL or invalid an error is returned. * - ``maxOpenCursors`` - OUT - A pointer of type uint32_t, which will be populated upon successful completion of this function. .. function:: int dpiConn_getObjectType(dpiConn* conn, const char* name, \ uint32_t nameLength, dpiObjectType** objType) Looks up an object type by name in the database and returns a reference to it. The reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection which contains the object type to look up. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - The name of the object type to lookup, as a byte string in the encoding used for CHAR data. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``objType`` - OUT - A pointer to a reference to the object type, which will be populated upon successfully locating the object type. .. function:: int dpiConn_getOciAttr(dpiConn* conn, uint32_t handleType, \ uint32_t attribute, dpiDataBuffer* value, uint32_t* valueLength) Returns the value of an OCI attribute. This is intended solely for testing attributes that are not otherwise supported by ODPI-C and should not be used for any other purpose. Use only as directed by Oracle. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the OCI attribute is to be returned. If the reference is NULL or invalid, an error is returned. * - ``handleType`` - IN - The type of OCI handle that is to be used. This should be one of 3 (service context handle), 8 (server handle) or 9 (session handle). * - ``attribute`` - IN - The attribute to acquire. * - ``value`` - OUT - A data buffer which will be populated with the value of the OCI attribute upon successfully completing this function. * - ``valueLength`` - OUT - The length of the attribute which will be populated upon succesfully completing this function. .. function:: int dpiConn_getServerVersion(dpiConn* conn, \ const char** releaseString, uint32_t* releaseStringLength, \ dpiVersionInfo* versionInfo) Returns the version information of the Oracle Database to which the connection has been made. .. note:: If you connect to Oracle Database 18 or later with Client libraries 12.2 or earlier that you will only receive the base version (such as 18.0.0.0.0) instead of the full version (such as 18.3.0.0.0). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the server version information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``releaseString`` - OUT - A pointer to the release string which will be populated when this function returns successfully. The string remains valid as long as a reference is held to the connection. This parameter may also be NULL. In Oracle Client 20.3 and higher, using NULL will eliminate the need for a round-trip to the server. * - ``releaseStringLength`` - OUT - A pointer to the length of the release string which will be populated when this function returns successfully. This parameter may also be NULL. * - ``versionInfo`` - OUT - A pointer to a :ref:`dpiVersionInfo` structure which will be populated with the version information of the Oracle Database to which the connection has been made. .. function:: int dpiConn_getServiceName(dpiConn* conn, \ const char** value, uint32_t* valueLength) Returns the Oracle Database service name associated with the connection. This is the same value returned by the SQL expression ``SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') FROM DUAL``. This function returns DPI_SCCUESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the service name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the service name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the connection is held. * - ``valueLength`` - OUT - A pointer to the length of the service name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiConn_getSodaDb(dpiConn* conn, dpiSodaDb** db) Return a reference to a SODA database which can be used to create, open and drop collections. The connection that is passed should remain open while SODA operations are being performed. If the connection is closed an error will take place when the next SODA operation is attempted. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection to use for accessing the SODA database. * - ``db`` - OUT - A pointer to a reference to a newly allocated SODA database if the function completes successfully. The function :func:`dpiSodaDb_release()` should be used when the database is no longer required. .. function:: int dpiConn_getStmtCacheSize(dpiConn* conn, uint32_t* cacheSize) Returns the size of the statement cache, in number of statements. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection from which the size of the statement cache is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``cacheSize`` - OUT - A pointer to the size of the statement cache, which will be populated upon successful completion of this function. .. function:: int dpiConn_getTransactionInProgress(dpiConn* conn, \ const int* txnInProgress) Returns whether a transaction is in progress or not. This function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the presence of a transaction should be detected. If the reference is NULL or invalid, an error is returned. * - ``txnInProgress`` - OUT - A pointer to the transaction in progress, which will be populated with 0 (no transaction) or 1 (a transaction is in progress) upon successful completion of this function. .. function:: int dpiConn_newDeqOptions(dpiConn* conn, dpiDeqOptions** options) Returns a reference to a new set of dequeue options, used in dequeuing objects from a queue. The reference should be released as soon as it is no longer needed. This function is deprecated and will be removed in version 4. The function :func:`dpiQueue_getDeqOptions()` should be used instead. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the dequeue is going to take place. If the reference is NULL or invalid, an error is returned. * - ``options`` - OUT - A pointer to a reference to the dequeue options that is created by this function. .. function:: int dpiConn_newEnqOptions(dpiConn* conn, dpiEnqOptions** options) Returns a reference to a new set of enqueue options, used in enqueuing objects into a queue. The reference should be released as soon as it is no longer needed. This function is deprecated and will be removed in version 4. The function :func:`dpiQueue_getEnqOptions()` should be used instead. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the enqueue is going to take place. If the reference is NULL or invalid, an error is returned. * - ``options`` - OUT - A pointer to a reference to the enqueue options that is created by this function. .. function:: int dpiConn_newJson(dpiConn* conn, dpiJson** json) Returns a reference to a new JSON object. This object can be used as the payload in a message enqueued in a JSON queue, or as the value for a variable. The reference should be released by calling :func:`dpiJson_release()` as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the JSON object is going to be used. If the reference is NULL or invalid, an error is returned. * - ``json`` - OUT - A pointer to a reference to the JSON object that is created by this function. .. function:: int dpiConn_newJsonQueue(dpiConn* conn, const char* name, \ uint32_t nameLength, dpiQueue** queue) Returns a reference to a new queue which enqueues and dequeues messages from Advanced Queueing (AQ) with a JSON payload. The reference should be released by calling :func:`dpiQueue_release()` as soon as it is no longer needed. For queues with RAW or Database Object payloads, use the method :func:`dpiConn_newQueue()` instead. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which messages are to be dequeued or enqueued. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - The name of the queue, as a byte string in the encoding used for CHAR data. Note that UTF-16 encodings are not currently supported by AQ. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``queue`` - OUT - A reference to the newly created queue which will be populated upon successful completion of this function. The reference should be released by calling :func:`dpiQueue_release()` as soon as it is no longer needed. .. function:: int dpiConn_newMsgProps(dpiConn* conn, dpiMsgProps** props) Returns a reference to a new set of message properties, used in enqueuing and dequeuing objects in a queue. The reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the enqueue or dequeue is going to take place. If the reference is NULL or invalid, an error is returned. * - ``props`` - OUT - A pointer to a reference to the message properties that is created by this function. .. function:: int dpiConn_newQueue(dpiConn* conn, const char* name, \ uint32_t nameLength, dpiObjectType* payloadType, dpiQueue** queue) Returns a reference to a new queue which may be used to enqueue and dequeue messages from Advanced Queuing (AQ) queues. The reference should be released by calling :func:`dpiQueue_release()` as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which messages are to be dequeued or enqueued. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - The name of the queue, as a byte string in the encoding used for CHAR data. Note that UTF-16 encodings are not currently supported by AQ. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``payloadType`` - IN - A reference to the object type which will be used for the payload of messages that dequeued and enqueued. This value may also be NULL in which case a RAW payload is dequeued and enqueued instead. * - ``queue`` - OUT - A reference to the newly created queue which will be populated upon successful completion of this function. The reference should be released by calling :func:`dpiQueue_release()` as soon as it is no longer needed. .. function:: int dpiConn_newTempLob(dpiConn* conn, dpiOracleTypeNum lobType, \ dpiLob** lob) Returns a reference to a new temporary LOB which may subsequently be written and bound to a statement. The reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the temporary LOB is to be created. If the reference is NULL or invalid, an error is returned. * - ``lobType`` - IN - The type of LOB which should be created. It should be one of these values from the enumeration :ref:`dpiOracleTypeNum`: DPI_ORACLE_TYPE_CLOB, DPI_ORACLE_TYPE_NCLOB or DPI_ORACLE_TYPE_BLOB. * - ``lob`` - OUT - A pointer to a reference to the temporary LOB that is created by this function, which will be populated upon successful completion of this function. .. function:: int dpiConn_newVar(dpiConn* conn, \ dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, \ uint32_t maxArraySize, uint32_t size, int sizeIsBytes, int isArray, \ dpiObjectType* objType, dpiVar** var, dpiData** data) Returns a reference to a new variable which can be used for binding data to a statement or providing a buffer for querying data from the database. The reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection which this variable will be used for binding or querying. If the reference is NULL or invalid, an error is returned. * - ``oracleTypeNum`` - IN - The type of Oracle data that is to be used. It should be one of the values from the enumeration :ref:`dpiOracleTypeNum`. * - ``nativeTypeNum`` - IN - The type of native C data that is to be used. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``maxArraySize`` - IN - The maximum number of rows that can be fetched or bound at one time from the database, or the maximum number of elements that can be stored in a PL/SQL array. * - ``size`` - IN - The maximum size of the buffer used for transferring data to/from Oracle. This value is only used for variables transferred as byte strings. Size is either in characters or bytes depending on the value of the sizeIsBytes parameter. If the value is in characters, internally the value will be multipled by the maximum number of bytes for each character and that value used instead when determining the necessary buffer size. * - ``sizeIsBytes`` - IN - A boolean value indicating if the size parameter refers to characters or bytes. This flag is only used if the variable refers to character data. * - ``isArray`` - IN - A boolean value indicating if the variable refers to a PL/SQL array or simply to buffers used for binding or fetching data. * - ``objType`` - IN - A reference to the object type of the object that is being bound or fetched. This value is only used if the Oracle type is DPI_ORACLE_TYPE_OBJECT. * - ``var`` - OUT - A pointer to a reference to the variable that is created by this function. * - ``data`` - OUT - A pointer to an array of :ref:`dpiData` structures that are used to transfer data to/from the variable. These are allocated when the variable is created and the number of structures corresponds to the maxArraySize. .. function:: int dpiConn_newVector(dpiConn* conn, dpiVectorInfo* info, \ dpiVector** vector) Returns a reference to a new vector object. This object can be used as the value for a variable. The reference should be released by calling :func:`dpiVector_release()` as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the vector object is going to be used. If the reference is NULL or invalid, an error is returned. * - ``info`` - IN - A pointer to a structure of type :ref:`dpiVectorInfo` which contains the information needed to populate the vector. A value of NULL is acceptable in which the vector will be empty and a call to :func:`dpiVector_setValue()` will be needed bofore it can be used. * - ``vector`` - OUT - A pointer to a reference to the vector object that is created by this function. .. function:: int dpiConn_ping(dpiConn* conn) Pings the database to determine if a connection is usable. This function does the local, light-weight checks of :func:`dpiConn_getIsHealthy()` and additionally performs a round-trip to the database if the local checks are successful. The session pool internally may perform this check before returning a connection to the application. This depends on the value of DPI_DEFAULT_PING_INTERVAL and when the connection was returned to the pool. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. If DPI_FAILURE is returned, the application should close the connection. .. parameters-table:: * - ``conn`` - IN - A reference to the connection which will be pinged. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_prepareStmt(dpiConn* conn, int scrollable, \ const char* sql, uint32_t sqlLength, const char* tag, \ uint32_t tagLength, dpiStmt** stmt) Returns a reference to a statement prepared for execution. The reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the statement is to be prepared. If the reference is NULL or invalid, an error is returned. * - ``scrollable`` - IN - A boolean indicating if the statement is scrollable or not. If it is scrollable, :func:`dpiStmt_scroll()` can be used to reposition the cursor; otherwise, rows are retrieved in order from the statement until the rows are exhausted. This value is ignored for statements that do not refer to a query. * - ``sql`` - IN - The SQL that is to be prepared for execution, as a byte string in the encoding used for CHAR data. The value can also be NULL if the tag parameter is specified. * - ``sqlLength`` - IN - The length of the SQL that is to be prepared for execution, in bytes, or 0 if the sql parameter is NULL. * - ``tag`` - IN - The key to be used for searching for the statement in the statement cache, as a byte string in the encoding used for CHAR data. The value can also be NULL if the sql parameter is specified. * - ``tagLength`` - IN - The length of the key to be used for searching for the statement in the statement cache, in bytes, or 0 if the tag parameter is NULL. * - ``stmt`` - OUT - A pointer to a reference to the statement that was just prepared, which will be populated upon successful completion of the function. .. function:: int dpiConn_release(dpiConn* conn) Releases a reference to the connection. A count of the references to the connection is maintained and when this count reaches zero, the memory associated with the connection is freed and the connection is closed or released back to the session pool if that has not already taken place using the function :func:`dpiConn_close()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - The connection from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_resumeSessionlessTransaction(dpiConn* conn, \ dpiSessionlessTransactionId* transactionId, uint32_t timeout, \ int deferRoundTrip) Resumes an existing sessionless transaction on the next server round-trip. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the sessionless transaction is to be resumed. If the reference is NULL or invalid, an error is returned. * - ``transactionId`` - IN - A unique identifier for the sessionless transaction. The length of this parameter must be non-zero and its value equal to an existing sessionless transaction. * - ``timeout`` - IN - The duration in seconds that it waits to resume a sessionless transaction (when it is being used by other session). If the timeout expires and the sessionless transaction was not resumed, an error is thrown. * - ``deferRoundTrip`` - IN - Whether to defer a round trip to the server or not. If the value is true (non-zero) the next round trip to the server will send the request instead. .. function:: int dpiConn_rollback(dpiConn* conn) Rolls back the current active transaction. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection which holds the transaction which is to be rolled back. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_setAction(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the action attribute on the connection. This is one of the end-to-end tracing attributes that can be tracked in database views, shown in audit trails and seen in tools such as Enterprise Manager. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the action attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the action attribute. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setCallTimeout(dpiConn* conn, uint32_t value) Sets the call timeout (in milliseconds) to be used for round-trips to the database made with this connection. A value of 0 means that no timeouts will take place. The current value can be acquired using the function :func:`dpiConn_getCallTimeout()`. The call timeout value applies to each database round-trip individually, not to the sum of all round-trips. Time spent processing in ODPI-C before or after the completion of each round-trip is not counted. - If the time from the start of any one round-trip to the completion of that same round-trip exceeds call timeout milliseconds, then the operation is halted and an exception occurs. - In the case where an ODPI-C operation requires more than one round-trip and each round-trip takes less than call timeout milliseconds, then no timeout will occur, even if the sum of all round-trip calls exceeds call timeout. - If no round-trip is required, the operation will never be interrupted. After a timeout is triggered, ODPI-C attempts to clean up the internal connection state. The cleanup is allowed to take another ``value`` milliseconds. If the cleanup was successful, an exception DPI-1067 will be raised but the application can continue to use the connection. For small values of call timeout, the connection cleanup may not complete successfully within the additional call timeout period. In this case an exception ORA-3114 is raised and the connection will no longer be usable. It should be closed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the current call timeout is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to use (in milliseconds) for round-trips to the database made with this connection. A value of 0 means that no timeouts will take place. .. function:: int dpiConn_setClientIdentifier(dpiConn* conn, \ const char* value, uint32_t valueLength) Sets the client identifier attribute on the connection. This is one of the end-to-end tracing attributes that can be tracked in database views, shown in audit trails and seen in tools such as Enterprise Manager. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the client identifier attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the client identifier attribute. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setClientInfo(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the client info attribute on the connection. This is one of the end-to-end tracing attributes that can be tracked in database views, shown in audit trails and seen in tools such as Enterprise Manager. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the client info attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the client info attribute. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setCurrentSchema(dpiConn* conn, \ const char* value, uint32_t valueLength) Sets the current schema to be used on the connection. This has the same effect as the SQL statement ALTER SESSION SET CURRENT_SCHEMA. The value be changed when the next call requiring a round trip to the server is performed. If the new schema name does not exist, the same error is returned as when the alter session statement is executed. The new schema name is placed before database objects in statement that you execute that do not already have a schema. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the current schema is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the current schema. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setDbOp(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the database operation attribute on the connection. This is one of the end-to-end tracing attributes that can be tracked in database views, shown in audit trails and seen in tools such as Enterprise Manager. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the database operation attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the database operation attribute. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setEcontextId(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the execution context id attribute on the connection. This is one of the end-to-end tracing attributes that can be tracked in database views, shown in audit trails and seen in tools such as Enterprise Manager. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the execution context id attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the module attribute. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setExternalName(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the external name that is being used by the connection. This value is used when logging distributed transactions. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the external name is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the external name. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setInternalName(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the internal name that is being used by the connection. This value is used when logging distributed transactions. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the internal name is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the internal name. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setModule(dpiConn* conn, const char* value, \ uint32_t valueLength) Sets the module attribute on the connection. This is one of the end-to-end tracing attributes that can be tracked in database views, shown in audit trails and seen in tools such as Enterprise Manager. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the module attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to a byte string in the encoding used for CHAR data which will be used to set the module attribute. * - ``valueLength`` - IN - The length of the value that is to be set, in bytes. .. function:: int dpiConn_setOciAttr(dpiConn* conn, uint32_t handleType, \ uint32_t attribute, void* value, uint32_t valueLength) Sets the value of an OCI attribute. This is intended solely for testing attributes that are not otherwise supported by ODPI-C and should not be used for any other purpose. Use only as directed by Oracle. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the OCI attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``handleType`` - IN - The type of OCI handle that is to be used. This should be one of 3 (service context handle), 8 (server handle) or 9 (session handle). * - ``attribute`` - IN - The attribute to set. * - ``value`` - IN - A pointer to the data which is to be set. * - ``valueLength`` - IN - The length of the data which is to be set. .. function:: int dpiConn_setStmtCacheSize(dpiConn* conn, uint32_t cacheSize) Sets the size of the statement cache. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the size of the statement cache is to be set. If the reference is NULL or invalid, an error is returned. * - ``cacheSize`` - IN - The new size of the statement cache, in number of statements. .. function:: int dpiConn_shutdownDatabase(dpiConn* conn, dpiShutdownMode mode) Shuts down the database. This function must be called twice for the database to be shut down successfully. After calling this function the first time, the SQL statements "alter database close normal" and "alter database dismount" must be executed. Once that is complete this function should be called again with the mode DPI_MODE_SHUTDOWN_FINAL in order to complete the orderly shutdown of the database. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection to the database which is to be shut down. If the reference is NULL or invalid, an error is returned. The connection needs to have been established at least with authorization mode set to DPI_MODE_AUTH_SYSDBA or DPI_MODE_AUTH_SYSOPER. * - ``mode`` - IN - One of the values from the enumeration :ref:`dpiShutdownMode`. .. function:: int dpiConn_startupDatabaseWithPfile(dpiConn* conn, \ const char* pfile, uint32_t pfileLength, dpiStartupMode mode) Starts up a database with a parameter file (PFILE). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection to the database which is to be started up. If the reference is NULL or invalid, an error is returned. The connection must be created with the authorization mode set to DPI_MODE_AUTH_PRELIM along with one of DPI_MODE_AUTH_SYSDBA or DPI_MODE_AUTH_SYSOPER. * - ``pfile`` - IN - A pointer to a byte string in the encoding used for CHAR data which identifies the name of the parameter file (PFILE) that will be used to startup the database. This value may be NULL if the pfileLength parameter is zero. In that case this function behaves identically to the :func:`dpiConn_startupDatabase()` function. * - ``pfileLength`` - IN - The length of the pfile parameter, in bytes. * - ``mode`` - IN - One or more of the values from the enumeration :ref:`dpiStartupMode`, OR'ed together. .. function:: int dpiConn_startupDatabase(dpiConn* conn, dpiStartupMode mode) Starts up a database. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection to the database which is to be started up. If the reference is NULL or invalid, an error is returned. The connection must be created with the authorization mode set to DPI_MODE_AUTH_PRELIM along with one of DPI_MODE_AUTH_SYSDBA or DPI_MODE_AUTH_SYSOPER. * - ``mode`` - IN - One or more of the values from the enumeration :ref:`dpiStartupMode`, OR'ed together. .. function:: int dpiConn_subscribe(dpiConn* conn, \ dpiSubscrCreateParams* params, dpiSubscr** subscr) Returns a reference to a subscription which is used for requesting notifications of events that take place in the database. Events that are supported are changes on tables or queries (continuous query notification) and the availability of messages to dequeue (advanced queuing). The reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the subscription is to be created. If the reference is NULL or invalid, an error is returned. * - ``params`` - IN - A pointer to a :ref:`dpiSubscrCreateParams` structure which is used to specify parameters for the subscription. These parameters determine what events will result in notifications. * - ``subscr`` - OUT - A pointer to a reference to the subscription that is created by this function. .. function:: int dpiConn_suspendSessionlessTransaction(dpiConn* conn, \ uint32_t flags) Suspends the active sessionless transaction on the current connection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection on which the sessionless transaction is to be suspended. If the reference is NULL or invalid, an error is returned. .. function:: int dpiConn_tpcBegin(dpiConn* conn, dpiXid* xid, \ uint32_t transactionTimeout, uint32_t flags) Begins a new TPC (two-phase commit) transaction with the given transaction id (XID). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the transaction is to begin. If the reference is NULL or invalid, an error is returned. * - ``xid`` - IN - A pointer to a structure of type :ref:`dpiXid` which identifies the TPC transaction which is to begin. * - ``transactionTimeout`` - IN - The duration in seconds to wait for a transaction to become available for resumption when the flags parameter is one of DPI_TPC_BEGIN_RESUME or DPI_TPC_BEGIN_JOIN. When DPI_TPC_BEGIN_NEW is specified for the flags parameter, this parameter indicates the number of seconds the transaction can be inactive before it is automatically terminated by the system. * - ``flags`` - IN - One of the values from the enumeration :ref:`dpiTpcBeginFlags`. .. function:: int dpiConn_tpcCommit(dpiConn* conn, dpiXid* xid, int onePhase) Commits a TPC (two-phase commit) transaction. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the transaction is to be committed. If the reference is NULL or invalid, an error is returned. * - ``xid`` - IN - A pointer to a structure of type :ref:`dpiXid` which identifies the TPC transaction which is to be committed. If this value is NULL, the XID associated with the connection via the last TPC call is used and this function becomes equivalent to :func:`dpiConn_commit()`. * - ``onePhase`` - IN - Specifies whether to perform a one phase commit (1) or a two-phase commit (0) if the xid parameter is not NULL. If the xid parameter is NULL the connection already knows what type of commit is needed and this parameter is ignored. .. function:: int dpiConn_tpcEnd(dpiConn* conn, dpiXid* xid, uint32_t flags) Ends a TPC (two-phase commit) transaction with the given transaction id (XID). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the transaction is to end. If the reference is NULL or invalid, an error is returned. * - ``xid`` - IN - A pointer to a structure of type :ref:`dpiXid` which identifies the TPC transaction which is to end. If this value is NULL, the XID associated with the connection via the last TPC call is used. * - ``flags`` - IN - One of the values from the enumeration :ref:`dpiTpcEndFlags`. .. function:: int dpiConn_tpcForget(dpiConn* conn, dpiXid* xid) Forgets a TPC (two-phase commit) transaction. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the transaction is to be forgotten. If the reference is NULL or invalid, an error is returned. * - ``xid`` - IN - A pointer to a structure of type :ref:`dpiXid` which identifies the TPC transaction which is to be forgotten. .. function:: int dpiConn_tpcPrepare(dpiConn* conn, dpiXid* xid, \ int* commitNeeded) Prepares a TPC (two-phase commit) transaction for commit. This function should only be called after :func:`dpiConn_tpcBegin()` is called and before :func:`dpiConn_tpcCommit()` or :func:`dpiConn_commit()` is called. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the transaction is to be prepared. If the reference is NULL or invalid, an error is returned. * - ``xid`` - IN - A pointer to a structure of type :ref:`dpiXid` which identifies the TPC transaction which is to be prepared. If this value is NULL, the XID associated with the connection during the previous call to :func:`dpiConn_tpcBegin()` is used. * - ``commitNeeded`` - OUT - A pointer to a boolean value indicating if a commit is needed or not. If no commit is needed, attempting to commit anyway will result in an ORA-24756 error (transaction does not exist). .. function:: int dpiConn_tpcRollback(dpiConn* conn, dpiXid* xid) Rolls back a TPC (two-phase commit) transaction. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the transaction is to be rolled back. If the reference is NULL or invalid, an error is returned. * - ``xid`` - IN - A pointer to a structure of type :ref:`dpiXid` which identifies the TPC transaction which is to be rolled back. If this value is NULL, the XID associated with the connection via the last TPC call is used and this function becomes equivalent to :func:`dpiConn_rollback()`. .. function:: int dpiConn_unsubscribe(dpiConn* conn, dpiSubscr* subscr) Unsubscribes from the events that were earlier subscribed to via the function :func:`dpiConn_subscribe()`. Once this function completes successfully no further notifications will be sent for this subscription. Note that this method does not generate a notification either. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``conn`` - IN - A reference to the connection in which the subscription is to be destroyed. If the reference is NULL or invalid, an error is returned. The connection used to unsubscribe should be the same connection used to subscribe or should access the same database and be connected as the same user name. * - ``subscr`` - OUT - A pointer to a reference to the subscription that is to be destroyed. A reference will be released and the subscription will no longer be usable once this function completes successfully. odpi-5.6.4/doc/src/functions/dpiContext.rst000066400000000000000000000241561510466437300207210ustar00rootroot00000000000000.. _dpiContextFunctions: ODPI-C Context Functions ------------------------ Context handles are the top level handles created by the library and are used for all error handling as well as creating pools and standalone connections to the database. The first call to ODPI-C by any application must be :func:`dpiContext_createWithParams()` which will create the context as well as validate the version used by the application. Context handles are destroyed by using the function :func:`dpiContext_destroy()`. .. function:: int dpiContext_createWithParams(unsigned int majorVersion, \ unsigned int minorVersion, dpiContextCreateParams* params, \ dpiContext** context, dpiErrorInfo* errorInfo) Creates a new context for interaction with the library. This is the first function that must be called and it must have completed successfully before any other functions can be called, including in other threads. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. If a failure occurs, the errorInfo structure is filled in with error information. .. note:: The function ``dpiContext_create()`` was replaced by a macro in version 4 which calls this function with params set to the value NULL. .. parameters-table:: * - ``majorVersion`` - IN - The major version of the ODPI-C library that is being used by the application. This should always be the constant value DPI_MAJOR_VERSION defined in the dpi.h being used by the application. It must match the major version of the ODPI-C library that is being linked to the application. * - ``minorVersion`` - IN - The minor version of the ODPI-C library that is being used by the application. This should always be the constant value DPI_MINOR_VERSION defined in the dpi.h being used by the application. It must be less than or equal to the minor version of the ODPI-C library that is being linked to the application. * - ``params`` - IN - A pointer to a :ref:`dpiContextCreateParams` structure containing parameters used to modify how ODPI-C loads the Oracle Client library. Although it is possible to create multiple contexts, only the first context created will use these parameters. This value can also be NULL in which case default parameters will be used. * - ``context`` - OUT - A pointer to a context handle which will be populated upon successful completion of this function. * - ``errorInfo`` - OUT - A pointer to a :ref:`dpiErrorInfo` structure which will be populated with error information if an error takes place during the execution of this function. If no error takes place, the structure is not modified in any way. Note that the only members of the structure that should be examined when an error occurs are message, messageLength, encoding, fnName, and action. .. function:: int dpiContext_destroy(dpiContext* context) Destroys the context that was earlier created with the function :func:`dpiContext_createWithParams()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle which should be destroyed. If the handle is NULL or invalid, an error is returned. .. function:: int dpiContext_freeStringList(dpiContext* context, \ dpiStringList* list) Frees the memory associated with the string list allocated by a call to one of the functions :func:`dpiSodaDb_getCollectionNames()` or :func:`dpiSodaColl_listIndexes()`. This function should not be called without first calling one of those functions first. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - A reference to the context in which the string list was allocated. * - ``list`` - IN - A pointer to a structure of type :ref:`dpiStringList` which was previously used in a call to :func:`dpiSodaDb_getCollectionNames()` or :func:`dpiSodaColl_listIndexes()`. .. function:: int dpiContext_getClientVersion(const dpiContext* context, \ dpiVersionInfo* versionInfo) Return information about the version of the Oracle Client that is being used. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``versionInfo`` - OUT - A pointer to a :ref:`dpiVersionInfo` structure which will be populated with the version information of the Oracle Client being used. .. function:: void dpiContext_getError(const dpiContext* context, \ dpiErrorInfo* errorInfo) Returns information for the last error or warning that was raised by the library. This function must be called with the same thread that generated the error or warning. It must also be called before any other ODPI-C library calls are made on the calling thread since the error/warning information specific to that thread is cleared at the start of every ODPI-C function call. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, the error information is populated with an invalid context handle error instead. * - ``errorInfo`` - OUT - A pointer to a :ref:`dpiErrorInfo` structure which will be populated with information about the last error or warning that was raised. If a warning was raised, the :member:`dpiErrorInfo.isWarning` flag will be set to the value 1. .. function:: int dpiContext_initCommonCreateParams( \ const dpiContext* context, dpiContextParams* params) Initializes the :ref:`dpiCommonCreateParams` structure to default values. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``params`` - OUT - A pointer to a :ref:`dpiCommonCreateParams` structure which will be populated with default values upon completion of this function. .. function:: int dpiContext_initConnCreateParams( \ const dpiContext* context, dpiConnCreateParams* params) Initializes the :ref:`dpiConnCreateParams` structure to default values. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``params`` - OUT - A pointer to a :ref:`dpiConnCreateParams` structure which will be populated with default values upon completion of this function. .. function:: int dpiContext_initPoolCreateParams( \ const dpiContext* context, dpiPoolCreateParams* params) Initializes the :ref:`dpiPoolCreateParams` structure to default values. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``params`` - OUT - A pointer to a :ref:`dpiPoolCreateParams` structure which will be populated with default values upon completion of this function. .. function:: int dpiContext_initSodaOperOptions( \ const dpiContext* context, dpiSodaOperOptions* options) Initializes the :ref:`dpiSodaOperOptions` structure to default values. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``options`` - OUT - A pointer to a :ref:`dpiSodaOperOptions` structure which will be populated with default values upon completion of this function. .. function:: int dpiContext_initSubscrCreateParams( \ const dpiContext* context, dpiSubscrCreateParams* params) Initializes the :ref:`dpiSubscrCreateParams` structure to default values. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``params`` - OUT - A pointer to a :ref:`dpiSubscrCreateParams` structure which will be populated with default values upon completion of this function. odpi-5.6.4/doc/src/functions/dpiData.rst000066400000000000000000000304341510466437300201420ustar00rootroot00000000000000.. _dpiDataFunctions: ODPI-C Data Functions --------------------- All of these functions are used for getting and setting the various members of the :ref:`dpiData` structure. The members of the structure can be manipulated directly but some languages (such as Go) do not have the ability to manipulate structures containing unions or the ability to process macros. For this reason, none of these functions perform any error checking. They are assumed to be replacements for direct manipulation of the various members of the structure. .. function:: int dpiData_getBool(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_BOOLEAN. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiBytes* dpiData_getBytes(dpiData* data) Returns a pointer to the value of the data when the native type is DPI_NATIVE_TYPE_BYTES. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: double dpiData_getDouble(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_DOUBLE. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: float dpiData_getFloat(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_FLOAT. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: int64_t dpiData_getInt64(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_INT64. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiIntervalDS* dpiData_getIntervalDS(dpiData* data) Returns a pointer to the value of the data when the native type is DPI_NATIVE_TYPE_INTERVAL_DS. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiIntervalYM* dpiData_getIntervalYM(dpiData* data) Returns a pointer to the value of the data when the native type is DPI_NATIVE_TYPE_INTERVAL_YM. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: int dpiData_getIsNull(dpiData* data) Returns whether the data refers to a null value (1) or not (0). .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the null indicator. .. function:: dpiLob* dpiData_getLOB(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_LOB. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiJson* dpiData_getJson(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_JSON. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiJsonArray* dpiData_getJsonArray(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_JSON_ARRAY. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiJsonObject* dpiData_getJsonObject(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_JSON_OBJECT. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiObject* dpiData_getObject(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_OBJECT. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiStmt* dpiData_getStmt(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_STMT. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiTimestamp* dpiData_getTimestamp(dpiData* data) Returns a pointer to the value of the data when the native type is DPI_NATIVE_TYPE_TIMESTAMP. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: uint64_t dpiData_getUint64(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_UINT64. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: dpiVector* dpiData_getVector(dpiData* data) Returns the value of the data when the native type is DPI_NATIVE_TYPE_VECTOR. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure from which to get the value. .. function:: void dpiData_setBool(dpiData* data, int value) Sets the value of the data when the native type is DPI_NATIVE_TYPE_BOOLEAN. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``value`` - IN - The value to set. .. function:: void dpiData_setBytes(dpiData* data, char* ptr, uint32_t length) Sets the value of the data when the native type is DPI_NATIVE_TYPE_BYTES. Do *not* use this function when setting data for variables. Instead, use the function :func:`dpiVar_setFromBytes()`. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``ptr`` - IN - The byte string containing the data to set. * - ``length`` - IN - The length of the byte string. .. function:: void dpiData_setDouble(dpiData* data, double value) Sets the value of the data when the native type is DPI_NATIVE_TYPE_DOUBLE. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``value`` - IN - The value to set. .. function:: void dpiData_setFloat(dpiData* data, float value) Sets the value of the data when the native type is DPI_NATIVE_TYPE_FLOAT. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``value`` - IN - The value to set. .. function:: void dpiData_setInt64(dpiData* data, int64_t value) Sets the value of the data when the native type is DPI_NATIVE_TYPE_INT64. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``value`` - IN - The value to set. .. function:: void dpiData_setIntervalDS(dpiData* data, int32_t days, \ int32_t hours, int32_t minutes, int32_t seconds, int32_t fseconds) Sets the value of the data when the native type is DPI_NATIVE_TYPE_INTERVAL_DS. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``days`` - IN - The number of days to set in the value. * - ``hours`` - IN - The number of hours to set in the value. * - ``minutes`` - IN - The number of minutes to set in the value. * - ``seconds`` - IN - The number of seconds to set in the value. * - ``fseconds`` - IN - The number of fractional seconds to set in the value. .. function:: void dpiData_setIntervalYM(dpiData* data, int32_t years, \ int32_t months) Sets the value of the data when the native type is DPI_NATIVE_TYPE_INTERVAL_YM. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``years`` - IN - The number of years to set in the value. * - ``months`` - IN - The number of months to set in the value. .. function:: void dpiData_setLOB(dpiData* data, dpiLob* lob) Sets the value of the data when the native type is DPI_NATIVE_TYPE_LOB. Do *not* use this function when setting data for variables. Instead, use the function :func:`dpiVar_setFromLob()`. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``lob`` - IN - A reference to the LOB to assign to the value. .. function:: void dpiData_setNull(dpiData* data) Sets the value of the data to be the null value. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. .. function:: void dpiData_setObject(dpiData* data, dpiObject* obj) Sets the value of the data when the native type is DPI_NATIVE_TYPE_OBJECT. Do *not* use this function when setting data for variables. Instead, use the function :func:`dpiVar_setFromObject()`. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``obj`` - IN - A reference to the object to assign to the value. .. function:: void dpiData_setStmt(dpiData* data, dpiStmt* stmt) Sets the value of the data when the native type is DPI_NATIVE_TYPE_STMT. Do *not* use this function when setting data for variables. Instead, use the function :func:`dpiVar_setFromStmt()`. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``stmt`` - IN - A reference to the statement to assign to the value. .. function:: void dpiData_setTimestamp(dpiData* data, int16_t year, \ uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, \ uint8_t second, uint32_t fsecond, int8_t tzHourOffset, \ int8_t tzMinuteOffset) Sets the value of the data when the native type is DPI_NATIVE_TYPE_TIMESTAMP. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``year`` - IN - The year to set in the value. * - ``month`` - IN - The month to set in the value. * - ``day`` - IN - The day to set in the value. * - ``hour`` - IN - The hour to set in the value. * - ``minute`` - IN - The minute to set in the value. * - ``second`` - IN - The second to set in the value. * - ``fsecond`` - IN - The fractional seconds to set in the value. * - ``tzHourOffset`` - IN - The time zone hour offset to set in the value. * - ``tzMinuteOffset`` - IN - The time zone minute offset to set in the value. .. function:: void dpiData_setUint64(dpiData* data, uint64_t value) Sets the value of the data when the native type is DPI_NATIVE_TYPE_UINT64. .. parameters-table:: * - ``data`` - IN - A pointer to the :ref:`dpiData` structure to set. * - ``value`` - IN - The value to set. odpi-5.6.4/doc/src/functions/dpiDeqOptions.rst000066400000000000000000000444511510466437300213620ustar00rootroot00000000000000.. _dpiDeqOptionsFunctions: ODPI-C Dequeue Options Functions -------------------------------- Dequeue option handles are used to represent the options specified when dequeuing messages using advanced queueing. They are created by calling the function :func:`dpiConn_newDeqOptions()` and are destroyed by releasing the last reference by calling the function :func:`dpiDeqOptions_release()`. .. function:: int dpiDeqOptions_addRef(dpiDeqOptions* options) Adds a reference to the dequeue options. This is intended for situations where a reference to the dequeue options needs to be maintained independently of the reference returned when the handle was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - The dequeue options to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiDeqOptions_getCondition(dpiDeqOptions* options, \ const char** value, uint32_t* valueLength) Returns the condition that must be satisfied in order for a message to be dequeued. See function :func:`dpiDeqOptions_setCondition()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the condition is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no condition, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no condition, the pointer will be populated with the value 0. .. function:: int dpiDeqOptions_getConsumerName(dpiDeqOptions* options, \ const char** value, uint32_t* valueLength) Returns the name of the consumer that is dequeuing messages. See function :func:`dpiDeqOptions_setConsumerName()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the consumer name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no consumer name, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no consumer name, the pointer will be populated with the value 0. .. function:: int dpiDeqOptions_getCorrelation(dpiDeqOptions* options, \ const char** value, uint32_t* valueLength) Returns the correlation of the message to be dequeued. See function :func:`dpiDeqOptions_setCorrelation()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the correlation is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no correlation, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no correlation, the pointer will be populated with the value 0. .. function:: int dpiDeqOptions_getMode(dpiDeqOptions* options, \ dpiDeqMode* value) Returns the mode that is to be used when dequeuing messages. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the mode is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiDeqMode`. .. function:: int dpiDeqOptions_getMsgId(dpiDeqOptions* options, \ const char** value, uint32_t* valueLength) Returns the identifier of the specific message that is to be dequeued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the message identifier is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. If there is no message identifier, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no message identifier, the pointer will be populated with the value 0. .. function:: int dpiDeqOptions_getNavigation(dpiDeqOptions* options, \ dpiDeqNavigation* value) Returns the position of the message that is to be dequeued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the navigation option is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiDeqNavigation`. .. function:: int dpiDeqOptions_getTransformation(dpiDeqOptions* options, \ const char** value, uint32_t* valueLength) Returns the transformation of the message to be dequeued. See function :func:`dpiDeqOptions_setTransformation()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the transformation is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no transformation, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no transformation, the pointer will be populated with the value 0. .. function:: int dpiDeqOptions_getVisibility(dpiDeqOptions* options, \ dpiVisibility* value) Returns whether the message being dequeued is part of the current transaction or constitutes a transaction on its own. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the visibility is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiVisibility`. .. function:: int dpiDeqOptions_getWait(dpiDeqOptions* options, \ uint32_t* value) Returns the time to wait, in seconds, for a message matching the search criteria. See function :func:`dpiDeqOptions_setWait()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options from which the wait time is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. .. function:: int dpiDeqOptions_release(dpiDeqOptions* options) Releases a reference to the dequeue options. A count of the references to the dequeue options is maintained and when this count reaches zero, the memory associated with the options is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - The dequeue options from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiDeqOptions_setCondition(dpiDeqOptions* options, \ const char* value, uint32_t valueLength) Sets the condition which must be true for messages to be dequeued. The condition must be a valid boolean expression similar to the where clause of a SQL query. The expression can include conditions on message properties, user data properties and PL/SQL or SQL functions. User data properties must be prefixed with tab.user_data as a qualifier to indicate the specific column of the queue table that stores the message payload. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the condition is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the condition is to be cleared. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiDeqOptions_setConsumerName(dpiDeqOptions* options, \ const char* value, uint32_t valueLength) Sets the name of the consumer which will be dequeuing messages. This value should only be set if the queue is set up for multiple consumers. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the consumer name is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the consumer name is to be cleared. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiDeqOptions_setCorrelation(dpiDeqOptions* options, \ const char* value, uint32_t valueLength) Sets the correlation of the message to be dequeued. Special pattern matching characters such as the percent sign (%) and the underscore (_) can be used. If multiple messages satisfy the pattern, the order of dequeuing is undetermined. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the correlation is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the correlation is to be cleared. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiDeqOptions_setDeliveryMode(dpiDeqOptions* options, \ dpiMessageDeliveryMode value) Sets the message delivery mode that is to be used when dequeuing messages. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the message delivery mode is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The mode that should be used. It should be one of the values from the enumeration :ref:`dpiMessageDeliveryMode`. .. function:: int dpiDeqOptions_setMode(dpiDeqOptions* options, \ dpiDeqMode value) Sets the mode that is to be used when dequeuing messages. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the mode is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The mode that should be used. It should be one of the values from the enumeration :ref:`dpiDeqMode`. .. function:: int dpiDeqOptions_setMsgId(dpiDeqOptions* options, \ const char* value, uint32_t valueLength) Sets the identifier of the specific message to be dequeued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the message identifier is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to the bytes making up the message identifier, or NULL if no specific message is to be dequeued. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiDeqOptions_setNavigation(dpiDeqOptions* options, \ dpiDeqNavigation value) Sets the position in the queue of the message that is to be dequeued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the navigation option is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value that should be used. It should be one of the values from the enumeration :ref:`dpiDeqNavigation`. .. function:: int dpiDeqOptions_setTransformation(dpiDeqOptions* options, \ const char* value, uint32_t valueLength) Sets the transformation of the message to be dequeued. The transformation is applied after the message is dequeued but before it is returned to the application. It must be created using DBMS_TRANSFORM. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the transformation is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the transformation is to be cleared. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiDeqOptions_setVisibility(dpiDeqOptions* options, \ dpiVisibility value) Sets whether the message being dequeued is part of the current transaction or constitutes a transaction on its own. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the visibility is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value that should be used. It should be one of the values from the enumeration :ref:`dpiVisibility`. .. function:: int dpiDeqOptions_setWait(dpiDeqOptions* options, \ uint32_t value) Set the time to wait, in seconds, for a message matching the search criteria. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the dequeue options on which the wait time is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The number of seconds to wait for a message matching the search criteria. Any integer is valid but the predefined constants DPI_DEQ_WAIT_NO_WAIT and DPI_DEQ_WAIT_FOREVER are provided as a convenience. odpi-5.6.4/doc/src/functions/dpiEnqOptions.rst000066400000000000000000000134401510466437300213660ustar00rootroot00000000000000.. _dpiEnqOptionsFunctions: ODPI-C Enqueue Options Functions -------------------------------- Enqueue option handles are used to represent the options specified when enqueuing messages using advanced queueing. They are created by calling the function :func:`dpiConn_newEnqOptions()` and are destroyed by releasing the last reference by calling the function :func:`dpiEnqOptions_release()`. .. function:: int dpiEnqOptions_addRef(dpiEnqOptions* options) Adds a reference to the enqueue options. This is intended for situations where a reference to the enqueue options needs to be maintained independently of the reference returned when the handle was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - The enqueue options to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiEnqOptions_getTransformation(dpiEnqOptions* options, \ const char** value, uint32_t* valueLength) Returns the transformation of the message to be enqueued. See function :func:`dpiEnqOptions_setTransformation()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the enqueue options from which the transformation is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no transformation, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no transformation, the pointer will be populated with the value 0. .. function:: int dpiEnqOptions_getVisibility(dpiEnqOptions* options, \ dpiVisibility* value) Returns whether the message being enqueued is part of the current transaction or constitutes a transaction on its own. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the enqueue options from which the visibility is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiVisibility`. .. function:: int dpiEnqOptions_release(dpiEnqOptions* options) Releases a reference to the enqueue options. A count of the references to the enqueue options is maintained and when this count reaches zero, the memory associated with the options is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - The enqueue options from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiEnqOptions_setDeliveryMode(dpiEnqOptions* options, \ dpiMessageDeliveryMode value) Sets the message delivery mode that is to be used when enqueuing messages. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the enqueue options on which the message delivery mode is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The mode that should be used. It should be one of the values from the enumeration :ref:`dpiMessageDeliveryMode`. .. function:: int dpiEnqOptions_setTransformation(dpiEnqOptions* options, \ const char* value, uint32_t valueLength) Sets the transformation of the message to be enqueued. The transformation is applied after the message is enqueued but before it is returned to the application. It must be created using DBMS_TRANSFORM. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the enqueue options on which the transformation is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the transformation is to be cleared. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiEnqOptions_setVisibility(dpiEnqOptions* options, \ dpiVisibility value) Sets whether the message being enqueued is part of the current transaction or constitutes a transaction on its own. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``options`` - IN - A reference to the enqueue options on which the visibility is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value that should be used. It should be one of the values from the enumeration :ref:`dpiVisibility`. odpi-5.6.4/doc/src/functions/dpiJson.rst000066400000000000000000000103171510466437300202000ustar00rootroot00000000000000.. _dpiJsonFunctions: ODPI-C JSON Functions --------------------- JSON handles are used to represent JSON values stored in the database. They are only available from Oracle Client and Database 20 and higher. They cannot be created directly but are created implicitly when a variable of type DPI_ORACLE_TYPE_JSON is created. They are destroyed when the last reference is released by a call to the function :func:`dpiJson_release()`. .. function:: int dpiJson_addRef(dpiJson* json) Adds a reference to the JSON value. This is intended for situations where a reference to the JSON value needs to be maintained independently of the reference returned when the JSON value was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``json`` - IN - The JSON value to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiJson_getValue(dpiJson* json, uint32_t options, \ dpiJsonNode** topNode) Returns the top node of a hierarchy of nodes containing the data stored in the JSON value. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``json`` - IN - The JSON value from which the top node is to be returned. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - One or more of the values from the :ref:`dpiJsonOptions` enumerations, OR'ed together. * - ``topNode`` - OUT - A pointer to the top node of the JSON value, which will be populated upon successful completion of this function. It is a structure of type :ref:`dpiJsonNode` and will remain valid as long as a reference is held to the JSON value and as long as the JSON value is not modified by call to :func:`dpiJson_setValue()`. .. function:: int dpiJson_release(dpiJson* json) Releases a reference to the JSON value. A count of the references to the JSON value is maintained and when this count reaches zero, the memory associated with the JSON value is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``json`` - IN - The JSON value from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiJson_setFromText(dpiJson* json, \ const char* value, uint64_t valueLength, uint32_t flags) Sets the JSON value from the JSON string passed as a byte string. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``json`` - IN - The JSON value which is to be modified to contain the data from input JSON string. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to the JSON string which contains the data to be set. This value can be NULL if the valueLength parameter is 0. * - ``valueLength`` - IN - The length of the data to be set, in bytes. * - ``flags`` - IN - Flags which can be used in the future to adjust how text is converted to JSON. Pass 0 for now. .. function:: int dpiJson_setValue(dpiJson* json, dpiJsonNode* topNode) Sets the JSON value to the data found in the hierarchy of nodes pointed to by the top level node. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``json`` - IN - The JSON value which is to be modified to contain the data found in the hierarchy of nodes pointed to by the top node. If the reference is NULL or invalid, an error is returned. * - ``topNode`` - IN - A pointer to the top node of the data which will replace the data in the JSON value. It is a structure of type :ref:`dpiJsonNode`. odpi-5.6.4/doc/src/functions/dpiLob.rst000066400000000000000000000416511510466437300200100ustar00rootroot00000000000000.. _dpiLobFunctions: ODPI-C LOB Functions -------------------- LOB handles are used to represent large objects (CLOB, BLOB, NCLOB, BFILE). Both persistent and temporary large objects can be represented. LOB handles can be created by calling the function :func:`dpiConn_newTempLob()` or are created implicitly when a variable of type DPI_ORACLE_TYPE_CLOB, DPI_ORACLE_TYPE_NCLOB, DPI_ORACLE_TYPE_BLOB or DPI_ORACLE_TYPE_BFILE is created and are destroyed when the last reference is released by calling the function :func:`dpiLob_release()`. They are used for reading and writing data to the database in smaller pieces than is contained in the large object. .. function:: int dpiLob_addRef(dpiLob* lob) Adds a reference to the LOB. This is intended for situations where a reference to the LOB needs to be maintained independently of the reference returned when the LOB was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - The LOB to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiLob_close(dpiLob* lob) Closes the LOB and makes it unusable for further operations immediately, rather than when the reference count reaches zero. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB which is to be closed. If the reference is NULL or invalid, an error is returned. .. function:: int dpiLob_closeResource(dpiLob* lob) Closes the LOB resource. This should be done when a batch of writes has been completed so that the indexes associated with the LOB can be updated. It should only be performed if a call to function :func:`dpiLob_openResource()` has been performed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB which will be closed. If the reference is NULL or invalid, an error is returned. .. function:: int dpiLob_copy(dpiLob* lob, dpiLob** copiedLob) Creates an independent copy of a LOB and returns a reference to the newly created LOB. This reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - The LOB which is to be copied. If the reference is NULL or invalid an error is returned. * - ``copiedLob`` - OUT - A pointer to a reference to the LOB which is created as a copy of the first LOB, which is populated upon successful completion of this function. .. function:: int dpiLob_getBufferSize(dpiLob* lob, uint64_t sizeInChars, \ uint64_t* sizeInBytes) Returns the size of the buffer needed to hold the number of characters specified for a buffer of the type associated with the LOB. If the LOB does not refer to a character LOB the value is returned unchanged. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB in which the buffer is going to be used for transferring data to and from Oracle. If the reference is NULL or invalid an error is returned. * - ``sizeInChars`` - IN - The number of characters for which a buffer size needs to be determined. * - ``sizeInBytes`` - OUT - A pointer to the size in bytes which will be populated when the function has completed successfully. .. function:: int dpiLob_getChunkSize(dpiLob* lob, uint32_t* size) Returns the chunk size, in bytes, of the internal LOB. Reading and writing to the LOB in multiples of this size will improve performance. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB from which the chunk size is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``size`` - OUT - A pointer to the chunk size, in bytes, which will be populated when this function completes successfully. .. function:: int dpiLob_getDirectoryAndFileName(dpiLob* lob, \ const char** directoryAlias, uint32_t* directoryAliasLength, \ const char** fileName, uint32_t* fileNameLength) Returns the directory alias name and file name for a BFILE type LOB. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB from which the directory alias name and file name are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``directoryAlias`` - OUT - A pointer to the name of the directory alias, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the LOB is held. * - ``directoryAliasLength`` - OUT - A pointer to the length of the name of the directory alias, in bytes, which will be populated upon successful completion of this function. * - ``fileName`` - OUT - A pointer to the name of the file, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the LOB is held. * - ``fileNameLength`` - OUT - A pointer to the length of the name of the file, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiLob_getFileExists(dpiLob* lob, int* exists) Returns a boolean value indicating if the file referenced by the BFILE type LOB exists (1) or not (0). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB which will be checked to see if the associated file exists. If the reference is NULL or invalid, an error is returned. * - ``exists`` - OUT - A pointer to the boolean value which will be populated when this function completes successfully. .. function:: int dpiLob_getIsResourceOpen(dpiLob* lob, int* isOpen) Returns a boolean value indicating if the LOB resource has been opened by making a call to the function :func:`dpiLob_openResource()` (1) or not (0). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB which will be checked to see if it is open. If the reference is NULL or invalid, an error is returned. * - ``isOpen`` - OUT - A pointer to the boolean value which will be populated when this function completes successfully. .. function:: int dpiLob_getSize(dpiLob* lob, uint64_t* size) Returns the size of the data stored in the LOB. For character LOBs the size is in characters; for binary LOBs the size is in bytes. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. **WARNING**: for historical reasons, Oracle stores CLOBs and NCLOBs using the UTF-16 encoding, regardless of what encoding is otherwise in use by the database. The number of characters, however, is defined by the number of UCS-2 codepoints. For this reason, if a character requires more than one UCS-2 codepoint, the size returned will be inaccurate and care must be taken to account for the difference. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB from which the size will be retrieved. If the reference is NULL or invalid, an error is returned. * - ``size`` - OUT - A pointer to the value which will be populated when this function completes successfully. .. function:: int dpiLob_getType(dpiLob* lob, dpiOracleTypeNum* type) Returns the type of the LOB. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB from which the type will be retrieved. If the reference is NULL or invalid, an error is returned. * - ``type`` - OUT - A pointer to the value which will be populated when this function completes successfully. It will one of the values from the enumeration :ref:`dpiOracleTypeNum` - `DPI_ORACLE_TYPE_CLOB`, `DPI_ORACLE_TYPE_NCLOB`, `DPI_ORACLE_TYPE_BLOB` or `DPI_ORACLE_TYPE_BFILE`. .. function:: int dpiLob_openResource(dpiLob* lob) Opens the LOB resource for writing. This will improve performance when writing to the LOB in chunks and there are functional or extensible indexes associated with the LOB. If this function is not called, the LOB resource will be opened and closed for each write that is performed. A call to the function :func:`dpiLob_closeResource()` should be done before performing a call to the function :func:`dpiConn_commit()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB which will be opened. If the reference is NULL or invalid, an error is returned. .. function:: int dpiLob_readBytes(dpiLob* lob, uint64_t offset, \ uint64_t amount, char* value, uint64_t* valueLength) Reads data from the LOB at the specified offset into the provided buffer. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. **WARNING**: for historical reasons, Oracle stores CLOBs and NCLOBs using the UTF-16 encoding, regardless of what encoding is otherwise in use by the database. The number of characters, however, is defined by the number of UCS-2 codepoints. For this reason, if a character requires more than one UCS-2 codepoint, care must be taken to account for them in both the offset and amount parameters. .. parameters-table:: * - ``lob`` - IN - The LOB from which data is to be read. If the reference is NULL or invalid, an error is returned. * - ``offset`` - IN - The offset into the LOB data from which to start reading. The first position is 1. For character LOBs this represents the number of characters from the beginning of the LOB; for binary LOBS, this represents the number of bytes from the beginning of the LOB. * - ``amount`` - IN - The maximum number of characters (for character LOBs) or the maximum number of bytes (for binary LOBs) that will be read from the LOB. If reading from a character LOB, the buffer size required can be calculated by taking the number of characters and multiplying by the maximum number of bytes per character. This will be :member:`dpiEncodingInfo.maxBytesPerCharacter` for CLOBs and :member:`dpiEncodingInfo.nmaxBytesPerCharacter` for NCLOBs. * - ``value`` - OUT - The buffer into which the data is read. It is assumed to contain the number of bytes specified in the valueLength parameter. * - ``valueLength`` - IN/OUT - A pointer to the size of the value. When this function is called it must contain the maximum number of bytes in the buffer specified by the value parameter. After the function is completed successfully it will contain the actual number of bytes read into the buffer. .. function:: int dpiLob_release(dpiLob* lob) Releases a reference to the LOB. A count of the references to the LOB is maintained and when this count reaches zero, the memory associated with the LOB is freed. The LOB is also closed unless that has already taken place using the function :func:`dpiLob_close()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - The LOB from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiLob_setDirectoryAndFileName(dpiLob* lob, \ const char* directoryAlias, uint32_t directoryAliasLength, \ const char* fileName, uint32_t fileNameLength) Sets the directory alias name and file name for a BFILE type LOB. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - A reference to the LOB on which the directory alias name and file name are to be set. If the reference is NULL or invalid, an error is returned. * - ``directoryAlias`` - IN - The name of the directory alias, as a byte string in the encoding used for CHAR data. * - ``directoryAliasLength`` - IN - The length of the directoryAlias parameter, in bytes. * - ``fileName`` - IN - The name of the file, as a byte string in the encoding used for CHAR data. * - ``fileNameLength`` - IN - The length of the fileName parameter, in bytes. .. function:: int dpiLob_setFromBytes(dpiLob* lob, const char* value, \ uint64_t valueLength) Replaces all of the data in the LOB with the contents of the provided buffer. The LOB will first be cleared and then the provided data will be written. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - The LOB to which data is to be written. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The buffer from which the data is written. This value can be NULL if the valueLength parameter is 0. * - ``valueLength`` - IN - The number of bytes which will be read from the buffer and written to the LOB. .. function:: int dpiLob_trim(dpiLob* lob, uint64_t newSize) Trims the data in the LOB so that it only contains the specified amount of data. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``lob`` - IN - The LOB which will be trimmed. If the reference is NULL or invalid an error is returned. * - ``newSize`` - IN - The new size of the data in the LOB. For character LOBs, this value is in characters; for binary LOBs this value is in bytes. .. function:: int dpiLob_writeBytes(dpiLob* lob, uint64_t offset, \ const char* value, uint64_t valueLength) Write data to the LOB at the specified offset using the provided buffer as the source. If multiple calls to this function are planned, the LOB should first be opened using the function :func:`dpiLob_openResource()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. **WARNING**: for historical reasons, Oracle stores CLOBs and NCLOBs using the UTF-16 encoding, regardless of what encoding is otherwise in use by the database. The number of characters, however, is defined by the number of UCS-2 codepoints. For this reason, if a character requires more than one UCS-2 codepoint, care must be taken to account for them in the offset parameter. .. parameters-table:: * - ``lob`` - IN - The LOB to which data is to be written. If the reference is NULL or invalid, an error is returned. * - ``offset`` - IN - The offset into the LOB data from which to start writing. The first position is 1. For character LOBs this represents the number of characters from the beginning of the LOB; for binary LOBS, this represents the number of bytes from the beginning of the LOB. * - ``value`` - IN - The buffer from which the data is written. * - ``valueLength`` - IN - The number of bytes which will be read from the buffer and written to the LOB. odpi-5.6.4/doc/src/functions/dpiMsgProps.rst000066400000000000000000000530061510466437300210430ustar00rootroot00000000000000.. _dpiMsgPropsFunctions: ODPI-C Message Properties Functions ----------------------------------- Message properties handles are used to represent the properties of messages that are enqueued and dequeued using advanced queuing. They are created by calling the function :func:`dpiConn_newMsgProps()` and are destroyed by releasing the last reference by calling the function :func:`dpiMsgProps_release()`. .. function:: int dpiMsgProps_addRef(dpiMsgProps* props) Adds a reference to the message properties. This is intended for situations where a reference to the message properties needs to be maintained independently of the reference returned when the handle was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - The message properties to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiMsgProps_getNumAttempts(dpiMsgProps* props, \ int32_t* value) Returns the number of attempts that have been made to dequeue a message. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the number of attempts is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. .. function:: int dpiMsgProps_getCorrelation(dpiMsgProps* props, \ const char** value, uint32_t* valueLength) Returns the correlation supplied by the producer when the message was enqueued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the correlation is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no correlation, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no correlation, the pointer will be populated with the value 0. .. function:: int dpiMsgProps_getDelay(dpiMsgProps* props, int32_t* value) Returns the number of seconds the enqueued message will be delayed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the delay is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. .. function:: int dpiMsgProps_getDeliveryMode(dpiMsgProps* props, \ dpiMessageDeliveryMode* value) Returns the mode that was used to deliver the message. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the message delivery mode is to be retrieved. If the reference is NULL or invalid an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiMessageDeliveryMode`. .. function:: int dpiMsgProps_getEnqTime(dpiMsgProps* props, \ dpiTimestamp* value) Returns the time that the message was enqueued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the enqueue time is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to a :ref:`dpiTimestamp` structure, which will be populated upon successful completion of this function. .. function:: int dpiMsgProps_getExceptionQ(dpiMsgProps* props, \ const char** value, uint32_t* valueLength) Returns the name of the queue to which the message is moved if it cannot be processed successfully. See function :func:`dpiMsgProps_setExceptionQ()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the name of the exception queue is to be retrieved. If the reference is NULL or invalid an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no exception queue name, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no exception queue name, the pointer will be populated with the value 0. .. function:: int dpiMsgProps_getExpiration(dpiMsgProps* props, \ int32_t* value) Returns the number of seconds the message is available to be dequeued. See function :func:`dpiMsgProps_setExpiration()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the expiration is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. .. function:: int dpiMsgProps_getMsgId(dpiMsgProps* props, \ const char** value, uint32_t* valueLength) Returns the id of the message in the queue that generated this message. No value is available until the message has been enqueued or dequeued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the message id is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no message id, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no message id, the pointer will be populated with the value 0. .. function:: int dpiMsgProps_getOriginalMsgId(dpiMsgProps* props, \ const char** value, uint32_t* valueLength) Returns the id of the message in the last queue that generated this message. See function :func:`dpiMsgProps_setOriginalMsgId()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the original message id is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. If there is no original message id, the pointer will be populated with the value NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If there is no original message id, the pointer will be populated with the value 0. .. function:: int dpiMsgProps_getPayload(dpiMsgProps* props, \ dpiObject** obj, const char** value, uint32_t* valueLength) Returns the payload associated with the message properties. The payload can either be an object or an arbitrary series of bytes and is available after a call to :func:`dpiQueue_deqOne()` or :func:`dpiQueue_deqMany()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the payload is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``obj`` - OUT - A reference to an object which will be populated upon successful completion of this function. If the payload is not an object, this value will be NULL. This parameter can also be NULL. * - ``value`` - OUT - A pointer to the value, as a byte string, which will be populated upon successful completion of this function. If the payload is not a series of bytes, this value will be NULL. This parameter can also be NULL. * - ``valueLength`` - OUT - A pointer to the length of the value, in bytes, which will be populated upon successful completion of this function. If the payload is not a series of bytes, this value will be 0. This parameter can also be NULL. .. function:: int dpiMsgProps_getPayloadJson(dpiMsgProps* props, \ dpiJson** json) Returns the payload associated with the message properties, The payload must be a JSON object and is available after the call to :func:`dpiQueue_deqOne()` or :func:`dpiQueue_deqMany()`; otherwise, the value NULL will be returned. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the payload is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``json`` - OUT - A reference to a JSON object which will be populated upon successful completion of this function. If the payload is not a JSON object, this value will be NULL. .. function:: int dpiMsgProps_getPriority(dpiMsgProps* props, int32_t* value) Returns the priority assigned to the message. See function :func:`dpiMsgProps_setPriority()` for more information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the priority is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. .. function:: int dpiMsgProps_getState(dpiMsgProps* props, \ dpiMessageState* value) Returns the state of the message at the time of dequeue. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties from which the message state is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiMessageState`. .. function:: int dpiMsgProps_release(dpiMsgProps* props) Releases a reference to the message properties. A count of the references to the message properties is maintained and when this count reaches zero, the memory associated with the properties is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - The message properties from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiMsgProps_setCorrelation(dpiMsgProps* props, \ const char* value, uint32_t valueLength) Sets the correlation of the message to be dequeued. Special pattern matching characters such as the percent sign (%) and the underscore (_) can be used. If multiple messages satisfy the pattern, the order of dequeuing is undetermined. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the correlation is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the correlation is to be cleared. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiMsgProps_setDelay(dpiMsgProps* props, int32_t value) Sets the number of seconds to delay the message before it can be dequeued. Messages enqueued with a delay are put into the DPI_MSG_STATE_WAITING state. When the delay expires the message is put into the DPI_MSG_STATE_READY state. Dequeuing directly by message id overrides this delay specification. Note that delay processing requires the queue monitor to be started. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the delay is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiMsgProps_setExceptionQ(dpiMsgProps* props, \ const char* value, uint32_t valueLength) Sets the name of the queue to which the message is moved if it cannot be processed successfully. Messages are moved if the number of unsuccessful dequeue attempts has reached the maximum allowed number or if the message has expired. All messages in the exception queue are in the DPI_MSG_STATE_EXPIRED state. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the name of the exception queue is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A byte string in the encoding used for CHAR data, or NULL if the exception queue name is to be cleared. If not NULL, the value must refer to a valid queue name. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiMsgProps_setExpiration(dpiMsgProps* props, int32_t value) Sets the number of seconds the message is available to be dequeued. This value is an offset from the delay. Expiration processing requires the queue monitor to be running. Until this time elapses, the messages are in the queue in the state DPI_MSG_STATE_READY. After this time elapses messages are moved to the exception queue in the DPI_MSG_STATE_EXPIRED state. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the expiration is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiMsgProps_setOriginalMsgId(dpiMsgProps* props, \ const char* value, uint32_t valueLength) Sets the id of the message in the last queue that generated this message. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the original message identifier is to be set. If the reference is NULL or invalid an error is returned. * - ``value`` - IN - A pointer to the bytes making up the message identifier, or NULL if no identifier is to be specified. * - ``valueLength`` - IN - The length of the value parameter in bytes, or 0 if the value parameter is NULL. .. function:: int dpiMsgProps_setPayloadBytes(dpiMsgProps* props, \ const char* value, uint32_t valueLength) Sets the payload for the message as a series of bytes. This value will be used when the message is enqueued using :func:`dpiQueue_enqOne()` or :func:`dpiQueue_enqMany()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the payload is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to the bytes making up the payload. * - ``valueLength`` - IN - The length of the value parameter in bytes. .. function:: int dpiMsgProps_setPayloadJson(dpiMsgProps* props, dpiJson* json) Sets the payload for the message as a JSON object. This value will be used when the message is enqueued using :func:`dpiQueue_enqOne()` or :func:`dpiQueue_enqMany()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the payload is to be set. If the reference is NULL or invalid, an error is returned. * - ``json`` - IN - A reference to the JSON object that will be used as the message payload. If the reference is NULL or invalid, an error is returned. .. function:: int dpiMsgProps_setPayloadObject(dpiMsgProps* props, \ dpiObject* obj) Sets the payload for the message as an object. This value will be used when the message is enqueued using :func:`dpiQueue_enqOne()` or :func:`dpiQueue_enqMany()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the payload is to be set. If the reference is NULL or invalid, an error is returned. * - ``obj`` - IN - A reference to the object that will be used as the message payload. If the reference is NULL or invalid, an error is returned. .. function:: int dpiMsgProps_setPriority(dpiMsgProps* props, int32_t value) Sets the priority assigned to the message. A smaller number indicates a higher priority. The priority can be any number, including negative numbers. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the priority is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiMsgProps_setRecipients(dpiMsgProps *props, \ dpiMsgRecipient *recipients, uint32_t numRecipients) Sets recipients list for the message to be enqueued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``props`` - IN - A reference to the message properties on which the recipients list is to be set. If the reference is NULL or invalid, an error is returned. * - ``recipients`` - IN - A pointer to an array of :ref:`dpiMsgRecipient` structures which indicate to which recipients the message should be sent. * - ``numRecipients`` - IN - The number of recipients in the recipients list. odpi-5.6.4/doc/src/functions/dpiObject.rst000066400000000000000000000403741510466437300205030ustar00rootroot00000000000000.. _dpiObjectFunctions: ODPI-C Object Functions ----------------------- Object handles are used to represent instances of the types created by the SQL command CREATE OR REPLACE TYPE. They are created by calling the function :func:`dpiObjectType_createObject()` or calling the function :func:`dpiObject_copy()` or implicitly by creating a variable of the type DPI_ORACLE_TYPE_OBJECT. The are destroyed when the last reference is released by calling the function :func:`dpiObject_release()`. .. function:: int dpiObject_addRef(dpiObject* obj) Adds a reference to the object. This is intended for situations where a reference to the object needs to be maintained independently of the reference returned when the object was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiObject_appendElement(dpiObject* obj, \ dpiNativeTypeNum nativeTypeNum, dpiData* value) Appends an element with the specified value to the collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object to which the value is to be appended. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection an error is returned. * - ``nativeTypeNum`` - IN - The native type of the data that is to be appended. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``value`` - IN - A pointer to a :ref:`dpiData` structure which contains the value of the element to append to the collection. .. function:: int dpiObject_copy(dpiObject* obj, dpiObject** copiedObj) Creates an independent copy of an object and returns a reference to the newly created object. This reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object which is to be copied. If the reference is NULL or invalid an error is returned. * - ``copiedObj`` - OUT - A pointer to a reference to the object which is created as a copy of the first object, which is populated upon successful completion of this function. .. function:: int dpiObject_deleteElementByIndex(dpiObject* obj, \ int32_t index) Deletes an element from the collection. Note that the position ordinals of the remaining elements are not changed. The delete operation creates *holes* in the collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the element is to be deleted. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - IN - The index of the element that is to be deleted. If no element exists at that index an error is returned. .. function:: int dpiObject_getAttributeValue(dpiObject* obj, \ dpiObjectAttr* attr, dpiNativeTypeNum nativeTypeNum, dpiData* value) Returns the value of one of the object's attributes. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the the attribute is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``attr`` - IN - The attribute which is to be retrieved. The attribute must belong to the same type as the object; otherwise, an error is returned. * - ``nativeTypeNum`` - IN - The native type of the data that is to be retrieved. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``value`` - IN/OUT - A pointer to a :ref:`dpiData` structure which will be populated with the value of the element when this function completes successfully. If the native type is ``DPI_NATIVE_TYPE_BYTES`` and the Oracle type of the attribute is ``DPI_ORACLE_TYPE_NUMBER``, a buffer must be supplied in the value.asBytes.ptr attribute and the maximum length of that buffer must be supplied in the value.asBytes.length attribute before calling this function. For all other conversions, the buffer is supplied by the library and remains valid as long as a reference to the object is held. Note that if the native type is ``DPI_NATIVE_TYPE_OBJECT`` the reference that is returned must be released by a call to :func:`dpiObject_release()`. .. function:: int dpiObject_getElementExistsByIndex(dpiObject* obj, \ int32_t index, int* exists) Returns whether an element exists at the specified index. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object for which an element's existence is to be tested. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - IN - The index into the collection that is to be checked. * - ``exists`` - OUT - A pointer to a boolean value indicating if an element exists at the specified index (1) or not (0), which will be populated when this function completes successfully. .. function:: int dpiObject_getElementValueByIndex(dpiObject* obj, \ int32_t index, dpiNativeTypeNum nativeTypeNum, dpiData* value) Returns the value of the element found at the specified index. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the element is to be retrieved. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - IN - The index into the collection from which the element is to be retrieved. If no element exists at that index, an error is returned. * - ``nativeTypeNum`` - IN - The native type of the data that is to be retrieved. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``value`` - IN/OUT - A pointer to a :ref:`dpiData` structure which will be populated with the value of the element when this function completes successfully. If the native type is ``DPI_NATIVE_TYPE_BYTES`` and the Oracle type of the attribute is ``DPI_ORACLE_TYPE_NUMBER``, a buffer must be supplied in the value.asBytes.ptr attribute and the maximum length of that buffer must be supplied in the value.asBytes.length attribute before calling this function. For all other conversions, the buffer is supplied by the library and remains valid as long as a reference to the object is held. Note that if the native type is ``DPI_NATIVE_TYPE_OBJECT`` the reference that is returned must be released by a call to :func:`dpiObject_release()`. .. function:: int dpiObject_getFirstIndex(dpiObject* obj, int32_t* index, \ int* exists) Returns the first index used in a collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the first index is to be retrieved. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - OUT - A pointer to the first index used in the collection, which will be populated when the function completes successfully. * - ``exists`` - OUT - A pointer to a boolean value specifying whether a first index exists (1) or not (0), which will be populated when the function completes successfully. .. function:: int dpiObject_getLastIndex(dpiObject* obj, int32_t* index, \ int* exists) Returns the last index used in a collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the last index is to be retrieved. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - OUT - A pointer to the last index used in the collection, which will be populated when the function completes successfully. * - ``exists`` - OUT - A pointer to a boolean value specifying whether a last index exists (1) or not (0), which will be populated when the function completes successfully. .. function:: int dpiObject_getNextIndex(dpiObject* obj, int32_t index, \ int32_t* nextIndex, int* exists) Returns the next index used in a collection following the specified index. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the next index is to be retrieved. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - IN - The index after which the next index is to be determined. This does not have to be an actual index in the collection. * - ``nextIndex`` - OUT - A pointer to the next index used in the collection, which will be populated when the function completes successfully and the value of the exists parameter is 1. * - ``exists`` - OUT - A pointer to a boolean value specifying whether a next index exists following the specified index (1) or not (0), which will be populated when the function completes successfully. .. function:: int dpiObject_getPrevIndex(dpiObject* obj, int32_t index, \ int32_t* prevIndex, int* exists) Returns the previous index used in a collection preceding the specified index. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the previous index is to be retrieved. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - IN - The index before which the previous index is to be determined. This does not have to be an actual index in the collection. * - ``prevIndex`` - OUT - A pointer to the previous index used in the collection, which will be populated when the function completes successfully and the value of the exists parameter is 1. * - ``exists`` - OUT - A pointer to a boolean value specifying whether a previous index exists preceding the specified index (1) or not (0), which will be populated when the function completes successfully. .. function:: int dpiObject_getSize(dpiObject* obj, int32_t* size) Returns the number of elements in a collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which the number of elements is to be retrieved. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``size`` - OUT - A pointer to the number of elements in the collection, which will be populated when the function completes successfully. .. function:: int dpiObject_release(dpiObject* obj) Releases a reference to the object. A count of the references to the object is maintained and when this count reaches zero, the memory associated with the object is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiObject_setAttributeValue(dpiObject* obj, \ dpiObjectAttr* attr, dpiNativeTypeNum nativeTypeNum, dpiData* value) Sets the value of one of the object's attributes. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object on which the attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``attr`` - IN - The attribute which is to be set. The attribute must belong to the same type as the object; otherwise, an error is returned. * - ``nativeTypeNum`` - IN - The native type of the data that is to be set. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``value`` - IN - A pointer to a :ref:`dpiData` structure which contains the value to which the attribute is to be set. .. function:: int dpiObject_setElementValueByIndex(dpiObject* obj, \ int32_t index, dpiNativeTypeNum nativeTypeNum, dpiData* value) Sets the value of the element found at the specified index. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object in which the element is to be set. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``index`` - IN - The index into the collection at which the element is to be set. * - ``nativeTypeNum`` - IN - The native type of the data that is to be set. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``value`` - IN - A pointer to a :ref:`dpiData` structure which contains the value of the element to place at the specified index. .. function:: int dpiObject_trim(dpiObject* obj, uint32_t numToTrim) Trims a number of elements from the end of a collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``obj`` - IN - The object from which a number of elements are to be trimmed. If the reference is NULL or invalid, an error is returned. Likewise, if the object does not refer to a collection, an error is returned. * - ``numToTrim`` - IN - The number of elements to trim from the end of the collection. If the number of of elements to trim exceeds the current size of the collection an error is returned. odpi-5.6.4/doc/src/functions/dpiObjectAttr.rst000066400000000000000000000041461510466437300213330ustar00rootroot00000000000000.. _dpiObjectAttrFunctions: ODPI-C Object Attribute Functions --------------------------------- Object attribute handles are used to represent the attributes of types such as those created by the SQL command CREATE OR REPLACE TYPE. They are created by calling the function :func:`dpiObjectType_getAttributes()` and are destroyed when the last reference is released by calling the function :func:`dpiObjectAttr_release()`. .. function:: int dpiObjectAttr_addRef(dpiObjectAttr* attr) Adds a reference to the attribute. This is intended for situations where a reference to the attribute needs to be maintained independently of the reference returned when the attribute was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``attr`` - IN - The attribute to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiObjectAttr_getInfo(dpiObjectAttr* attr, \ dpiObjectAttrInfo* info) Returns information about the attribute. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``attr`` - IN - A reference to the attribute whose information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a :ref:`dpiObjectAttrInfo` structure which will be populated with information about the attribute. .. function:: int dpiObjectAttr_release(dpiObjectAttr* attr) Releases a reference to the attribute. A count of the references to the attribute is maintained and when this count reaches zero, the memory associated with the attribute is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``attr`` - IN - The attribute from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiObjectType.rst000066400000000000000000000105531510466437300213410ustar00rootroot00000000000000.. _dpiObjectTypeFunctions: ODPI-C Object Type Functions ---------------------------- Object type handles are used to represent types such as those created by the SQL command CREATE OR REPLACE TYPE. They are created using the function :func:`dpiConn_getObjectType()` or implicitly when fetching from a column containing objects by calling the function :func:`dpiStmt_getQueryInfo()`. Object types are also retrieved when used as attributes in another object by calling the function :func:`dpiObjectAttr_getInfo()` or as the element type of a collection by calling the function :func:`dpiObjectType_getInfo()`. They are destroyed when the last reference is released by calling the function :func:`dpiObjectType_release()`. .. function:: int dpiObjectType_addRef(dpiObjectType* objType) Adds a reference to the object type. This is intended for situations where a reference to the object type needs to be maintained independently of the reference returned when the object type was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``objType`` - IN - The object type to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiObjectType_createObject(dpiObjectType* objType, \ dpiObject** obj) Creates an object of the specified type and returns a reference to it. This reference should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``objType`` - IN - A reference to the object type whose information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``obj`` - OUT - A pointer to a reference to the created object, which will be populated when the function completes successfully. .. function:: int dpiObjectType_getAttributes(dpiObjectType* objType, \ uint16_t numAttributes, dpiObjectAttr** attributes) Returns the list of attributes that belong to the object type. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``objType`` - IN - A reference to the object type whose attributes are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numAttributes`` - OUT - The number of attributes which will be returned. This value can be determined using the function :func:`dpiObjectType_getInfo()`. * - ``attributes`` - OUT - An array of references to the object's attributes, which will be populated with attribute references upon successful completion of this function. It is assumed that the array is large enough to hold numAttributes attribute references. These references must be released when they are no longer required by calling the function :func:`dpiObjectAttr_release()`. .. function:: int dpiObjectType_getInfo(dpiObjectType* objType, \ dpiObjectTypeInfo* info) Returns information about the object type. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``objType`` - IN - A reference to the object type whose information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a :ref:`dpiObjectTypeInfo` structure which will be populated with information about the object type when the function completes successfully. .. function:: int dpiObjectType_release(dpiObjectType* objType) Releases a reference to the object type. A count of the references to the object type is maintained and when this count reaches zero, the memory associated with the object type is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``objType`` - IN - The object type from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiPool.rst000066400000000000000000000566411510466437300202120ustar00rootroot00000000000000.. _dpiPoolFunctions: ODPI-C Pool Functions --------------------- Pool handles are used to represent session pools. They are created using the function :func:`dpiPool_create()` and can be closed by calling the function :func:`dpiPool_close()` or releasing the last reference to the pool by calling the function :func:`dpiPool_release()`. Pools can be used to create connections by calling the function :func:`dpiPool_acquireConnection()`. .. function:: int dpiPool_acquireConnection(dpiPool* pool, \ const char* userName, uint32_t userNameLength, \ const char* password, uint32_t passwordLength, \ dpiConnCreateParams* params, dpiConn** conn) Acquires a connection from the pool and returns a reference to it. This reference should be released by calling :func:`dpiConn_release()` as soon as it is no longer needed, which will also return the connection back to the pool for subsequent calls to this function. The connection can be returned back to the pool earlier by calling :func:`dpiConn_close()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - The pool from which a connection is to be acquired. If the reference is NULL or invalid, an error is returned. * - ``userName`` - IN - The name of the user used for authenticating the user, as a byte string in the encoding used for CHAR data. NULL is also acceptable if external authentication is being requested or credentials were supplied when the pool was created. * - ``userNameLength`` - IN - The length of the userName parameter, in bytes, or 0 if the userName parameter is NULL. * - ``password`` - IN - The password to use for authenticating the user, as a byte string in the encoding used for CHAR data. NULL is also acceptable if external authentication is being requested or if credentials were supplied when the pool was created. * - ``passwordLength`` - IN - The length of the password parameter, in bytes, or 0 if the password parameter is NULL. * - ``params`` - IN - A pointer to a :ref:`dpiConnCreateParams` structure which is used to specify parameters for connection creation. NULL is also acceptable in which case all default parameters will be used when creating the connection. * - ``conn`` - OUT - A reference to the connection that is acquired from the pool. This value is populated upon successful completion of this function. .. function:: int dpiPool_addRef(dpiPool* pool) Adds a reference to the pool. This is intended for situations where a reference to the pool needs to be maintained independently of the reference returned when the pool was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - The pool to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiPool_close(dpiPool* pool, dpiPoolCloseMode closeMode) Closes the pool and makes it unusable for further activity. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool which is to be closed. If the reference is NULL or invalid, an error is returned. * - ``closeMode`` - IN - One or more of the values from the enumeration :ref:`dpiPoolCloseMode`, OR'ed together. .. function:: int dpiPool_create(const dpiContext* context, \ const char* userName, uint32_t userNameLength, \ const char* password, uint32_t passwordLength, \ const char* connectString, uint32_t connectStringLength, \ dpiCommonCreateParams* commonParams, \ dpiPoolCreateParams* createParams, dpiPool** pool) Creates a session pool which creates and maintains a group of stateless sessions to the database. The main benefit of session pooling is performance since making a connection to the database is a time-consuming activity, especially when the database is remote. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. If a failure occurs, the errorInfo structure is filled in with error information. .. parameters-table:: * - ``context`` - IN - The context handle created earlier using the function :func:`dpiContext_createWithParams()`. If the handle is NULL or invalid, an error is returned. * - ``userName`` - IN - The name of the user used for authenticating sessions, as a byte string in the encoding used for CHAR data. NULL is also acceptable if external authentication is being requested or if a heterogeneous pool is being created. * - ``userNameLength`` - IN - The length of the userName parameter, in bytes, or 0 if the userName parameter is NULL. * - ``password`` - IN - The password to use for authenticating sessions, as a byte string in the encoding used for CHAR data. NULL is also acceptable if external authentication is being requested or if a heterogeneous pool is being created. * - ``passwordLength`` - IN - The length of the password parameter, in bytes, or 0 if the password parameter is NULL. * - ``connectString`` - IN - The connect string identifying the database to which connections are to be established by the session pool, as a byte string in the encoding used for CHAR data. NULL is also acceptable for local connections (identified by the environment variable ORACLE_SID). * - ``connectStringLength`` - IN - The length of the connectString parameter, in bytes, or 0 if the connectString parameter is NULL. * - ``commonParams`` - IN - A pointer to a :ref:`dpiCommonCreateParams` structure which is used to specify context parameters for pool creation. NULL is also acceptable in which case all default parameters will be used when creating the pool. * - ``createParams`` - IN - A pointer to a :ref:`dpiPoolCreateParams` structure which is used to specify parameters for pool creation. NULL is also acceptable in which case all default parameters will be used for pool creation. * - ``pool`` - OUT - A pointer to a reference to the pool that is created. Call :func:`dpiPool_release()` when the reference is no longer needed. .. function:: int dpiPool_getBusyCount(dpiPool* pool, uint32_t* value) Returns the number of sessions in the pool that are busy. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the number of busy sessions is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getEncodingInfo(dpiPool* pool, \ dpiEncodingInfo* info) Returns the encoding information used by the pool. This will be equivalent to the values passed when the pool was created, or the values retrieved from the environment variables NLS_LANG and NLS_NCHAR. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool whose encoding information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a :ref:`dpiEncodingInfo` structure which will be populated with the encoding information used by the pool. .. function:: int dpiPool_getGetMode(dpiPool* pool, dpiPoolGetMode* value) Returns the mode used for acquiring or getting connections from the pool. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the mode used for acquiring connections is to be retrieved. If the reference is NULL or invalid an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getMaxLifetimeSession(dpiPool* pool, \ uint32_t* value) Returns the maximum lifetime a pooled session may exist, in seconds. Sessions in use will not be closed. They become candidates for termination only when they are released back to the pool and have existed for longer then the returned value. Note that termination only occurs when the pool is accessed. The value 0 means that there is no maximum length of time that a pooled session may exist. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the maximum lifetime of sessions is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getMaxSessionsPerShard(dpiPool* pool, \ uint32_t* value) Returns the maximum sessions per shard. This parameter is used for balancing shards. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the maximum sessoins per shard is to be retrieved. If the refernece is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getOpenCount(dpiPool* pool, uint32_t* value) Returns the number of sessions in the pool that are open. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the number of open sessions is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getPingInterval(dpiPool* pool, int* value) Returns the ping interval duration (in seconds), which is used to check the healthiness of idle connections before getting checked out. A negative value indicates this check is disabled. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the ping interval is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getSodaMetadataCache(dpiPool* pool, int* enabled) Returns whether or not the SODA metadata cache is enabled or not. The SODA metadata cache requires Oracle Client 21.3, or later. It is also available in Oracle Client 19 from 19.11. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the status of the SODA metadata cache is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``enabled`` - OUT - A pointer to an integer defining whether the SODA metadata cache is enabled (1) or not (0), which will be populated upon successful completion of this function. .. function:: int dpiPool_getStmtCacheSize(dpiPool* pool, \ uint32_t* cacheSize) Returns the default size of the statement cache for sessions in the pool, in number of statements. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the default size of the statement cache is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``cacheSize`` - OUT - A pointer to the default size of the statement cache, which will be populated upon successful completion of this function. .. function:: int dpiPool_getTimeout(dpiPool* pool, uint32_t* value) Returns the length of time (in seconds) after which idle sessions in the pool are terminated. Note that termination only occurs when the pool is accessed. A value of 0 means that no ide sessions are terminated. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the timeout for idle sessions is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_getWaitTimeout(dpiPool* pool, uint32_t* value) Returns the amount of time (in milliseconds) that the caller will wait for a session to become available in the pool before returning an error. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool from which the wait timeout is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiPool_reconfigure(dpiPool* pool, uint32_t minSessions, \ uint32_t maxSessions, uint32 sessionIncrement) Changes pool configuration corresponding to members :member:`dpiPoolCreateParams.minSessions`, :member:`dpiPoolCreateParams.maxSessions` and :member:`dpiPoolCreateParams.sessionIncrement` to the specified values. Connections will be created as needed if the value of `minSessions` is increased. Connections will be dropped from the pool as they are released back to the pool if `minSessions` is decreased. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool which needs to be reconfigured. If the reference is NULL or invalid, an error is returned. * - ``minSessions`` - IN - New value for the minimum number of sessions that should be maintained. * - ``maxSessions`` - IN - New value for the maximum number of sessions that may be retained in the pool. * - ``sessionIncrement`` - IN - New value for the number of sessions that will be created each time the pool needs to be expanded. .. function:: int dpiPool_release(dpiPool* pool) Releases a reference to the pool. A count of the references to the pool is maintained and when this count reaches zero, the memory associated with the pool is freed and the session pool is closed if that has not already taken place using the function :func:`dpiPool_close()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - The pool from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiPool_setAccessToken(dpiPool* pool, \ dpiAccessToken* accessToken) The function is used to manually set the token and private key for a session pool. After pool creation it can be used to periodically reset the token and private key to avoid the need for the pool token callback function :member:`accessTokenCallback` to be called during pool growth. This function may also be useful for testing. By setting an expired token and key the subsequent pool callback function behavior can be seen without waiting for normal token expiry. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool where authentication parameters will be set. If the pool parameter is NULL or invalid, an error is returned. * - ``accessToken`` - IN - A pointer to a :ref:`dpiAccessToken` structure which is used to specify parameters for token based authentication. If the pointer is NULL, an error is returned. .. function:: int dpiPool_setGetMode(dpiPool* pool, dpiPoolGetMode value) Sets the mode used for acquiring or getting connections from the pool. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the mode used for acquiring connections is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiPool_setMaxLifetimeSession(dpiPool* pool, uint32_t value) Sets the maximum lifetime a pooled session may exist, in seconds. Sessions in use will not be closed. They become candidates for termination only when they are released back to the pool and have existed for longer then the specified value. Note that termination only occurs when the pool is accessed. The value 0 means that there is no maximum length of time that a pooled session may exist. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the maximum lifetime of sessions is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiPool_setMaxSessionsPerShard(dpiPool* pool, uint32_t value) Sets the maximum number of sessions per shard. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the maximum sessions per shard is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiPool_setPingInterval(dpiPool* pool, int value) Sets the ping interval duration (in seconds) which is used to to check for healthiness of sessions. If this time has passed since the last time the session was checked out a ping will be performed. A negative value will disable this check. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the ping interval is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiPool_setSodaMetadataCache(dpiPool* pool, int enabled) Sets whether the SODA metadata cache is enabled or not. Enabling the SODA metadata cache can significantly improve the performance of repeated calls to methods :func:`dpiSodaDb_createCollection()` (when not specifying a value for the metadata parameter) and :func:`dpiSodaDb_openCollection()`. Note that the cache can become out of date if changes to the metadata of cached collections are made externally. The SODA metadata cache requires Oracle Client 21.3, or later. It is also available in Oracle Client 19 from 19.11. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the SODA metadata cache is to be enabled or disabled. If the reference is NULL or invalid, an error is returned. * - ``enabled`` - IN - Identifies if the cache should be enabled (1) or not (0). .. function:: int dpiPool_setStmtCacheSize(dpiPool* pool, uint32_t cacheSize) Sets the default size of the statement cache for sessions in the pool. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the default size of the statement cache is to be set. If the reference is NULL or invalid, an error is returned. * - ``cacheSize`` - IN - The new size of the statement cache, in number of statements. .. function:: int dpiPool_setTimeout(dpiPool* pool, uint32_t value) Sets the amount of time (in seconds) after which idle sessions in the pool are terminated. Note that termination only occurs when the pool is accessed. A value of zero will result in no idle sessions being terminated. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the timeout for idle sessions is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. .. function:: int dpiPool_setWaitTimeout(dpiPool* pool, uint32_t value) Sets the amount of time (in milliseconds) that the caller should wait for a session to be available in the pool before returning with an error. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``pool`` - IN - A reference to the pool in which the wait timeout is to be set. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - The value to set. odpi-5.6.4/doc/src/functions/dpiQueue.rst000066400000000000000000000154251510466437300203600ustar00rootroot00000000000000.. _dpiQueue: ODPI-C Queue Functions ---------------------- Queue handles are used to represent Advanced Queueing (AQ) queues. They are created by calling the function :func:`dpiConn_newQueue()` and are destroyed when the last reference is released by calling the function :func:`dpiQueue_release()`. .. function:: int dpiQueue_addRef(dpiQueue* queue) Adds a reference to the queue. This is intended for situations where a reference to the queue needs to be maintained independently of the reference returned when the queue was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiQueue_deqMany(dpiQueue* queue, uint32_t* numProps, \ dpiMsgProps** props) Dequeues multiple messages from the queue. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue from which messages are to be dequeued. If the reference is NULL or invalid, an error is returned. * - ``numProps`` - IN/OUT - A pointer to the number of elements in the props array. When the function is called, the value refers to the length of the props array and the maximum number of messages that should be dequeued. After the function has completed successfully, the value refers to the number of messages that were actually dequeued from the queue. * - ``props`` - OUT - An array of references to message properties which will be populated upon successful completion of this function. Each of these references should be released when they are no longer needed by calling the function :func:`dpiMsgProps_release()`. .. function:: int dpiQueue_deqOne(dpiQueue* queue, dpiMsgProps** props) Dequeues a single message from the queue. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue from which the messages is to be dequeued. If the reference is NULL or invalid, an error is returned. * - ``props`` - OUT - A pointer to a reference to a message property which will be populated upon successful completion of this function. This reference should be released when it is no longer needed by calling the function :func:`dpiMsgProps_release()`. If no messages are available, this reference will be NULL. .. function:: int dpiQueue_enqMany(dpiQueue* queue, uint32_t numProps, \ dpiMsgProps** props) Enqueues multiple messages into the queue. Warning: calling this function in parallel on different connections acquired from the same pool may fail due to Oracle bug 29928074. Ensure that this function is not run in parallel, use standalone connections or connections from different pools, or make multiple calls to :func:`dpiQueue_enqOne()` instead. The function :func:`dpiQueue_deqMany()` call is not affected. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue into which the messages are to be enqueued. If the reference is NULL or invalid, an error is returned. * - ``numProps`` - IN/OUT - The number of messages that are to be enqueued. * - ``props`` - IN - An array of references to message properties that are to be enqueued. The length of the array is specified by the numProps parameter. Each of the message properties must have the right type of payload associated before calling this method or an error will occur. .. function:: int dpiQueue_enqOne(dpiQueue* queue, dpiMsgProps* props) Enqueues a single mesasge into the queue. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue into which the message is to be enqueued. If the reference is NULL or invalid, an error is returned. * - ``props`` - IN - A reference to the message that is to be enqueued. The message properties must have the right type of payload associated before calling this method or an error will occur. .. function:: int dpiQueue_getDeqOptions(dpiQueue* queue, \ dpiDeqOptions** options) Returns a reference to the dequeue options associated with the queue. These options affect how messages are dequeued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue from which the dequeue options are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``options`` - OUT - A reference to the dequeue options associated with the queue which will be populated upon successful completion of this function. This reference is owned by the queue and will remain valid as long as a reference to the queue is held. .. function:: int dpiQueue_getEnqOptions(dpiQueue* queue, \ dpiEnqOptions** options) Returns a reference to the enqueue options associated with the queue. These options affect how messages are enqueued. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue from which the enqueue options are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``options`` - OUT - A reference to the enqueue options associated with the queue which will be populated upon successful completion of this function. This reference is owned by the queue and will remain valid as long as a reference to the queue is held. .. function:: int dpiQueue_release(dpiQueue* queue) Releases a reference to the queue. A count of the references to the queue is maintained and when this count reaches zero, the memory associated with the queue is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``queue`` - IN - The queue from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiRowid.rst000066400000000000000000000045421510466437300203560ustar00rootroot00000000000000.. _dpiRowidFunctions: ODPI-C Rowid Functions ---------------------- Rowid handles are used to represent the unique identifier of a row in the database. They cannot be created or set directly but are created implicitly when a variable of type DPI_ORACLE_TYPE_ROWID is created. They are destroyed when the last reference is released by a call to the function :func:`dpiRowid_release()`. .. function:: int dpiRowid_addRef(dpiRowid* rowid) Adds a reference to the rowid. This is intended for situations where a reference to the rowid needs to be maintained independently of the reference returned when the rowid was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``rowid`` - IN - The rowid to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiRowid_getStringValue(dpiRowid* rowid, \ const char** value, uint32_t* valueLength) Returns the sting (base64) representation of the rowid. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``rowid`` - IN - The rowid from which the string representation is to be returned. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the value as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference is held to the rowid. * - ``valueLength`` - OUT - A pointer to the length of the value parameter, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiRowid_release(dpiRowid* rowid) Releases a reference to the rowid. A count of the references to the rowid is maintained and when this count reaches zero, the memory associated with the rowid is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``rowid`` - IN - The rowid from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiSodaColl.rst000066400000000000000000000666561510466437300210100ustar00rootroot00000000000000.. _dpiSodaCollFunctions: ODPI-C SODA Collection Functions -------------------------------- SODA collection handles are used to represent SODA collections in the database. They are created by calling one of the functions :func:`dpiSodaDb_createCollection()`, :func:`dpiSodaDb_openCollection()` or :func:`dpiSodaCollCursor_getNext()` and are destroyed when the last reference is released by calling the function :func:`dpiSodaColl_release()`. See `this tracking issue `__ for known issues with SODA. .. function:: int dpiSodaColl_addRef(dpiSodaColl* coll) Adds a reference to the SODA collection. This is intended for situations where a reference to the collection needs to be maintained independently of the reference returned when the collection was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaColl_createIndex(dpiSodaColl* coll, \ const char* indexSpec, uint32_t indexSpecLength, uint32_t flags) Create an index on the collection, which can improve the performance of SODA query-by-examples (QBE). An index is defined by a specification, which is a JSON-encoded string that specifies how particular QBE patterns are to be indexed for quicker matching. See `Overview of SODA indexing `__. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection on which the index is to be created. If the reference is NULL or invalid, an error is returned. * - ``indexSpec`` - IN - The JSON specification of the index as a byte string in the encoding used for CHAR data. * - ``indexSpecLength`` - IN - The length of the specification of the index, in bytes. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. .. function:: int dpiSodaColl_drop(dpiSodaColl* coll, uint32_t flags, \ int* isDropped) Drops a SODA collection from the database. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection which is to be dropped. If the reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``isDropped`` - OUT - A pointer to a boolean which indicates whether the collection was dropped (1) or not (0). If this information is not needed, NULL can also be passed. .. function:: int dpiSodaColl_dropIndex(dpiSodaColl* coll, const char* name, \ uint32_t nameLength, uint32_t flags, int* isDropped) Drop an index on the collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection on which the index is to be dropped. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - The name of the index that is to be dropped as a byte string in the encoding used for CHAR data. * - ``nameLength`` - IN - The length of the index name, in bytes. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``isDropped`` - OUT - A pointer to a boolean which indicates whether the specified index was dropped (1) or not (0). If this information is not needed, NULL can also be passed. .. function:: int dpiSodaColl_find(dpiSodaColl* coll, \ const dpiSodaOperOptions* options, uint32_t flags, \ dpiSodaDocCursor** cursor) Finds all of the documents in the collection that match the specified options. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection which is to be searched. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a structure of type :ref:`dpiSodaOperOptions` which specifies options for restricting the number of documents returned. This value can also be NULL which will result in all documents in the collection being returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``cursor`` - OUT - A pointer to a reference to the cursor that is populated if the function completes successfully. The reference that is returned should be released using :func:`dpiSodaDocCursor_release()` when it is no longer needed. .. function:: int dpiSodaColl_findOne(dpiSodaColl* coll, \ const dpiSodaOperOptions* options, uint32_t flags, dpiSodaDoc** doc) Finds a single document in the collection that matches the specified options. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection which is to be searched. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a structure of type :ref:`dpiSodaOperOptions` which specifies options for restricting the document that is returned. This value can also be NULL which will result in the first document in the collection being returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``doc`` - OUT - A pointer to a reference to the document that is populated if the function completes successfully. The reference that is returned should be released using :func:`dpiSodaDoc_release()` when it is no longer needed. If no document matches the specified options, the value NULL is returned instead. .. function:: int dpiSodaColl_getDataGuide(dpiSodaColl* coll, \ uint32_t flags, dpiSodaDoc** doc) Returns a document containing the data guide for the collection. See `JSON Data Guide `__. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection from which the data guide is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``doc`` - OUT - A pointer to a reference to the document that is populated if the function completes successfully. The document reference that is returned should be released using :func:`dpiSodaDoc_release()` when it is no longer needed. If no data guide is available because the collection contains no documents, then a NULL reference is returned. .. function:: int dpiSodaColl_getDocCount(dpiSodaColl* coll, \ const dpiSodaOperOptions* options, uint32_t flags, uint64_t* count) Returns the number of documents in the collection that match the specified options. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection which is to be searched. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a structure of type :ref:`dpiSodaOperOptions` which specifies options for restricting the number of documents found. This value can also be NULL which will result in all of the documents in the collection being counted. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``count`` - OUT - A pointer to a count of the number of documents found that is populated if the function completes successfully. .. function:: int dpiSodaColl_getMetadata(dpiSodaColl* coll, \ const char** value, uint32_t* valueLength) Returns the metadata for the collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection from which the metadata is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to the collection metadata, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the collection is held. * - ``valueLength`` - OUT - A pointer to the length of the collection metadata, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaColl_getName(dpiSodaColl* coll, \ const char** value, uint32_t* valueLength) Returns the name of the collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection from which the name is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - IN - A pointer to the collection name, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The string returned will remain valid as long as a reference to the collection is held. * - ``valueLength`` - OUT - A pointer to the length of the collection name, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaColl_insertMany(dpiSodaColl* coll, uint32_t numDocs, \ dpiSodaDoc** docs, uint32_t flags, dpiSodaDoc** insertedDocs) Inserts multiple documents into the collection and optionally returns result documents containing information about the newly inserted documents. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. On failure the offset attribute in the :ref:`dpiErrorInfo` structure will contain the index into the SODA document handles array where the error took place. NOTE: this function requires Oracle Client 18.5 or higher in addition to the usual SODA requirements and is currently available only as a preview. .. parameters-table:: * - ``coll`` - IN - A reference to the collection into which the documents are to be inserted. If the reference is NULL or invalid, an error is returned. * - ``numDocs`` - IN - The length of the arrays passed for the docs and insertedDocs parameters. * - ``docs`` - IN - An array of SODA document handles which will be inserted into the collection. The length of the array is determined by the numDocs parameter. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``insertedDocs`` - OUT - A pointer to an array of document references that will be populated upon successful completion of this function. The length of the array is determined by the numDocs parameter. Call the function :func:`dpiSodaDoc_release()` for each of the elements of this array when the references contained in the array are no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_insertManyWithOptions(dpiSodaColl* coll, \ uint32_t numDocs, dpiSodaDoc** docs, dpiSodaOperOptions* options, \ uint32_t flags, dpiSodaDoc** insertedDocs) Inserts multiple documents into the collection and optionally returns result documents containing information about the newly inserted documents. In addition, options can be supplied to modify how the documents are inserted or returned. This function requires Oracle Client 21.3 or higher to be used in addition to the normal SODA requirements (also available in Oracle Client 19 from 19.11). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. On failure the offset attribute in the :ref:`dpiErrorInfo` structure will contain the index into the SODA document handles array where the error took place. .. parameters-table:: * - ``coll`` - IN - A reference to the collection into which the documents are to be inserted. If the reference is NULL or invalid, an error is returned. * - ``numDocs`` - IN - The length of the arrays passed for the docs and insertedDocs parameters. * - ``docs`` - IN - An array of SODA document handles which will be inserted into the collection. The length of the array is determined by the numDocs parameter. * - ``options`` - IN - A pointer to a :ref:`dpiSodaOperOptions ` structure containing any desired options, or NULL. If the value is NULL, this function behaves identically to :func:`dpiSodaColl_insertMany()`. Options can only be specified with Oracle Client 21.3 or higher (also available in Oracle Client 19 from 19.11). * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``insertedDocs`` - OUT - A pointer to an array of document references that will be populated upon successful completion of this function. The length of the array is determined by the numDocs parameter. Call the function :func:`dpiSodaDoc_release()` for each of the elements of this array when the references contained in the array are no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_insertOne(dpiSodaColl* coll, dpiSodaDoc* doc, \ uint32_t flags, dpiSodaDoc** insertedDoc) Inserts a document into the collection and optionally returns it. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection into which the document is to be inserted. If the reference is NULL or invalid, an error is returned. * - ``doc`` - IN - A reference to the document which is to be inserted into the collection. If the reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``insertedDoc`` - OUT - A pointer to a document reference that will be populated upon successful completion of this function. Call the function :func:`dpiSodaDoc_release()` when it is no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_insertOneWithOptions(dpiSodaColl* coll, \ dpiSodaDoc* doc, dpiSodaOperOptions* options, uint32_t flags, \ dpiSodaDoc** insertedDoc) Inserts a document into the collection and optionally returns it. In addition, options can be supplied to modify how the document is inserted or returned. This method requires Oracle Client 21.3 or higher to be used in addition to the normal SODA requirements (also available in Oracle Client 19 from 19.11). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection into which the document is to be inserted. If the reference is NULL or invalid, an error is returned. * - ``doc`` - IN - A reference to the document which is to be inserted into the collection. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a :ref:`dpiSodaOperOptions ` structure containing any desired options, or NULL. If the value is NULL, this function behaves identically to :func:`dpiSodaColl_insertOne()`. Options can only be specified with Oracle Client 21.3 or higher (also available in Oracle Client 19 from 19.11). * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``insertedDoc`` - OUT - A pointer to a document reference that will be populated upon successful completion of this function. Call the function :func:`dpiSodaDoc_release()` when it is no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_listIndexes(dpiSodaColl* coll, \ uint32_t flags, dpiStringList* list) Returns a list of indexes associated with the collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection from which the list of indexes is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``list`` - OUT - A pointer to a structure of type :ref:`dpiStringList` which is populated if the function completes successfully. The memory associated with this list should be freed by calling :func:`dpiContext_freeStringList()` when it is no longer needed. .. function:: int dpiSodaColl_release(dpiSodaColl* coll) Releases a reference to the SODA collection. A count of the references to the collection is maintained and when this count reaches zero, the memory associated with the collection is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaColl_remove(dpiSodaColl* coll, \ const dpiSodaOperOptions* options, uint32_t flags, uint64_t* count) Removes all of the documents in the collection that match the specified options. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection from which documents are to be removed. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a structure of type :ref:`dpiSodaOperOptions` which specifies options for restricting the number of documents removed. This value can also be NULL which will result in all documents in the collection being removed. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``count`` - OUT - A pointer to a count of the number of documents removed that is populated if the function completes successfully. .. function:: int dpiSodaColl_replaceOne(dpiSodaColl* coll, \ const dpiSodaOperOptions* options, dpiSodaDoc* doc, uint32_t flags, \ int* replaced, dpiSodaDoc** replacedDoc) Replaces the single document in the collection matching the given options with the new document. .. parameters-table:: * - ``coll`` - IN - A reference to the collection in which the document is to be replaced. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a structure of type :ref:`dpiSodaOperOptions` which identifies options for specifying the document which is to be replaced. Currently at least the :member:`dpiSodaOperOptions.key` member must be specified or the error "ORA-40734: key for the document to replace must be specified using the key attribute" will be raised. * - ``doc`` - IN - A reference to the document which is to replace the document in the collection found using the provided options. If the reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``replaced`` - OUT - A pointer to a boolean value indicating if the document was replaced (1) or not (0). This parameter may also be NULL if this information is not required. * - ``replacedDoc`` - OUT - A pointer to a document reference which will be populated when this function returns successfully. Call the function :func:`dpiSodaDoc_release()` when the reference is no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_save(dpiSodaColl* coll, dpiSodaDoc* doc, \ uint32_t flags, dpiSodaDoc** savedDoc) Saves a document into the collection. This method is equivalent to :func:`dpiSodaColl_insertOne()` except that if client-assigned keys are used, and the document with the specified key already exists in the collection, it will be replaced with the input document. This method requires Oracle Client 19.9 or higher to be used in addition to the normal SODA requirements. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection in which the document is to be saved. If the reference is NULL or invalid, an error is returned. * - ``doc`` - IN - A reference to the document which is to be saved into the collection. If the reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``savedDoc`` - OUT - A pointer to a document reference which will be populated when this function returns successfully. Call the function :func:`dpiSodaDoc_release()` when the reference is no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_saveWithOptions(dpiSodaColl* coll, \ dpiSodaDoc* doc, dpiSodaOperOptions* options, uint32_t flags, \ dpiSodaDoc** savedDoc) Saves a document into the collection. This method is equivalent to :func:`dpiSodaColl_insertOneWithOptions()` except that if client-assigned keys are used, and the document with the specified key already exists in the collection, it will be replaced with the input document. This method requires Oracle Client 21.3 or higher to be used in addition to the normal SODA requirements (also available in Oracle Client 19 from 19.11). The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection in which the document is to be saved. If the reference is NULL or invalid, an error is returned. * - ``doc`` - IN - A reference to the document which is to be saved into the collection. If the reference is NULL or invalid, an error is returned. * - ``options`` - IN - A pointer to a :ref:`dpiSodaOperOptions ` structure containing any desired options, or NULL. If the value is NULL, this function behaves identically to :func:`dpiSodaColl_save()`. Options can only be specified with Oracle Client 21.3 or higher (also available in Oracle Client 19 from 19.11). * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``savedDoc`` - OUT - A pointer to a document reference which will be populated when this function returns successfully. Call the function :func:`dpiSodaDoc_release()` when the reference is no longer needed. This parameter can also be NULL if this information is not required. .. function:: int dpiSodaColl_truncate(dpiSodaColl* coll) Removes all of the documents in a SODA collection in a similar manner to a TRUNCATE TABLE statement. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``coll`` - IN - A reference to the collection in which all of the documents are to be removed. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiSodaCollCursor.rst000066400000000000000000000061061510466437300221660ustar00rootroot00000000000000.. _dpiSodaCollCursorFunctions: ODPI-C SODA Collection Cursor Functions --------------------------------------- SODA collection cursor handles are used to represent SODA collection cursors. They are created by calling the function :func:`dpiSodaDb_getCollections()` and are destroyed when the last reference is released by calling the function :func:`dpiSodaCollCursor_release()`. See `this tracking issue `__ for known issues with SODA. .. function:: int dpiSodaCollCursor_addRef(dpiSodaCollCursor* cursor) Adds a reference to the SODA collection cursor. This is intended for situations where a reference to the cursor needs to be maintained independently of the reference returned when the cursor was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - The cursor to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaCollCursor_close(dpiSodaCollCursor* cursor) Closes the cursor and makes it unusable for further work immediately, rather than when the reference count reaches zero. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - A reference to the cursor which is to be closed. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaCollCursor_getNext(dpiSodaCollCursor* cursor, \ uint32_t flags, dpiSodaColl** coll) Gets the next collection from the cursor, if there is one. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - The cursor from which the next collection is to be retrieved. The reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. Only the value DPI_SODA_FLAGS_DEFAULT is currently supported. * - ``coll`` - OUT - A pointer to a reference to the next collection in the cursor, if one exists. If no further collections are available from the cursor, NULL is returned instead. The function :func:`dpiSodaColl_release()` should be called when the collection is no longer required. .. function:: int dpiSodaCollCursor_release(dpiSodaCollCursor* cursor) Releases a reference to the SODA collection cursor. A count of the references to the cursor is maintained and when this count reaches zero, the memory associated with the cursor is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - The cursor from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiSodaDb.rst000066400000000000000000000270421510466437300204260ustar00rootroot00000000000000.. _dpiSodaDbFunctions: ODPI-C SODA Database Functions ------------------------------ SODA database handles are used to represent connections to the SODA database. They are created by calling the function :func:`dpiConn_getSodaDb()`. They are destroyed when the last reference is released by calling :func:`dpiSodaDb_release()`. See `this tracking issue `__ for known issues with SODA. .. function:: int dpiSodaDb_addRef(dpiSodaDb* db) Adds a reference to the SODA database. This is intended for situations where a reference to the SODA database needs to be maintained independently of the reference returned when the database was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - The database to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaDb_createCollection(dpiSodaDb* db, \ const char* name, uint32_t nameLength, const char* metadata, \ uint32_t metadataLength, uint32_t flags, dpiSodaColl** coll) Creates a new SODA collection if a collection by that name does not exist. If a collection by that name already exists, the collection is opened if the metadata of the collection is equivalent to the supplied metadata; otherwise, an error is returned. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. NOTE: the creation of the collection is performed using an autonomous transaction. Any current transaction is left unchanged. .. parameters-table:: * - ``db`` - IN - A reference to the database in which the SODA collection is to be created. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - The name of the collection which is to be created or opened. NOTE: the name is case sensitive. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``metadata`` - IN - The metadata to use when creating the collection, or NULL if default metadata should be used instead. * - ``metadataLength`` - IN - The length of the metadata parameter, in bytes, or 0 if metadata is NULL. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``coll`` - OUT - A pointer to a reference to the newly created or opened SODA collection if the function completes successfully. The function :func:`dpiSodaColl_release()` should be called when the collection is no longer required. .. function:: int dpiSodaDb_createDocument(dpiSodaDb* db, const char* key, \ uint32_t keyLength, const char* content, uint32_t contentLength, \ const char* mediaType, uint32_t mediaTypeLength, uint32_t flags, \ dpiSodaDoc** doc) Creates a SODA document that can later be inserted into a collection or used to replace an existing document in a collection. This method should be used when the content is binary or encoded text. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - A reference to the database in which the SODA document is going to be inserted or replaced. If the reference is NULL or invalid, an error is returned. * - ``key`` - IN - The key used to identify this document, or NULL if a key should be generated instead (and the collection metadata supports key generation). * - ``keyLength`` - IN - The length of the key used to identify the document, in bytes, or 0 if the key is NULL. * - ``content`` - IN - The content of the document to create, as a byte string. The type of content is controlled by the mediaType parameter. If the mediaType parameter is set to NULL or "application/json", the content must be a valid UTF-8 or UTF-16 encoded JSON string. * - ``contentLength`` - IN - The length of the document content, in bytes. * - ``mediaType`` - IN - The type of content that is found in the content parameter. This value may also be NULL, in which case the default value of "application/json" is assumed. * - ``mediaTypeLength`` - IN - The length of the mediaType parameter, in bytes, or 0 if the mediaType parameter is NULL. * - ``flags`` - IN - Currently unused. * - ``doc`` - OUT - A pointer to a document reference that will be populated upon successful completion of this function. Call the function :func:`dpiSodaDoc_release()` when it is no longer needed. .. function:: int dpiSodaDb_createJsonDocument(dpiSodaDb* db, \ const char* key, uint32_t keyLength, const dpiJsonNode* content, \ uint32_t flags, dpiSodaDoc** doc) Creates a SODA document that can later be inserted into a collection or used to replace an existing document in a collection. This method should be used when the content is JSON and Oracle Client 23 or higher is being used. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - A reference to the database in which the SODA document is going to be inserted or replaced. If the reference is NULL or invalid, an error is returned. * - ``key`` - IN - The key used to identify this document, or NULL if a key should be generated instead (and the collection metadata supports key generation). * - ``keyLength`` - IN - The length of the key used to identify the document, in bytes, or 0 if the key is NULL. * - ``content`` - IN - The content of the document to create, as a value of type :ref:`dpiJsonNode`. * - ``flags`` - IN - Currently unused. * - ``doc`` - OUT - A pointer to a document reference that will be populated upon successful completion of this function. Call the function :func:`dpiSodaDoc_release()` when it is no longer needed. .. function:: int dpiSodaDb_getCollections(dpiSodaDb* db, \ const char* startName, uint32_t startNameLength, uint32_t flags, \ dpiSodaCollCursor** cursor) Return a cursor to iterate over the SODA collections available in the database. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - A reference to the database to use for iterating over available SODA collections. If the reference is NULL or invalid, an error is returned. * - ``startName`` - IN - A name from which to start iterating over collections available in the database or NULL if all collections should be returned. * - ``startNameLength`` - IN - The length of the startName parameter, in bytes, or 0 if startName is NULL. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``cursor`` - OUT - A pointer to a reference to a newly allocated cursor if the function completes successfully. The function :func:`dpiSodaCollCursor_getNext()` should be used to get the next collection from the database and :func:`dpiSodaCollCursor_release()` should be used when the cursor is no longer required. .. function:: int dpiSodaDb_getCollectionNames(dpiSodaDb* db, \ const char* startName, uint32_t startNameLength, uint32_t limit, \ uint32_t flags, dpiStringList* names) Return an array of names of SODA collections available in the database. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - A reference to the database to use for getting the names of available SODA collections. If the reference is NULL or invalid, an error is returned. * - ``startName`` - IN - The value from which to start getting the names of collections available in the database or NULL if the names of all collections should be returned. * - ``startNameLength`` - IN - The length of the startName parameter, in bytes, or 0 if startName is NULL. * - ``limit`` - IN - The maximum number of collection names to return, or 0 if all names matching the criteria should be returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``names`` - IN - A pointer to structure of type :ref:`dpiStringList` which will be populated upon successful completion of this function. A call to the function :func:`dpiContext_freeStringList()` should be made once the names of the collections returned in this structure are no longer needed. .. function:: int dpiSodaDb_openCollection(dpiSodaDb* db, const char* name, \ uint32_t nameLength, uint32_t flags, dpiSodaColl** coll) Opens an existing SODA collection. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - A reference to the database in which the SODA collection is to be opened. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - The name of the collection which is to be opened. NOTE: the name is case sensitive. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. * - ``coll`` - OUT - A pointer to a reference to the newly opened SODA collection if the function completes successfully. The function :func:`dpiSodaColl_release()` should be called when the collection is no longer required. If the collection with the specified name does not exist, the returned reference is NULL and no error is returned. .. function:: int dpiSodaDb_release(dpiSodaDb* db) Releases a reference to the database. A count of the references to the database is maintained and when this count reaches zero, the memory associated with the database is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``db`` - IN - The database from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiSodaDoc.rst000066400000000000000000000252251510466437300206070ustar00rootroot00000000000000.. _dpiSodaDocFunctions: ODPI-C SODA Document Functions ------------------------------ SODA document handles are used to represent SODA documents in the database. They are created by calling one of the functions :func:`dpiSodaDb_createDocument()`, :func:`dpiSodaDocCursor_getNext()`, :func:`dpiSodaColl_findOne()`, :func:`dpiSodaColl_getDataGuide()`, :func:`dpiSodaColl_insertMany()`, :func:`dpiSodaColl_insertOne()`, :func:`dpiSodaColl_replaceOne()` or :func:`dpiSodaColl_save()` and are destroyed when the last reference is released by calling the function :func:`dpiSodaDoc_release()`. See `this tracking issue `__ for known issues with SODA. .. function:: int dpiSodaDoc_addRef(dpiSodaDoc* doc) Adds a reference to the SODA document. This is intended for situations where a reference to the document needs to be maintained independently of the reference returned when the document was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - The document to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaDoc_getContent(dpiSodaDoc* doc, \ const char** value, uint32_t* valueLength, const char** encoding) Returns the content of the document. If the document contains JSON an exception will be thrown. Use :func:`dpiSodaDoc_getIsJson()` to determine whether to call this function or :func:`dpiSodaDoc_getJsonContent()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document from which the content is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the document content, as a byte string, which will be populated upon successful comletion of this function. The pointer returned will remain valid as long as a reference to the document is held. * - ``valueLength`` - OUT - A pointer to the length of the document content, in bytes, which will be populated upon successful completion of this function. * - ``encoding`` - OUT - A pointer to the the encoding in which the content was stored, which will be populated upon successful completion of this function. If the document content is not "application/json", a NULL value will be returned. .. function:: int dpiSodaDoc_getCreatedOn(dpiSodaDoc* doc, \ const char** value, uint32_t* valueLength) Returns the timestamp when the document was created, as a string, in ISO format. This value will be empty if the metadata used to create the collection in which the document is found does not support the storage of this attribute, or if the document was created using :func:`dpiSodaDb_createDocument()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document from which the creation timestamp is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the document creation timestamp, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The pointer returned will remain valid as long as a reference to the document is held. * - ``valueLength`` - OUT - A pointer to the length of the document creation timestamp, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaDoc_getIsJson(dpiSodaDoc* doc, int* isJson) Returns a boolean value indicating if the document contains JSON or not. This method should be used to determine if :func:`dpiSodaDoc_getContent()` or :func:`dpiSodaDoc_getJsonContent()` should be called to get the content of the document. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document which will be checked to see if it contains JSON content. If the reference is NULL or invalid, an error is returned. * - ``isJson`` - OUT - A pointer to a boolean value which will be populated upon successful completion of this function. .. function:: int dpiSodaDoc_getJsonContent(dpiSodaDoc* doc, dpiJson** value) Returns the content of the document. If the document does not contain JSON an exception will be thrown. Use :func:`dpiSodaDoc_getIsJson()` to determine whether to call this function or :func:`dpiSodaDoc_getContent()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document which will be checked to see if it contains JSON content. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to a dpiJson reference which will be populated upon successful completion of this function. This reference will remain valid as long as the SODA document itself is valid. .. function:: int dpiSodaDoc_getKey(dpiSodaDoc* doc, const char** value, \ uint32_t* valueLength) Returns the key that uniquely identifies the document in the collection. This value will be empty if no key was supplied when the document was created using :func:`dpiSodaDb_createDocument()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document from which the key is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the document key, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The pointer returned will remain valid as long as a reference to the document is held. * - ``valueLength`` - OUT - A pointer to the length of the document key, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaDoc_getLastModified(dpiSodaDoc* doc, \ const char** value, uint32_t* valueLength) Returns the timestamp when the document was last modified, as a string, in ISO format. This value will be empty if the metadata used to create the collection in which the document is found does not support the storage of this attribute, or if the document was created using :func:`dpiSodaDb_createDocument()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document from which the last modified timestamp is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the document last modified timestamp, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The pointer returned will remain valid as long as a reference to the document is held. * - ``valueLength`` - OUT - A pointer to the length of the document last modified timestamp, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaDoc_getMediaType(dpiSodaDoc* doc, \ const char** value, uint32_t* valueLength) Returns the media type of the document. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document from which the media type is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the media type, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The pointer returned will remain valid as long as a reference to the document is held. * - ``valueLength`` - OUT - A pointer to the length of the media type, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaDoc_getVersion(dpiSodaDoc* doc, \ const char** value, uint32_t* valueLength) Returns the current version of the document. This value will be empty if the metadata used to create the collection in which the document is found does not support the storage of this attribute, or if the document was created using :func:`dpiSodaDb_createDocument()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - A reference to the document from which the version is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``value`` - OUT - A pointer to the version, as a byte string in the encoding used for CHAR data, which will be populated upon successful completion of this function. The pointer returned will remain valid as long as a reference to the document is held. * - ``valueLength`` - OUT - A pointer to the length of the version, in bytes, which will be populated upon successful completion of this function. .. function:: int dpiSodaDoc_release(dpiSodaDoc* doc) Releases a reference to the SODA document. A count of the references to the document is maintained and when this count reaches zero, the memory associated with the document is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``doc`` - IN - The document from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiSodaDocCursor.rst000066400000000000000000000060321510466437300220000ustar00rootroot00000000000000.. _dpiSodaDocCursorFunctions: ODPI-C SODA Document Cursor Functions ------------------------------------- SODA document cursor handles are used to represent SODA document cursors. They are created by calling the function :func:`dpiSodaColl_find()` and are destroyed when the last reference is released by calling the function :func:`dpiSodaDocCursor_release()`. See `this tracking issue `__ for known issues with SODA. .. function:: int dpiSodaDocCursor_addRef(dpiSodaDocCursor* cursor) Adds a reference to the SODA document cursor. This is intended for situations where a reference to the cursor needs to be maintained independently of the reference returned when the cursor was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - The cursor to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaDocCursor_close(dpiSodaDocCursor* cursor) Closes the cursor and makes it unusable for further work immediately, rather than when the reference count reaches zero. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - A reference to the cursor which is to be closed. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSodaDocCursor_getNext(dpiSodaDocCursor* cursor, \ uint32_t flags, dpiSodaDoc** doc) Gets the next document from the cursor, if there is one. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - The cursor from which the next document is to be retrieved. The reference is NULL or invalid, an error is returned. * - ``flags`` - IN - One or more of the values from the enumeration :ref:`dpiSodaFlags`, OR'ed together. Only the value DPI_SODA_FLAGS_DEFAULT is currently supported. * - ``doc`` - OUT - A pointer to a reference to the next document in the cursor, if one exists. If no further documents are available from the cursor, NULL is returned instead. The function :func:`dpiSodaDoc_release()` should be called when the document is no longer required. .. function:: int dpiSodaDocCursor_release(dpiSodaDocCursor* cursor) Releases a reference to the SODA document cursor. A count of the references to the cursor is maintained and when this count reaches zero, the memory associated with the cursor is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``cursor`` - IN - The cursor from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiStmt.rst000066400000000000000000001130261510466437300202170ustar00rootroot00000000000000.. _dpiStmtFunctions: ODPI-C Statement Functions -------------------------- Statement handles are used to represent statements of all types (queries, DML, DDL and PL/SQL). They are created by calling the function :func:`dpiConn_prepareStmt()` or the function :func:`dpiSubscr_prepareStmt()`. They are also created implicitly when a variable of type DPI_ORACLE_TYPE_STMT is created. Statement handles can be closed by calling the function :func:`dpiStmt_close()` or by releasing the last reference to the statement by calling the function :func:`dpiStmt_release()`. .. function:: int dpiStmt_addRef(dpiStmt* stmt) Adds a reference to the statement. This is intended for situations where a reference to the statement needs to be maintained independently of the reference returned when the statement was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - The statement to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiStmt_bindByName(dpiStmt* stmt, const char* name, \ uint32_t nameLength, dpiVar* var) Binds a variable to a named placeholder in the statement. A reference to the variable is retained by the library and is released when the statement itself is released or a new variable is bound to the same name. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to have the variable bound. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - A byte string in the encoding used for CHAR data giving the name of the placeholder which is to be bound. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``var`` - IN - A reference to the variable which is to be bound. If the reference is NULL or invalid, an error is returned. .. function:: int dpiStmt_bindByPos(dpiStmt* stmt, uint32_t pos, dpiVar* var) Binds a variable to a placeholder in the statement by position. A reference to the variable is retained by the library and is released when the statement itself is released or a new variable is bound to the same position. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to have the variable bound. If the reference is NULL or invalid, an error is returned. * - ``pos`` - IN - The position which is to be bound. The position of a placeholder is determined by its location in the statement. Placeholders are numbered from left to right, starting from 1, and duplicate names do not count as additional placeholders. * - ``var`` - IN - A reference to the variable which is to be bound. If the reference is NULL or invalid, an error is returned. .. function:: int dpiStmt_bindValueByName(dpiStmt* stmt, const char* name, \ uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData* data) Binds a value to a named placeholder in the statement without the need to create a variable directly. One is created implicitly and released when the statement is released or a new value is bound to the same name. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to have the variable bound. If the reference is NULL or invalid, an error is returned. * - ``name`` - IN - A byte string in the encoding used for CHAR data giving the name of the placeholder which is to be bound. * - ``nameLength`` - IN - The length of the name parameter, in bytes. * - ``nativeTypeNum`` - IN - The type of data that is being bound. It is expected to be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``data`` - IN - The data which is to be bound, as a pointer to a :ref:`dpiData` structure. A variable will be created based on the type of data being bound and a reference to this variable retained. Once the statement has been executed, this new variable will be released. .. function:: int dpiStmt_bindValueByPos(dpiStmt* stmt, uint32_t pos, \ dpiNativeTypeNum nativeTypeNum, dpiData* data) Binds a value to a placeholder in the statement without the need to create a variable directly. One is created implicitly and released when the statement is released or a new value is bound to the same position. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to have the variable bound. If the reference is NULL or invalid, an error is returned. * - ``pos`` - IN - The position which is to be bound. The position of a placeholder is determined by its location in the statement. Placeholders are numbered from left to right, starting from 1, and duplicate names do not count as additional placeholders. * - ``nativeTypeNum`` - IN - The type of data that is being bound. It is expected to be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``data`` - IN - The data which is to be bound, as a pointer to a :ref:`dpiData` structure. A variable will be created based on the type of data being bound and a reference to this variable retained. Once the statement has been executed, this new variable will be released. .. function:: int dpiStmt_close(dpiStmt* stmt, const char* tag, \ uint32_t tagLength) Closes the statement and makes it unusable for further work immediately, rather than when the reference count reaches zero. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to be closed. If the reference is NULL or invalid, an error is returned. * - ``tag`` - IN - A key to associate the statement with in the statement cache, in the encoding used for CHAR data. NULL is also acceptable in which case the statement is not tagged. This value is ignored for statements that are acquired through bind variables (REF CURSOR) or implicit results. * - ``tagLength`` - IN - The length of the tag parameter, in bytes, or 0 if the tag parameter is NULL. .. function:: int dpiStmt_define(dpiStmt* stmt, uint32_t pos, dpiVar* var) Defines the variable that will be used to fetch rows from the statement. A reference to the variable will be retained until the next define is performed on the same position or the statement is closed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement on which the variable is to be defined. If the reference is NULL or invalid, an error is returned. Note that the statement must have already been executed or an error is returned. * - ``pos`` - IN - The position which is to be defined. The first position is 1. * - ``var`` - IN - A reference to the variable which is to be used for fetching rows from the statement at the given position. If the reference is NULL or invalid, an error is returned. .. function:: int dpiStmt_defineValue(dpiStmt* stmt, uint32_t pos, \ dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, \ uint32_t size, int sizeIsBytes, dpiObjectType* objType) Defines the type of data that will be used to fetch rows from the statement. This is intended for use with the function :func:`dpiStmt_getQueryValue()`, when the default data type derived from the column metadata needs to be overridden by the application. Internally, a variable is created with the specified data type and size. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement on which the define is to take place. If the reference is NULL or invalid, an error is returned. Note that the statement must have already been executed or an error is returned. * - ``pos`` - IN - The position which is to be defined. The first position is 1. * - ``oracleTypeNum`` - IN - The type of Oracle data that is to be used. It should be one of the values from the enumeration :ref:`dpiOracleTypeNum`. * - ``nativeTypeNum`` - IN - The type of native C data that is to be used. It should be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``size`` - IN - The maximum size of the buffer used for transferring data to/from Oracle. This value is only used for variables transferred as byte strings. Size is either in characters or bytes depending on the value of the sizeIsBytes parameter. If the value is in characters, internally the value will be multipled by the maximum number of bytes for each character and that value used instead when determining the necessary buffer size. * - ``sizeIsBytes`` - IN - A boolean value indicating if the size parameter refers to characters or bytes. This flag is only used if the variable refers to character data. * - ``objType`` - IN - A reference to the object type of the object that is being bound or fetched. This value is only used if the Oracle type is DPI_ORACLE_TYPE_OBJECT. .. function:: int dpiStmt_deleteFromCache(dpiStmt* stmt) Excludes the associated SQL statement from the statement cache. If the SQL statement was not already in the cache, it will not be added. This function can be called before or after the statment is executed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to be excluded from the statement cache. If the reference is NULL or invalid, an error is returned. .. function:: int dpiStmt_execute(dpiStmt* stmt, dpiExecMode mode, \ uint32_t* numQueryColumns) Executes the statement using the bound values. For queries this makes available metadata which can be acquired using the function :func:`dpiStmt_getQueryInfo()`. For non-queries, out and in-out variables are populated with their values. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to be executed. If the reference is NULL or invalid, an error is returned. * - ``mode`` - IN - One or more of the values from the enumeration :ref:`dpiExecMode`, OR'ed together. * - ``numQueryColumns`` - OUT - A pointer to the number of columns which are being queried, which will be populated upon successful execution of the statement. If the statement does not refer to a query, the value is set to 0. This parameter may also be NULL. .. function:: int dpiStmt_executeMany(dpiStmt* stmt, dpiExecMode mode, \ uint32_t numIters) Executes the statement the specified number of times using the bound values. Each bound variable must have at least this many elements allocated or an error is returned. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to be executed. If the reference is NULL or invalid, an error is returned. * - ``mode`` - IN - One or more of the values from the enumeration :ref:`dpiExecMode`, OR'ed together. Note that modes DPI_MODE_EXEC_BATCH_ERRORS and DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS are only supported with insert, update, delete and merge statements. * - ``numIters`` - IN - The number of times the statement is executed. Each iteration corresponds to one of the elements of the array that was bound earlier. .. function:: int dpiStmt_fetch(dpiStmt* stmt, int* found, \ uint32_t* bufferRowIndex) Fetches a single row from the buffers defined for the query. If no row is available in the buffers, an internal fetch takes place to populate them, if rows are available. The number of rows fetched into the internal buffers can be set by calling :func:`dpiStmt_setFetchArraySize()`. If the statement does not refer to a query an error is returned. All columns that have not been defined prior to this call are implicitly defined using the metadata made available when the statement was executed. The function :func:`dpiStmt_fetchRows()` should be used instead of this function if it is important to control when the internal fetch (and round-trip to the database) takes place. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which a row is to be fetched. If the reference is NULL or invalid, an error is returned. * - ``found`` - OUT - A pointer to a boolean value indicating if a row was fetched or not, which will be populated upon successful completion of this function. * - ``bufferRowIndex`` - OUT - A pointer to the buffer row index which will be populated upon successful completion of this function if a row is found. This index is used as the array position for getting values from the variables that have been defined for the statement. .. function:: int dpiStmt_fetchRows(dpiStmt* stmt, uint32_t maxRows, \ uint32_t* bufferRowIndex, uint32_t* numRowsFetched, int* moreRows) Returns the number of rows that are available in the buffers defined for the query. If no rows are currently available in the buffers, an internal fetch takes place in order to populate them, if rows are available. The number of rows fetched into the internal buffers can be set by calling :func:`dpiStmt_setFetchArraySize()`. If the statement does not refer to a query an error is returned. All columns that have not been defined prior to this call are implicitly defined using the metadata made available when the statement was executed. This function should be used instead of :func:`dpiStmt_fetch()` if it is important to control when the internal fetch (and round-trip to the database) takes place. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which rows are to be fetched. If the reference is NULL or invalid, an error is returned. * - ``maxRows`` - IN - The maximum number of rows to fetch. If the number of rows available exceeds this value only this number will be fetched. * - ``bufferRowIndex`` - OUT - A pointer to the buffer row index which will be populated upon successful completion of this function. This index is used as the array position for getting values from the variables that have been defined for the statement. * - ``numRowsFetched`` - OUT - A pointer to the number of rows that have been fetched, populated after the call has completed successfully. * - ``moreRows`` - OUT - A pointer to a boolean value indicating if there are potentially more rows that can be fetched after the ones fetched by this function call. .. function:: int dpiStmt_getBatchErrorCount(dpiStmt* stmt, uint32_t* count) Returns the number of batch errors that took place during the last execution with batch mode enabled. Batch errors are only available when both the client and the server are at 12.1. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the number of batch errors is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``count`` - OUT - A pointer to the number of batch errors that took place, which is populated after successful completion of the function. .. function:: int dpiStmt_getBatchErrors(dpiStmt* stmt, uint32_t numErrors, \ dpiErrorInfo* errors) Returns the batch errors that took place during the last execution with batch mode enabled. Batch errors are only available when both the client and the server are at 12.1. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the batch errors are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numErrors`` - IN - The size of the errors array in number of elements. The number of batch errors that are available can be determined using :func:`dpiStmt_getBatchErrorCount()`. * - ``errors`` - IN - A pointer to the first element of an array of :ref:`dpiErrorInfo` structures which is assumed to contain the number of elements specified by the numErrors parameter. .. function:: int dpiStmt_getBindCount(dpiStmt* stmt, uint32_t* count) Returns the number of bind variables in the prepared statement. In SQL statements this is the total number of bind variables whereas in PL/SQL statements this is the count of the **unique** bind variables. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the number of bind variables is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``count`` - OUT - A pointer to the number of bind variables found in the statement, which is populated upon successful completion of the function. .. function:: int dpiStmt_getBindNames(dpiStmt* stmt, uint32_t* numBindNames, \ const char** bindNames, uint32_t* bindNameLengths) Returns the names of the unique bind variables in the prepared statement. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the names of bind variables are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numBindNames`` - IN/OUT - A pointer to the size of the bindNames and bindNameLengths arrays in number of elements. This value must be large enough to hold all of the unique bind variables in the prepared statement or an error will be returned. The maximum number of bind variables can be determined by calling :func:`dpiStmt_getBindCount()`. Upon successful completion of this function, the actual number of unique bind variables in the prepared statement will be populated. * - ``bindNames`` - OUT - An array of pointers to byte strings in the encoding used for CHAR data. The size of the array is specified using the numBindNames parameter. When the function completes this array will be filled with the names of the unique bind variables in the statement. * - ``bindNameLengths`` - OUT - A pointer to the first element of an array of integers containing the lengths of the bind variable names which is filled in upon successful completion of the function. The number of elements is assumed to be specified by the numBindNames parameter. .. function:: int dpiStmt_getFetchArraySize(dpiStmt* stmt, uint32_t* arraySize) Gets the array size used for performing fetches. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the fetch array size is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``arraySize`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiStmt_getImplicitResult(dpiStmt* stmt, \ dpiStmt** implicitResult) Returns the next implicit result available from the last execution of the statement. Implicit results are only available when both the client and server are 12.1 or higher. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the next implicit result is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``implicitResult`` - OUT - A pointer to a reference to a statement which will be populated with the next implicit result upon successful completion of the function. If no implicit results remain, the reference will be set to NULL. The reference that is returned must be released as soon as it is no longer needed. .. function:: int dpiStmt_getInfo(dpiStmt* stmt, dpiStmtInfo* info) Returns information about the statement. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which information is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a structure of type :ref:`dpiStmtInfo` which will be filled in with information about the statement upon successful completion of the function. .. function:: int dpiStmt_getLastRowid(dpiStmt* stmt, dpiRowid** rowid) Returns the rowid of the last row that was affected by the statement. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the rowid of the last row affected is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``rowid`` - OUT - A pointer to a rowid which will be populated upon successful completion of this function. If no statement has been executed, the last statement executed was not a DML statement or no rows were affected by a DML statement, the value returned will be NULL. If a rowid is returned, the reference will remain valid until the next call to this function or until the statement is closed. If the reference is needed for a longer period of time, call :func:`dpiRowid_addRef()` to acquire an independent reference (and call :func:`dpiRowid_release()` when that reference is no longer required). .. function:: int dpiStmt_getNumQueryColumns(dpiStmt* stmt, \ uint32_t* numQueryColumns) Returns the number of columns that are being queried. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the number of query columns is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numQueryColumns`` - OUT - A pointer to the number of columns which are being queried by the statement, which is filled in upon successful completion of the function. If the statement does not refer to a query, the value is populated with 0. .. function:: int dpiStmt_getOciAttr(dpiStmt* stmt, uint32_t attribute, \ dpiDataBuffer* value, uint32_t* valueLength) Returns the value of an OCI attribute. This is intended solely for testing attributes that are not otherwise supported by ODPI-C and should not be used for any other purpose. Use only as directed by Oracle. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the OCI attribute is to be returned. If the reference is NULL or invalid, an error is returned. * - ``attribute`` - IN - The attribute to acquire. * - ``value`` - OUT - A data buffer which will be populated with the value of the OCI attribute upon successfully completing this function. * - ``valueLength`` - OUT - The length of the attribute which will be populated upon succesfully completing this function. .. function:: int dpiStmt_getPrefetchRows(dpiStmt* stmt, uint32_t* numRows) Gets the number of rows that will be prefetched by the Oracle Client library when a query is executed. The value may be changed by calling :func:`dpiStmt_setPrefetchRows()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the number of rows to prefetch is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numRows`` - OUT - A pointer to the value which will be populated upon successful completion of this function. .. function:: int dpiStmt_getQueryInfo(dpiStmt* stmt, uint32_t pos, \ dpiQueryInfo* info) Returns information about the column that is being queried. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the column metadata is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``pos`` - IN - The position of the column whose metadata is to be retrieved. The first position is 1. * - ``info`` - OUT - A pointer to a :ref:`dpiQueryInfo` structure which will be filled in upon successful completion of the function. .. function:: int dpiStmt_getQueryValue(dpiStmt* stmt, uint32_t pos, \ dpiNativeTypeNum* nativeTypeNum, dpiData** data) Returns the value of the column at the given position for the currently fetched row, without needing to provide a variable. If the data type of the column needs to be overridden, the function :func:`dpiStmt_defineValue()` can be called to specify a different type after executing the statement but before fetching any data. This function should only be called after a call to the function :func:`dpiStmt_fetch()` has succeeded and indicated that a row is available. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the column value is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``pos`` - IN - The position of the column whose value is to be retrieved. The first position is 1. * - ``nativeTypeNum`` - OUT - A pointer to the native type that is used by the value, which will be populated upon successful completion of this function. It will be one of the values from the enumeration :ref:`dpiNativeTypeNum`. * - ``data`` - OUT - A pointer to a reference to an internally created :ref:`dpiData` structure which will be populated upon successful completion of this function. The structure contains the value of the column at the specified position. Note that any references to LOBs, statements, objects, and rowids are owned by the statement. If you wish to retain these values independently of the statement, a reference must be added by calling one of :func:`dpiLob_addRef()`, :func:`dpiStmt_addRef()`, :func:`dpiObject_addRef()` or :func:`dpiRowid_addRef()`. .. function:: int dpiStmt_getRowCount(dpiStmt* stmt, uint64_t* count) Returns the number of rows affected by the last DML statement that was executed, the number of rows currently fetched from a query, or the number of successful executions of a PL/SQL block. In all other cases 0 is returned. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the row count is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``count`` - OUT - A pointer to the row count which will be populated upon successful completion of the function. .. function:: int dpiStmt_getRowCounts(dpiStmt* stmt, \ uint32_t* numRowCounts, uint64_t** rowCounts) Returns an array of row counts affected by the last invocation of :func:`dpiStmt_executeMany()` with the array DML rowcounts mode enabled. This feature is only available if both client and server are at 12.1. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the row counts are to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numRowCounts`` - OUT - A pointer to the size of the rowCounts array which is being returned. It is populated upon successful completion of the function. * - ``rowCounts`` - OUT - A pointer to an array of row counts which is populated upon successful completion of the function. This array should be considered read-only. .. function:: int dpiStmt_getSubscrQueryId(dpiStmt* stmt, uint64_t* queryId) Returns the id of the query that was just registered on the subscription by calling :func:`dpiStmt_execute()` on a statement prepared by calling :func:`dpiSubscr_prepareStmt()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement from which the query id should be retrieved. This statement should have been prepared using the function :func:`dpiSubscr_prepareStmt()`. If the reference is NULL or invalid an error is returned. * - ``queryId`` - OUT - A pointer to the query id, which is filled in upon successful completion of the function. .. function:: int dpiStmt_release(dpiStmt* stmt) Releases a reference to the statement. A count of the references to the statement is maintained and when this count reaches zero, the memory associated with the statement is freed and the statement is closed if that has not already taken place using the function :func:`dpiStmt_close()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - The statement from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiStmt_scroll(dpiStmt* stmt, dpiFetchMode mode, \ int32_t offset, int32_t rowCountOffset) Scrolls the statement to the position in the cursor specified by the mode and offset. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement which is to be scrolled to a particular row position. If the reference is NULL or invalid, an error is returned. * - ``mode`` - IN - One of the values from the enumeration :ref:`dpiFetchMode`. * - ``offset`` - IN - A value which is used with the mode in order to determine the row position in the cursor. * - ``rowCountOffset`` - IN - An offset to the row count used when calculating the desired row to be fetched. This is needed when a client has fetched multiple rows but has not yet consumed all of them. If this is not being done by the client, the value 0 is appropriate. .. function:: int dpiStmt_setFetchArraySize(dpiStmt* stmt, uint32_t arraySize) Sets the array size used for performing fetches. All variables defined for fetching must have this many (or more) elements allocated for them. The higher this value is the less network round trips are required to fetch rows from the database but more memory is also required. A value of zero will reset the array size to the default value of DPI_DEFAULT_FETCH_ARRAY_SIZE. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement on which the fetch array size is to be set. If the reference is NULL or invalid, an error is returned. * - ``arraySize`` - IN - The number of rows which should be fetched each time more rows need to be fetched from the database. .. function:: int dpiStmt_setOciAttr(dpiStmt* stmt, uint32_t attribute, \ void* value, uint32_t valueLength) Sets the value of an OCI attribute. This is intended solely for testing attributes that are not otherwise supported by ODPI-C and should not be used for any other purpose. Use only as directed by Oracle. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement on which the OCI attribute is to be set. If the reference is NULL or invalid, an error is returned. * - ``attribute`` - IN - The attribute to set. * - ``value`` - IN - A pointer to the data which is to be set. * - ``valueLength`` - IN - The length of the data which is to be set. .. function:: int dpiStmt_setPrefetchRows(dpiStmt* stmt, uint32_t numRows) Sets the number of rows that will be prefetched by the Oracle Client library when a query is executed. The default value is `DPI_DEFAULT_PREFETCH_ROWS` (2). Increasing this value may reduce the number of round-trips to the database that are required in order to fetch rows, but at the cost of increasing memory requirements. Setting this value to 0 will disable prefetch completely, which may be useful when the timing for fetching rows must be controlled by the caller. The current value can be determined by calling :func:`dpiStmt_getPrefetchRows()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``stmt`` - IN - A reference to the statement on which the number of rows to prefetch is to be set. If the reference is NULL or invalid, an error is returned. * - ``numRows`` - OUT - The number of rows to prefetch. odpi-5.6.4/doc/src/functions/dpiSubscr.rst000066400000000000000000000054411510466437300205320ustar00rootroot00000000000000.. _dpiSubscrFunctions: ODPI-C Subscription Functions ----------------------------- Subscription handles are used to represent subscriptions to events such as continuous query notification and object change notification. They are created by calling the function :func:`dpiConn_subscribe()` and are destroyed by calling the function :func:`dpiConn_unsubscribe()` or releasing the last reference by calling the function :func:`dpiSubscr_release()`. .. function:: int dpiSubscr_addRef(dpiSubscr* subscr) Adds a reference to the subscription. This is intended for situations where a reference to the subscription needs to be maintained independently of the reference returned when the subscription was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``subscr`` - IN - The subscription to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiSubscr_prepareStmt(dpiSubscr* subscr, const char* sql, \ uint32_t sqlLength, dpiStmt** stmt) Prepares a statement for registration on the subscription. The statement is then registered by calling the function :func:`dpiStmt_execute()`. The reference to the statement that is returned should be released as soon as it is no longer needed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``subscr`` - IN - A reference to the subscription on which the statement is to be prepared for registration. If the reference is NULL or invalid, an error is returned. * - ``sql`` - IN - The SQL that is to be prepared, as a byte string in the encoding used for CHAR data. * - ``sqlLength`` - IN - The length of the sql parameter, in bytes. * - ``stmt`` - OUT - A reference to the statement that was prepared, which will be populated when the function completes successfully. .. function:: int dpiSubscr_release(dpiSubscr* subscr) Releases a reference to the subscription. A count of the references to the subscription is maintained and when this count reaches zero, the memory associated with the subscription is freed. The subscription is also deregistered so that notifications are no longer sent, if this was not already done using the function :func:`dpiConn_unsubscribe()`. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``subscr`` - IN - The subscription from which a reference is to be released. If the reference is NULL or invalid, an error is returned. odpi-5.6.4/doc/src/functions/dpiVar.rst000066400000000000000000000337301510466437300200230ustar00rootroot00000000000000.. _dpiVarFunctions: ODPI-C Variable Functions ------------------------- Variable handles are used to represent memory areas used for transferring data to and from the database. They are created by calling the function :func:`dpiConn_newVar()`. They are destroyed when the last reference to the variable is released by calling the function :func:`dpiVar_release()`. They are bound to statements by calling the function :func:`dpiStmt_bindByName()` or the function :func:`dpiStmt_bindByPos()`. They can also be used for fetching data from the database by calling the function :func:`dpiStmt_define()`. .. function:: int dpiVar_addRef(dpiVar* var) Adds a reference to the variable. This is intended for situations where a reference to the variable needs to be maintained independently of the reference returned when the variable was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - The variable to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiVar_copyData(dpiVar* var, uint32_t pos, \ dpiVar* sourceVar, uint32_t sourcePos) Copies the data from one variable to another variable. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - The variable into which data is to be copied. If the reference is NULL or invalid, an error is returned. * - ``pos`` - IN - The array position into which the data is to be copied. The first position is 0. If the array position specified exceeds the number of elements allocated in the variable, an error is returned. * - ``sourceVar`` - IN - The variable from which is to be copied. If the reference is NULL or invalid, an error is returned. * - ``sourcePos`` - IN - The array position from which the data is to be copied. The first position is 0. If the array position specified exceeds the number of elements allocated in the source variable, an error is returned. .. function:: int dpiVar_getNumElementsInArray(dpiVar* var, \ uint32_t* numElements) Returns the number of elements in a PL/SQL index-by table if the variable was created as an array by the function :func:`dpiConn_newVar()`. If the variable is one of the output bind variables of a DML returning statement, however, the value returned will correspond to the number of rows returned by the DML returning statement. In all other cases, the value returned will be the number of elements the variable was created with. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable from which the number of elements is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``numElements`` - OUT - A pointer to the number of elements, which will be populated when the function completes successfully. .. function:: int dpiVar_getReturnedData(dpiVar* var, uint32_t pos, \ uint32_t* numElements, dpiData** data) Returns a pointer to an array of :ref:`dpiData` structures used for transferring data to and from the database. These structures are allocated by the variable itself when a DML returning statement is executed and the variable is bound. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which contains the data structures used for transferring data to and from the database. If the reference is NULL or invalid, an error is returned. * - ``pos`` - IN - The array position in the variable from which returned data is to be determined. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``numElements`` - OUT - A pointer to the number of elements that have been allocated by the variable, which will be populated when the function completes successfully. The value 0 is returned if the statement is not a DML returning statement or the statement returned no data. * - ``data`` - OUT - A pointer to an array of :ref:`dpiData` structures which will be populated when the function completes successfully. A NULL value is returned if the statement is not a DML returning statement or the statement returned no data. .. function:: int dpiVar_getSizeInBytes(dpiVar* var, uint32_t* sizeInBytes) Returns the size of the buffer used for one element of the array used for fetching/binding Oracle data. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable whose buffer size is to be retrieved. If the reference is NULL or invalid, an error is returned. * - ``sizeInBytes`` - OUT - A pointer to the size of the buffer, in bytes, which will be populated when the function completes successfully. .. function:: int dpiVar_release(dpiVar* var) Releases a reference to the variable. A count of the references to the variable is maintained and when this count reaches zero, the memory associated with the variable is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - The variable from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiVar_setFromBytes(dpiVar* var, uint32_t pos, \ const char* value, uint32_t valueLength) Sets the variable value to the specified byte string. In the case of the variable's Oracle type being DPI_ORACLE_TYPE_NUMBER, the byte string is converted to an Oracle number during the call to this function. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. If the variable does not use native type DPI_NATIVE_TYPE_BYTES or DPI_NATIVE_TYPE_LOB, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``value`` - IN - A pointer to the byte string which contains the data to be set. The data is copied to the variable buffer and does not need to be retained after this function call has completed. This value can be NULL if the valueLength parameter is 0. * - ``valueLength`` - IN - The length of the data to be set, in bytes. The maximum value permitted is 2 bytes less than 1 GB (1,073,741,822 bytes). .. function:: int dpiVar_setFromJson(dpiVar* var, uint32_t pos, \ dpiJson* json) Sets the variable value to the specified JSON value. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. If the variable does not use native type DPI_NATIVE_TYPE_JSON, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``json`` - IN - A reference to the JSON value which should be set. If the reference is null or invalid, an error is returned. A reference is retained by the variable until a new value is set or the variable itself is freed. .. function:: int dpiVar_setFromLob(dpiVar* var, uint32_t pos, dpiLob* lob) Sets the variable value to the specified LOB. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``lob`` - IN - A reference to the LOB which should be set. If the reference is null or invalid, an error is returned. A reference is retained by the variable until a new value is set or the variable itself is freed. .. function:: int dpiVar_setFromObject(dpiVar* var, uint32_t pos, \ dpiObject* obj) Sets the variable value to the specified object. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``obj`` - IN - A reference to the object which should be set. If the reference is null or invalid, an error is returned. A reference is retained by the variable until a new value is set or the variable itself is freed. .. function:: int dpiVar_setFromRowid(dpiVar* var, uint32_t pos, \ dpiRowid* rowid) Sets the variable value to the specified rowid. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``rowid`` - IN - A reference to the rowid which should be set. If the reference is null or invalid, an error is returned. A reference is retained by the variable until a new value is set or the variable itself is freed. .. function:: int dpiVar_setFromStmt(dpiVar* var, uint32_t pos, dpiStmt* stmt) Sets the variable value to the specified statement. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``stmt`` - IN - A reference to the statement which should be set. If the reference is null or invalid, an error is returned. A reference is retained by the variable until a new value is set or the variable itself is freed. .. function:: int dpiVar_setFromVector(dpiVar* var, uint32_t pos, \ dpiVector* vector) Sets the variable value to the specified vector value. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable which should be set. If the reference is null or invalid, an error is returned. If the variable does not use native type DPI_NATIVE_TYPE_VECTOR, an error is returned. * - ``pos`` - IN - The array position in the variable which is to be set. The first position is 0. If the position exceeds the number of elements allocated by the variable an error is returned. * - ``vector`` - IN - A reference to the vector value which should be set. If the reference is null or invalid, an error is returned. A reference is retained by the variable until a new value is set or the variable itself is freed. .. function:: int dpiVar_setNumElementsInArray(dpiVar* var, \ uint32_t numElements) Sets the number of elements in a PL/SQL index-by table. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``var`` - IN - A reference to the variable in which the number of elements is to be set. If the reference is NULL or invalid, an error is returned. * - ``numElements`` - IN - The number of elements that PL/SQL should consider part of the array. This number should not exceed the number of elements that have been allocated in the variable. odpi-5.6.4/doc/src/functions/dpiVector.rst000066400000000000000000000057041510466437300205350ustar00rootroot00000000000000.. _dpiVectorFunctions: ODPI-C Vector Functions ----------------------- Vector handles are used to represent vector values stored in the database. They are only available from Oracle Client and Database 23.4 and higher. They can be created explicitly by a call to :func:`dpiConn_newVector()` or implicitly when a variable of type DPI_ORACLE_TYPE_VECTOR is created. They are destroyed when the last reference is released by a call to the function :func:`dpiVector_release()`. .. function:: int dpiVector_addRef(dpiVector* vector) Adds a reference to the vector value. This is intended for situations where a reference to the vector value needs to be maintained independently of the reference returned when the vector value was created. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``vector`` - IN - The vector value to which a reference is to be added. If the reference is NULL or invalid, an error is returned. .. function:: int dpiVector_getValue(dpiVector* vector, dpiVectorInfo* info) Returns information about the vector. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``vector`` - IN - The vector value from which the information is to be extracted. If the reference is NULL or invalid, an error is returned. * - ``info`` - OUT - A pointer to a structure of type :ref:`dpiVectorInfo` which will be populated upon successful completion of this function. The structure's contents will remain valid as long as a reference is held to the vector value and the vector value itself is not modified. .. function:: int dpiVector_release(dpiVector* vector) Releases a reference to the vector value. A count of the references to the vector value is maintained and when this count reaches zero, the memory associated with the vector value is freed. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``vector`` - IN - The vector value from which a reference is to be released. If the reference is NULL or invalid, an error is returned. .. function:: int dpiVector_setValue(dpiVector* vector, dpiVectorInfo* info) Sets the vector value from the supplied information. The function returns DPI_SUCCESS for success and DPI_FAILURE for failure. .. parameters-table:: * - ``vector`` - IN - The vector value which is to be modified using the supplied information. If the reference is NULL or invalid, an error is returned. * - ``info`` - IN - A pointer to a structure of type :ref:`dpiVectorInfo` which contains the information to be set on the vector. odpi-5.6.4/doc/src/functions/index.rst000066400000000000000000000021331510466437300176760ustar00rootroot00000000000000**************** ODPI-C Functions **************** This chapter details the functions available in the ODPI-C library. .. toctree:: :maxdepth: 1 :hidden: Connection Functions Context Functions Data Functions Dequeue Options Functions Enqueue Options Functions JSON Functions LOB Functions Message Properties Functions Object Functions Object Attribute Functions Object Type Functions Pool Functions Queue Functions Rowid Functions SODA Collection Functions SODA Collection Cursor Functions SODA Database Functions SODA Document Functions SODA Document Cursor Functions Statement Functions Subscription Functions Variable Functions Vector Functions odpi-5.6.4/doc/src/index.rst000066400000000000000000000016161510466437300156730ustar00rootroot00000000000000.. ODPI-C documentation main file. Welcome to ODPI-C's |release| documentation! ============================================ **ODPI-C** is a C library that simplifies the use of common Oracle Call Interface (OCI_) features for drivers and applications. The ODPI-C project home page can be found `here `__ and the source code can be found `here `__. .. _OCI: http://www.oracle.com/technetwork/database/features/oci/index.html .. toctree:: :numbered: :maxdepth: 2 user_guide/introduction.rst user_guide/installation.rst Debugging Data Types Round-Trips Enumerations Structures Unions Functions Release Notes Licenses odpi-5.6.4/doc/src/license.rst000066400000000000000000000304541510466437300162100ustar00rootroot00000000000000Licenses ======== Copyright (c) 2016, 2025 Oracle and/or its affiliates. This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license. If you elect to accept the software under the Apache License, Version 2.0, the following applies: Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. The Universal Permissive License (UPL), Version 1.0 --------------------------------------------------- Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both (a) the Software, and (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a "Larger Work" to which the Software is contributed by such licensors), without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms. This license is subject to the following condition: The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Apache License -------------- Version 2.0, January 2004 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. **Definitions**. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. **Grant of Copyright License.** Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. **Grant of Patent License.** Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. **Redistribution.** You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. **Submission of Contributions.** Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. **Trademarks.** This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. **Disclaimer of Warranty.** Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. **Limitation of Liability.** In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. **Accepting Warranty or Additional Liability.** While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS odpi-5.6.4/doc/src/releasenotes.rst000066400000000000000000002132411510466437300172540ustar00rootroot00000000000000ODPI-C Release notes ==================== Version 5.6.4 (November 11, 2025) --------------------------------- #) Fixed bug that caused a segfault to take place when fetching LOBs without enabling threaded mode (`issue 200 `__). #) Fixed bug that prevented an error from being returned when attempting to scroll before the start of the result set with mode ``DPI_MODE_FETCH_PRIOR`` (`issue 201 `__). #) Fixed bug that caused ``ORA-03137: malformed TTC packet from client rejected`` exception to be raised when attempting to execute a scrollable statement with mode ``DPI_MODE_EXEC_DESCRIBE_ONLY`` (`issue 202 `__). #) Fixed segfault on some platforms when trying to access vector flags on Oracle type information. #) Connectivity and interoperability with Oracle Database and Oracle Client libraries older than version 19 is deprecated and will be removed in a future version of ODPI-C. Production use, and availability of database and client software, is detailed in `Release Schedule of Current Database Releases `__. Version 5.6.3 (October 6, 2025) ------------------------------- #) Add NULL terminator to buffers used for returning NUMBER column data as text. This eliminates the need for making a copy when using C conversion functions such as ``strtoll()`` and ``strtod()``. #) Fixed bug with error wrapping which could result in garbage characters being introduced. Fixed potential bug when truncation could occur with very large error messages. Version 5.6.2 (July 29, 2025) ----------------------------- #) Fixed bug resulting in a segfault when environment variable ``DPI_DEBUG_LEVEL`` includes flag ``DPI_DEBUG_LEVEL_LOAD_LIB`` on Windows (`issue 197 `__). #) Fixed bug that masked the error thrown when a PL/SQL fixup callback for session state failed. #) Fixed null checks and version checks for functions :func:`dpiConn_beginSessionlessTransaction()`, :func:`dpiConn_resumeSessionlessTransaction()`, and :func:`dpiConn_suspendSessionlessTransaction()`. Version 5.6.1 (July 16, 2025) ----------------------------- #) Fixed bug resulting in a segfault when a pooled connection is returned to the pool with an active sessionless transaction. Version 5.6.0 (June 26, 2025) ----------------------------- #) Added support for Oracle Database 23ai sessionless transactions with new APIs - :func:`dpiConn_beginSessionlessTransaction()`, :func:`dpiConn_resumeSessionlessTransaction()` and :func:`dpiConn_suspendSessionlessTransaction()`. Also, added a new datatype :ref:`dpiSessionlessTransactionId`. #) Added support for fetching SQL_ID (`issue 194 `__). #) Fixed bug resulting in a segfault when fetching nested collections. #) Fixed bug resulting in a non-zero integer value for the registration ID of Oracle Advanced Queueing subscriptions. #) Adjusted Makfile to allow for greater flexbility in building, as suggested (`issue 196 `__). Version 5.5.1 (March 25, 2025) ------------------------------ #) Fixed bug resulting in a segfault when unable to load the Oracle Client libraries. #) Fixed bug which resulted in error ``ORA-24328: illegal attribute value`` when calling :func:`dpiConn_getObjectType()` with Oracle Client libraries 11.2. #) Improved error message when calling :func:`dpiVector_getValue()` and :func:`dpiVector_setValue()` with sparse vectors and Oracle Client libraries 23.6 or earlier. #) Improved error message when calling :func:`dpiConn_getMaxOpenCursors()` when using Oracle Client libraries 11.2. Version 5.5.0 (February 25, 2025) --------------------------------- #) Added support for Oracle Database 23.7 SPARSE vectors. #) Added support for giving the path of the relative Oracle Client configuration directory if no configuration directory was supplied when calling :func:`dpiContext_createWithParams()`. #) Fixed bug that cleared the isRecoverable flag when an Oracle error is wrapped by an ODPI-C specific error. #) Added method :func:`dpiData_getVector()` to retrieve the value of the data when the native type is `DPI_NATIVE_TYPE_VECTOR`. Version 5.4.1 (December 11, 2024) --------------------------------- #) Fixed bug calculating the maximum identifier length when using Oracle Client libraries 12.1, or older. The returned value may now be 0 when the size cannot be reliably determined by ODPI-C, which occurs when using Oracle Client libraries 12.1 (or older) to connect to Oracle Database 12.2, or later. #) Fixed bug resulting in a segfault when using external authentication (`python-oracledb issue 425 `__). Version 5.4.0 (November 5, 2024) -------------------------------- #) Added support for getting information about a connection in the structure :ref:`dpiConnInfo` using the new method :func:`dpiConn_getInfo()`. #) Fixed bug resulting in error ``ORA-25707: The token is invalid`` when using IAM token based authentication and creating multiple pooled connections. #) Fixed bug affecting Application Continuity with older Oracle Client libraries by ensuring that the mode indicating bound REF CURSOR statement handles are never re-used is only enabled with Oracle Client libraries 23.6 and higher. #) Disable support added in Oracle Client 23ai for connection pool ping intervals since this functionality is already available in ODPI-C. Version 5.3 (July 23, 2024) --------------------------- #) Added support for vector storage format ``DPI_VECTOR_FORMAT_BINARY`` available in Oracle Database 23.5 and higher. #) Eliminated memory leak when dequeing messages with JSON payloads (`python-oracledb issue 346 `__). #) Internal change: let the Oracle Client library know that bound REF CURSOR statement handles are never re-used. Version 5.2 (March 11, 2024) ---------------------------- #) Added methods :func:`dpiSodaDb_createJsonDocument()`, :func:`dpiSodaDoc_getIsJson()` and :func:`dpiSodaDoc_getJsonContent()` in order to support using JSON when fetching and binding SODA documents with Oracle Client 23 onward. This allows for seamless transfer of extended data types. In order to make use of this the member :member:`dpiContextCreateParams.sodaUseJsonDesc` must be set to 1 before calling :func:`dpiContext_createWithParams()`. #) Added new type ``DPI_ORACLE_TYPE_JSON_ID`` for JSON ids. In order to make use of this the member :member:`dpiContextCreateParams.useJsonId` must be set to 1 before calling :func:`dpiContext_createWithParams()`; otherwise, these values are returned as type ``DPI_ORACLE_TYPE_RAW``. #) Added attribute :member:`dpiDataTypeInfo.isOson` which is set to true when columns are fetched that have the "IS JSON FORMAT OSON" constraint enabled. #) Error ``DPI-1010: not connected`` is now raised when attempting to use a LOB with a closed connection instead of ``DPI-1040: LOB was already closed``. #) Errors ``DPI-1067: call timeout of %u ms exceeded with ORA-%05d`` and ``DPI-1080: connection was closed by ORA-%05d`` now retain the original error message. #) Added support for vectors. This requires Oracle Database 23ai and Oracle Client 23. Version 5.1 (December 19, 2023) ------------------------------- #) Added members :member:`dpiDataTypeInfo.domainSchema`, :member:`dpiDataTypeInfo.domainName`, and :member:`dpiDataTypeInfo.annotations` which provide the `SQL domain `__ and `annotations `__ associated with a column in Oracle Database 23ai. Also requires Oracle Client 23.1 or higher. #) Added methods :func:`dpiConn_getDbDomain()`, :func:`dpiConn_getDbName()`, :func:`dpiConn_getMaxOpenCursors()`, :func:`dpiConn_getServiceName()`, and :func:`dpiConn_getTransactionInProgress()` in order to provide additional metadata about the database. #) Added new type ``DPI_ORACLE_TYPE_XMLTYPE`` for data of type ``SYS.XMLTYPE`` to the :ref:`dpiOracleTypeNum` enumeration. Previously data of this type was returned as ``DPI_ORACLE_TYPE_LONG_VARCHAR``, which was unclear. Version 5.0.1 (October 10, 2023) -------------------------------- #) Fixed bug resulting in a segfault on some platforms when using two-phase commit. Version 5.0 (August 15, 2023) ----------------------------- #) Added function :func:`dpiSodaColl_listIndexes()` in order to get a list of the indexes for a SODA collection. #) Added function :func:`dpiContext_freeStringList()` which replaces the function dpiSodaDb_freeCollectionNames(). The new structure :ref:`dpiStringList` replaces the old structure dpiSodaCollNames. The old names are deprecated and will be removed in a future version. #) Added support for member :member:`dpiSodaOperOptions.lock`. This can only be used with Oracle Client 21.3 and higher (also available in Oracle Client 19 from 19.11). #) Added attribute :member:`dpiDataTypeInfo.isJson` which is set to true when columns are fetched that are of type `DPI_ORACLE_TYPE_JSON` or have the "IS JSON" constraint enabled. #) Added method :func:`dpiConn_getInstanceName()` in order to be able to get the Oracle Database instance name associated with the connection. This is the same value as given by the SQL expression ``sys_context('userenv', 'instance_name')``. #) Added support for the embedded OIDs found in SODA documents in Oracle Database 23ai. #) Adjusted the value of the attribute :member:`dpiJsonNode.nativeTypeNum` to be `DPI_NATIVE_TYPE_FLOAT` when the value stored in JSON is a float value. Previously the value was `DPI_NATIVE_TYPE_DOUBLE` (`issue 174 `__). #) Added support for automatically retrying a query if the error ``ORA-00932: inconsistent data types`` is raised (which can occur if a table or view is recreated with a data type that is incompatible with the column's previous data type). #) Dropped functions dpiConn_beginDistribTrans() and dpiConn_prepareDistribTrans() which were deprecated in version 4.3. Version 4.6.1 (March 30, 2023) ------------------------------ #) Added support for the "signed int", "signed long" and "decimal128" scalar types in JSON (generally only seen when converting from MongoDB). Version 4.6 (November 10, 2022) ------------------------------- #) Added attributes :member:`~dpiObjectTypeInfo.packageName` and :member:`~dpiObjectTypeInfo.packageNameLength` to structure :ref:`dpiObjectTypeInfo`. #) Defer debugging startup until first use of an ODPI-C function instead of upon loading of the library. Version 4.5 (September 13, 2022) -------------------------------- #) Added support for OAuth token authentication when creating standalone connections and connection pools. #) Added support for enqueuing and dequeuing JSON payloads using Advanced Queuing (AQ). Functions :func:`dpiConn_newJson()`, :func:`dpiConn_newJsonQueue()`, :func:`dpiMsgProps_getPayloadJson()` and :func:`dpiMsgProps_setPayloadJson()` were added to support this functionality. Version 4.4.1 (June 14, 2022) ----------------------------- #) Fixed ability to use constant `DPI_ORACLE_TYPE_LONG_NVARCHAR` when creating variables to fetch NCLOB values. #) Adjusted test suite and samples for token based authentication to more closely follow the behavior of the Oracle Client libraries. Version 4.4 (May 20, 2022) -------------------------- #) Added support for token based authentication when establishing pool based connections and standalone connections. #) Added method :func:`dpiMsgProps_setRecipients()` to support the recipients list message property of AQ. #) Added attribute :member:`dpiSubscrMessage.aqMsgId` which provides the message id of an AQ message that is available to dequeue. #) Added constant `DPI_ORACLE_TYPE_LONG_NVARCHAR`. This type cannot be represented in an Oracle database but is used when fetching NCLOB data as a string. #) Fixed bug resulting in a segfault when certain errors occur during the binding of a variable (`issue 168 `__). #) Prefer the use of memcpy() over strncpy(), even though embedded NULL characters in XID values are extremely unlikely (`issue 175 `__). #) Fixed bug resulting in error ORA-25263 when attempting to dequeue a message with a specific message ID that is known to exist. #) Improved documentation and the test suite. Version 4.3 (November 4, 2021) ------------------------------ #) Added methods :func:`dpiData_getJson()`, :func:`dpiData_getJsonArray()`, :func:`dpiData_getJsonObject()` to retrieve the value of the data when the native types are `DPI_NATIVE_TYPE_JSON`, `DPI_JSON_TYPE_JSON_ARRAY` and `DPI_NATIVE_TYPE_JSON_OBJECT` respectively. #) Added method :func:`dpiJson_setFromText()` to set a JSON value from a JSON string. #) Added method :func:`dpiVar_setFromJson()` to set the value of a JSON variable to a specified JSON value. #) Enhanced support for TPC (two-phase commit). The functions :func:`dpiConn_tpcBegin()`, :func:`dpiConn_tpcCommit()`, :func:`dpiConn_tpcEnd()`, :func:`dpiConn_tpcForget()`, :func:`dpiConn_tpcPrepare()` and :func:`dpiConn_tpcRollback()` were added. The functions dpiConn_beginDistribTrans() and dpiConn_prepareDistribTrans() are deprecated and will be removed in a future version. #) Added function :func:`dpiConn_setEcontextId()` to enable setting the execution context id attribute on connections. #) Added method :func:`dpiStmt_deleteFromCache()` to exclude the associated SQL statement from getting added to the statement cache. #) Added support for setting JSON node values using the following type combinations: `DPI_ORACLE_TYPE_NATIVE_DOUBLE` with `DPI_NATIVE_TYPE_DOUBLE` and `DPI_ORACLE_TYPE_NATIVE_FLOAT` with `DPI_NATIVE_TYPE_FLOAT` (`issue 155 `__). #) The method OCIAQDeq() is now used for single message dequeue in order to support dequeue of Oracle Transactional Event Queue (TEQ) messages. #) Added function :func:`dpiConn_getIsHealthy()` to do a local, light-weight connection health check. #) Added constant `DPI_ORACLE_TYPE_UROWID` as a synonym for `DPI_ORACLE_TYPE_ROWID` and placeholder for when it is possible to distinguish between ROWID and UROWID columns in the database. Version 4.2.1 (June 1, 2021) ---------------------------- #) Added support for caching the database version in pooled connections with Oracle Client 19 and earlier (later Oracle Clients handle this caching internally). This optimization eliminates a round-trip previously often required when reusing a pooled connection. #) Fixed a regression with error messages raised during connection creation. #) All errors identified as causing a dead connection now populate :member:`dpiErrorInfo.sqlState` with the value `01002` instead of only a hard-coded list of errors. #) Improved documentation and the test suite. Version 4.2 (May 18, 2021) -------------------------- #) Added methods :func:`dpiPool_getMaxSessionsPerShard()`, :func:`dpiPool_getPingInterval()`, :func:`dpiPool_setMaxSessionsPerShard()`, :func:`dpiPool_setPingInterval()` and :func:`dpiPool_reconfigure()` in order to support changing pool configuration after the pool has been created. #) Added support for the SODA metadata cache available in Oracle Client 21.3 and higher (also available in Oracle Client 19 from 19.11). This significantly improves the performance of repeated calls to methods :func:`dpiSodaDb_createCollection()` (when not specifying a value for the metadata parameter) and :func:`dpiSodaDb_openCollection()`. The member :member:`dpiCommonCreateParams.sodaMetadataCache` has been added and functions :func:`dpiPool_getSodaMetadataCache()` and :func:`dpiPool_setSodaMetadataCache()` have been added. #) Added support for supplying hints to SODA operations. The members :member:`dpiSodaOperOptions.hint` and :member:`dpiSodaOperOptions.hintLength` were added and methods :func:`dpiSodaColl_insertOneWithOptions()`, :func:`dpiSodaColl_insertManyWithOptions()` and :func:`dpiSodaColl_saveWithOptions()` were added. These can only be used with Oracle Client 21.3 and higher (also available in Oracle Client 19 from 19.11). #) Added support for specifying the size of the statement cache when a pool or standalone connection is created. The member :member:`dpiCommonCreateParams.stmtCacheSize` was added and can be populated with the desired value prior to calling :func:`dpiPool_create()` or :func:`dpiConn_create()`. #) Added function :func:`dpiLob_getType()` in order to get the type of a LOB, as requested (`issue 135 `__). #) Changed the requirement for the method :func:`dpiSodaColl_save()` to Oracle Client 19.9 or higher (instead of 20.1 or higher). #) Added flag to internal calls made by method :func:`dpiSodaColl_getDataGuide()` to ensure that the returned content is in encoding UTF-8. This ensures consistency with other SODA documents returned by ODPI-C. #) Corrected internal handling of flags sent to :func:`dpiSodaDocCursor_getNext()` and :func:`dpiSodaCollCursor_getNext()`. #) The distributed transaction handle assosciated with the connection is now cleared on commit or rollback (`cx_Oracle issue 530 `__). #) When calling :func:`dpiJson_getValue()`, any cached value is now cleared before getting the new value in order to take into account possible calls to :func:`dpiJson_setValue()` that were made in between or to take into account the passing of different flags (`issue 154 `__). #) Corrected internal handling of client version information when creating multiple contexts (`issue 156 `__). #) Threaded mode is now always enabled when creating pools, regardless of what mode is provided in the :member:`dpiCommonCreateParams.createMode` member in order to provide for greater safety. Although there may be instances where threaded mode is not strictly needed, these are few and any advantages are minimal. #) Improved dead connection detection. If any error occurs that indicates that the connection is no longer usable, the connection is marked as dead and the unified error `DPI-1080: connection was closed by ORA-%d` (where the `%d` is replaced by the Oracle error that caused the connection to be closed) is returned instead. Attempts to use the connection after this result in the error `DPI-1010: not connected` being returned. This includes call timeout errors such as when :func:`dpiConn_setCallTimeout()` is called with a value set too low to allow the connection to break the executing statement and reset after the timeout occurs. #) Improved documentation and the test suite. Version 4.1 (December 8, 2020) ------------------------------ #) Added support for the new JSON data type available in Oracle Client and Database 21 and higher. #) Added methods :func:`dpiConn_getOciAttr()`, :func:`dpiConn_setOciAttr()`, :func:`dpiStmt_getOciAttr()` and :func:`dpiStmt_setOciAttr()` in order to be able to get and set OCI attributes that are otherwise not supported by ODPI-C. These methods should only be used as directed by Oracle. #) Workaround unexpected error when calling :func:`dpiLob_readBytes()` with a very small value in the `valueLength` parameter (`issue 146 `__). #) Ensure that calls to :func:`dpiStmt_setPrefetchRows()` are honored when binding as a REF cursor. #) Improved documentation and the test suite. Version 4.0.2 (August 31, 2020) ------------------------------- #) Adjusted check for GNU version of strerror_r() on Cygwin as suggested (`issue 138 `__). #) Up to 40 digits can be represented in an unconstrained Oracle number so allow for that possibility (`cx_Oracle issue 459 `__). #) Correct double free error (`issue 141 `__). #) Improved documentation and adjusted test suite. Version 4.0.1 (June 26, 2020) ----------------------------- #) Ensure that all members of the ``dpiErrorInfo`` structure parameter are set properly during a call to :func:`dpiContext_getError()`. Version 4.0 (June 25, 2020) --------------------------- #) Replaced function ``dpiContext_create()`` with :func:`dpiContext_createWithParams()`. A new structure :ref:`dpiContextCreateParams` can be passed to this function, enabling applications or drivers to modify how the Oracle Client library is loaded. In particular the structure allows the directories for Oracle Client libraries and configuration files to be specified. The original function ``dpiContext_create()`` is still available as a macro that calls the new function and passes NULL for the parameters (meaning all built-in defaults will be used). #) The default encoding for all character data is now UTF-8 but can be overridden by setting the member :member:`dpiContextCreateParams.defaultEncoding` before calling :func:`dpiContext_createWithParams()`. Setting the members :member:`dpiCommonCreateParams.encoding` and :member:`dpiCommonCreateParams.nencoding` to NULL will use the ``NLS_LANG`` and ``NLS_NCHAR`` environment variables, which was the previous default. #) The algorithm by which the Oracle Client library is loaded was improved. See the :ref:`installation guide` for more details. #) Added new debugging level (64) for debugging the loading of the Oracle Client libraries (https://github.com/oracle/odpi/issues/131). See :ref:`debugging` for more details. #) Renamed debugging level 1 to ``DPI_DEBUG_LEVEL_UNREPORTED_ERRORS`` to be more clear as to its purpose. #) Added methods :func:`dpiSodaColl_save()` and :func:`dpiSodaColl_truncate()` available in Oracle Client 20 and higher. #) Added member :member:`dpiSodaOperOptions.fetchArraySize` which defines the array size to use when fetching SODA documents from a collection. It is available in Oracle Client 19.5 and higher. #) Internally make use of new mode available in Oracle Client 20.3 and higher in order to avoid a round-trip when calling :func:`dpiConn_getServerVersion()` with ``releaseString`` set to NULL. #) Added member :member:`dpiErrorInfo.isWarning` to identify warnings that are returned when calling :func:`dpiContext_getError()`. After a method returns ``DPI_SUCCESS``, a call to :func:`dpiContext_getError()` can be made to determine if a warning has been created. Calling any other function will result in the warning being cleared. Known warnings include ``ORA-28002: the password will expire within %d days`` (after a successful call to :func:`dpiPool_create()` or :func:`dpiConn_create()`) and ``ORA-24344: success with compilation error`` (after a successful call to :func:`dpiStmt_execute()` to create a stored procedure with compilation errors). #) Modified member :member:`dpiErrorInfo.offset` to be 32-bit and added new member :member:`dpiErrorInfo.offset16` for backwards compatibility; in this way row offsets that exceed 65536 can be reported successfully (`node-oracledb issue 1157 `__). #) Added method :func:`dpiConn_startupDatabaseWithPfile()` in order to support starting up the database with a parameter file (PFILE), as requested (`issue 41 `__). #) Added support for converting all three timestamp types to/from double values (number of milliseconds since January 1, 1970) as used by frameworks such as Node.js. #) When an INSERT ALL statement is executed, return NULL in the ``rowid`` parameter to :func:`dpiStmt_getLastRowid()` instead of the error ``DPI-1004: unable to get error message``. #) Added methods :func:`dpiStmt_getPrefetchRows()` and :func:`dpiStmt_setPrefetchRows()` in order to control how many rows the Oracle Client library prefetches when calling :func:`dpiStmt_execute()` for a query (`issue 73 `__). #) Added support for returning DATE values as ``DPI_NATIVE_TYPE_DOUBLE``, as commonly used by environments like Node.js #) Added DLL export attribute for Windows, as suggested by Kubo (`issue 126 `__). #) Improved documentation, samples, tutorial and test suite. Version 3.3 (December 2, 2019) ------------------------------ #) Added support for CQN and other subscription :member:`~dpiSubscrCreateParams.clientInitiated` connections to the database (as opposed to the default server initiated connections). #) Added function :func:`dpiStmt_getLastRowid()` for getting the rowid of the last row affected by a DML statement (`issue 111 `__). #) Added support for setting the :member:`~dpiPoolCreateParams.maxSessionsPerShard` attribute for session pools. #) Added support for providing double input for DATE sharding keys, as required by environments like Node.js. #) Corrected processing of DATE sharding keys (sharding requires a slightly different format to be passed to the server). #) Added support for using TIMESTAMP columns as sharding keys. #) Added check to ensure sharding key is specified when a super sharding key is specified. #) Improved error message when the library is loaded successfully but the attempt to detect the version of the library fails, either due to the fact that the library is too old or the method could not be called for some reason (`node-oracledb issue 1168 `__). #) Adjusted support for creating a connection using an existing service context handle. The service context handle and its associated environment handle are now used directly in order to avoid potential memory corruption. #) Made the ``releaseString`` and ``releaseStringLength`` parameters to :func:`dpiConn_getServerVersion()` optional since they are not frequently used. #) Added ``ORA-3156: OCI call timed out`` to the list of error messages that result in error DPI-1067. #) Allow a NULL pointer to be passed to :func:`dpiVar_setFromBytes()` and :func:`dpiLob_setFromBytes()` when the length is zero. #) Improved documentation and test suite. Version 3.2.2 (October 1, 2019) ------------------------------- #) Ensured that sharding keys are dedicated to the connection that is acquired using them in order to avoid possible hangs, crashes or unusual errors. #) Corrected support for PLS_INTEGER and BINARY_INTEGER types when used in PL/SQL records (`issue 112 `__). #) Improved documentation for :func:`dpiLob_getSize()`, :func:`dpiLob_readBytes()` and :func:`dpiLob_writeBytes()` regarding the lengths reported in number of characters (`issue 94 `__). Version 3.2.1 (August 12, 2019) ------------------------------- #) A more meaningful error is now returned when calling :func:`dpiSodaColl_insertMany()` with an empty array. #) A more meaningful error is now returned when calling :func:`dpiSubscr_prepareStmt()` with SQL that is not a SELECT statement. #) Eliminated a segfault when calling :func:`dpiConn_close()` when a value was specified for the connection class during connection creation. #) Added documentation discussing round-trips to the database, as requested (`issue 108 `__). #) Improved processing of internal handle lists. Version 3.2 (July 1, 2019) -------------------------- #) Added support for enqueue and dequeue of RAW payloads and for bulk enqueue and dequeue of messages. The methods dpiConn_deqObject() and dpiConn_enqObject() are deprecated and will be removed in version 4.0. The new methods :func:`dpiConn_newQueue()`, :func:`dpiQueue_deqMany()`, :func:`dpiQueue_deqOne()`, :func:`dpiQueue_enqMany()` and :func:`dpiQueue_enqOne()` should be used instead (`issue 58 `__ and `issue 104 `__). #) Added support for getting the registration id for a CQN subscription, as requested (`node-oracledb issue 1075 `__). #) Removed preview status from existing SODA functionality. See `this tracking issue `__ for known issues with SODA. #) Added support for a preview of SODA bulk insert, available in Oracle Client 18.5 and higher. #) Added support for setting the LOB prefetch length indicator in order to reduce the number of round trips when processing LOB values. #) Added support for getting and setting timestamp and date attributes of objects as double values (number of milliseconds since January 1, 1970), as preferred by some environments like Node.js. #) Added support for types BINARY_INTEGER, PLS_INTEGER, ROWID, LONG and LONG RAW when used in PL/SQL. #) Eliminated memory leak when fetching objects that are atomically null (`cx_Oracle issue 298 `__). #) Eliminated memory leak when setting LOB attributes on objects. #) Eliminated bug when attempting to unregister a subscription while callbacks are ongoing. #) Eliminated bug when processing the string representation of numbers like 1e-08 and 1e-09 (`cx_Oracle issue 300 `__). #) Eliminated attempt to adjust the time a session was last used (to manage internal pool pinging functionality) if the pool is being closed. #) Eliminated potential segfault when an implicit result statement is closed before its parent statement is closed. #) Eliminated overhead by deferring the creation of OCI error handles until they are needed. #) Replaced prefix "Test" with "Demo" on all sample file names. #) Added additional test cases. #) Documentation improvements. Version 3.1.4 (April 24, 2019) ------------------------------ #) Added support for getting the row count for PL/SQL statements (`cx_Oracle issue 285 `__). Version 3.1.3 (March 12, 2019) ------------------------------ #) Ensure that the strings "-0" and "-0.0" are correctly handled as zero values (`cx_Oracle issue 274 `__). #) When using an external handle, create a new service context handle so that there are no discrepancies in character sets between the service context and the newly created environment handle (`cx_Oracle issue 273 `__). #) Eliminated error when startup and shutdown events are generated (`issue 102 `__). #) Improved documentation. Version 3.1.2 (February 19, 2019) --------------------------------- #) Corrected code for freeing CQN message objects when multiple queries are registered (`issue 96 `__). #) Fixed typo in documentation (`issue 97 `__). #) Improved error messages and installation documentation. Version 3.1.1 (February 4, 2019) -------------------------------- #) Improved code preventing a statement from binding itself, in order to avoid a potential segfault under certain cirumstances. #) Always set :member:`dpiConnCreateParams.outNewSession` to the appropriate value when calling :func:`dpiPool_acquireConnection()` or :func:`dpiConn_create()`. #) Worked around OCI bug when attempting to free objects that are PL/SQL records, in order to avoid a potential segfault. #) Added samples demonstrating how to fetch CLOBs as strings and BLOBs as bytes (preferred for smaller LOBs). #) Documentation improvements based on feedback (`issue 87 `__, `issue 88 `__, `issue 90 `__, `issue 91 `__, `issue 92 `__). Version 3.1 (January 21, 2019) ------------------------------ #) Added support for getting and setting attributes of type RAW on Oracle objects, as requested (`issue 72 `__). #) Added function :func:`dpiData_getIsNull()` for getting the null indicator from a :ref:`dpiData ` structure and function :func:`dpiData_setNull()` for setting a value to null, as requested (`issue 82 `__). #) Added support for fetching SYS.XMLTYPE objects as string data, limited to the VARCHAR2 length (`cx_Oracle issue 14 `__). #) Added support for multi-property session tags and added attribute :member:`dpiPoolCreateParams.plsqlFixupCallback` for identifying a PL/SQL callback that will be executed when a requested tag doesn't match the tag associated with a pooled connection. Both of these features are only available in Oracle Client 12.2 and higher. #) The attribute :member:`dpiConnCreateParams.outNewSession` was added to support determining if a session in a pool is completely new and has never been acquired from the pool. #) Added support for performing external authentication with proxy for standalone connections. #) Added error message when external authentication with proxy is attempted without placing the user name in [] (proxy authentication is otherwise silently ignored). #) Exempted additional error messages from forcing the statement to be dropped from the cache (`issue 76 `__). #) Tightened up handling of numeric values when converted from a string representation. The error message returned when the string cannot be converted to an Oracle number was also improved. #) Completed enabling of pool pinging functionality for 12.2+ clients (see attribute :member:`dpiPoolCreateParams.pingInterval` for more information on this feature). #) Ensured that the connection returned from the pool after a failed ping (such as due to a killed session) is not itself marked as needing to be dropped. #) Eliminated memory leak under certain circumstances when pooled connections are released back to the pool. #) Eliminated memory leak when connections are dropped from the pool. #) Eliminated memory leak when calling :func:`dpiConn_close()` after fetching collections from the database. #) Adjusted order in which memory is freed when the last references to SODA collections, documents, document cursors and collection cursors are released, in order to prevent a segfault under certain circumstances. #) Improved error message when using an older version of the ODPI-C library. #) Added additional test cases. #) Improved documentation. Version 3.0.0 (September 13, 2018) ---------------------------------- #) Added support for Oracle Client 18 libraries. #) Added support for SODA (as preview). See :ref:`SODA Database`, :ref:`SODA Collection` and :ref:`SODA Document` for more information. #) Added support for call timeouts available in Oracle Client 18.1 and higher. See functions :func:`dpiConn_setCallTimeout()` and :func:`dpiConn_getCallTimeout()`. #) Added support for setting a LOB attribute of an object with string/bytes using the function :func:`dpiObject_setAttributeValue()`. #) Added support for the packed decimal type used by object attributes with historical types DECIMAL and NUMERIC (`cx_Oracle issue 212 `__). #) On Windows, first attempt to load oci.dll from the same directory as the module that contains ODPI-C. #) SQL Objects that are created or fetched from the database are now tracked and marked unusable when a connection is closed. This was done in order to avoid a segfault in some circumstances. #) Improved support for closing pools by ensuring that once a pool has closed, further attempts to use connections acquired from that pool will fail with error "DPI-1010: not connected". #) Re-enabled pool pinging functionality for Oracle Client 12.2 and higher to handle classes of connection errors such as resource profile limits. #) Improved error messages when the Oracle Client or Oracle Database need to be at a minimum version in order to support a particular feature. #) Use plain integers instead of enumerations in order to simplify code and reduce the requirement for casts. Typedefs have been included so that code does not need to be changed. #) Eliminated potential buffer overrun (`issue 69 `__). #) In the Makefile for non-Windows platforms, the version information for ODPI-C is acquired directly from include/dpi.h as suggested (`issue 66 `__). #) Removed function dpiConn_newSubscription(). Use function :func:`dpiConn_subscribe()` instead. #) Removed function dpiLob_flushBuffer(). This function never worked anyway. #) Removed function dpiSubscr_close(). Use function :func:`dpiConn_unsubscribe()` instead. #) Removed function dpiVar_getData(). Use function :func:`dpiVar_getReturnedData()` instead. #) Added additional test cases. #) Improved documentation. Version 2.4.2 (July 9, 2018) ---------------------------- #) Avoid buffer overrun due to improper calculation of length byte when converting some negative 39 digit numbers from string to the internal Oracle number format (`issue 67 `__). Version 2.4.1 (July 2, 2018) ---------------------------- #) Use the install_name_tool on macOS to adjust the library name, as suggested (`issue 65 `__). #) Even when dequeue fails OCI still provides a message id so make sure it is deallocated to avoid a memory leak. #) Ensure that the row count for queries is reset to zero when the statement is executed (`cx_Oracle issue 193 `__). #) If the statement should be deleted from the statement cache, first check to see that there is a statement cache currently being used; otherwise, the error "ORA-24300: bad value for mode" will be raised under certain conditions. Version 2.4 (June 6, 2018) -------------------------- #) Added support for grouping events for subscriptions. See attributes :member:`dpiSubscrCreateParams.groupingClass`, :member:`dpiSubscrCreateParams.groupingValue` and :member:`dpiSubscrCreateParams.groupingType`. #) Added support for specifying the IP address a subscription should use instead of having the Oracle Client libraries determine the IP address to use on its own. See attributes :member:`dpiSubscrCreateParams.ipAddress` and :member:`dpiSubscrCreateParams.ipAddressLength`. #) Added support for subscribing to notifications when messages are available to dequeue in an AQ queue. See attribute :member:`dpiSubscrCreateParams.subscrNamespace` and the enumeration :ref:`dpiSubscrNamespace` as well as the attributes :member:`dpiSubscrMessage.queueName`, :member:`dpiSubscrMessage.queueNameLength`, :member:`dpiSubscrMessage.consumerName` and :member:`dpiSubscrMessage.consumerNameLength`. #) Added attribute :member:`dpiSubscrMessage.registered` to allow the application to know when a subscription is no longer registered with the database. Deregistration can take place when the :member:`dpiSubscrCreateParams.timeout` value is reached or when :member:`dpiSubscrCreateParams.qos` is set to the value DPI_SUBSCR_QOS_DEREG_NFY. Note that notifications are not sent when a subscription is explicitly deregistered. #) Added method :func:`dpiConn_subscribe()` to replace method dpiConn_newSubscription() and added method :func:`dpiConn_unsubscribe()` to replace method dpiSubscr_close(). The replaced methods are deprecated and will be removed in version 3.0. The new methods clarify the fact that subscriptions do not require the connection they were created with to remain open. A new connection with the same credentials can be used to unusbscribe from events in the database. #) Added support for the pool "get" mode of timed wait. See attributes :member:`dpiPoolCreateParams.getMode` and :member:`dpiPoolCreateParams.waitTimeout`. The wait timeout value can be acquired after pool creation using the new method :func:`dpiPool_getWaitTimeout()` and set after pool creation using the new method :func:`dpiPool_setWaitTimeout()`. #) Added support for setting the maximum lifetime session and timeout parameters when creating a pool. See attributes :member:`dpiPoolCreateParams.maxLifetimeSession` and :member:`dpiPoolCreateParams.timeout`. #) Added support for installing ODPI-C into a user-defined prefix on platforms other than Windows, as requested (`issue 59 `__). #) Added support for setting the SONAME for shared libraries on platforms other than Windows, as requested (`issue 44 `__). #) Improved error message when attempting to create a subscription without enabling events mode when the pool or standalone connection is created. #) Added checks for minimal Oracle Client version (12.1) when calling the methods :func:`dpiPool_getMaxLifetimeSession()` and :func:`dpiPool_setMaxLifetimeSession()`. #) Added check to prevent attempts to bind PL/SQL array variables using the method :func:`dpiStmt_executeMany()`. #) Ensure that method :func:`dpiStmt_getRowCount()` returns the value 0 for all statements other than queries and DML, as documented. #) Correct handling of ROWIDs and statements when used as bind variables during execution of DML RETURNING statements. #) Added additional test cases. #) Improved documentation. Version 2.3.2 (May 7, 2018) --------------------------- #) Ensure that a call to unregister a subscription only occurs if the subscription is still registered. #) Ensure that before a statement is executed that any dynamic buffers created for DML returning statments are reset since the out bind callback is not called if no rows are returned! #) Silenced compilation warning in test suite. #) Added test cases for DML returning statements. Version 2.3.1 (April 25, 2018) ------------------------------ #) Fixed determination of the number of rows returned in a DML Returning statement when the same statement is executed multiple times in succession with less rows being returned in each succeeding execution. #) Stopped attempting to unregister a CQN subscription before it was completely registered. This prevents errors encountered during registration from being masked by an error stating that the subscription has not been registered! #) Fixed support for true heterogeneous session pools that use different user/password combinations for each session acquired from the pool. #) Added error message indicating that modes DPI_MODE_EXEC_BATCH_ERRORS and DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS are only supported with insert, update, delete and merge statements. #) Corrected comment (`issue 61 `__). #) Renamed internal method dpiStmt__preFetch() to dpiStmt__beforeFetch() in order to avoid confusion with OCI prefetch. Version 2.3 (April 2, 2018) --------------------------- #) Corrected support for getting the OUT values of bind variables bound to a DML Returning statement when calling the function :func:`dpiStmt_executeMany()`. Since multiple rows can be returned for each iteration, a new function :func:`dpiVar_getReturnedData()` has been added and the original function :func:`dpiVar_getData()` has been deprecated and will be removed in version 3. #) Corrected binding of LONG data (values exceeding 32KB) when using the function :func:`dpiStmt_executeMany()`. #) Added code to verify that the CQN subscription is open before permitting it to be used. Error "DPI-1060: subscription was already closed" will now be raised if an attempt is made to use a subscription that was closed earlier. #) Added error "DPI-1061: edition is not supported when a new password is specified" to clarify the fact that specifying an edition and a new password at the same time is not supported. Previously the edition value was simply ignored. #) Query metadata is no longer fetched if executing a statement with mode DPI_MODE_EXEC_PARSE_ONLY. #) Added additional statement types (DPI_STMT_TYPE_EXPLAIN_PLAN, DPI_STMT_TYPE_ROLLBACK and DPI_STMT_TYPE_COMMIT) as well as one that covers statement types not currently identified (DPI_STMT_TYPE_UNKNOWN). #) Improved error message when older OCI client libraries are being used that don't have the method OCIClientVersion(). #) Corrected the handling of ANSI types REAL and DOUBLE PRECISION as implemented by Oracle. These types are just subtypes of NUMBER and are different from BINARY_FLOAT and BINARY_DOUBLE (`cx_Oracle issue 163 `__). #) Added check that the return value from OCI functions matches the expected value of OCI_ERROR, and if not, raises an error including the value that was actually returned. #) Added additional test cases. #) Removed unused error messages. Version 2.2.1 (March 5, 2018) ----------------------------- #) Maintain a reference to the "parent" object and use the actual object instance instead of a copy, so that "child" objects can be manipulated in-place instead of having to be created externally and then set (attributes) or appended (collections). #) Correct handling of boundary numbers 1e126 and -1e126. #) Eliminate memory leak when calling :func:`dpiConn_deqObject()` and :func:`dpiConn_enqObject()`. #) Eliminate memory leak when setting NCHAR and NVARCHAR attributes of objects. #) Eliminate memory leak when fetching collection objects from the database. #) Prevent internal re-execution of statement from duplicating itself in the list of open statements maintained on the connection. #) Improved documentation. Version 2.2 (February 14, 2018) ------------------------------- #) Keep track of open statements and LOBs and automatically close them when the connection is closed; this eliminates the need for users of the driver to do so and removes the error "DPI-1054: connection cannot be closed when open statements or LOBs exist". #) Ignore failures that occur during the implicit rollback performed when a connection is closed, but if an error does occur, ensure that the connection is dropped from the pool (if it was acquired from a pool); such failures are generally due to an inability to communicate with the server (such as when your session has been killed). #) Avoid a round trip to the database when a connection is released back to the pool by preventing a rollback from being called when there is no transaction in progress. #) Improve error message when the use of bind variables is attempted with DDL statements, which is not supported. #) Since rowid is returned as a handle, the size in bytes and characters was simply being returned as the size of a pointer; set these values to 0 instead as is done with other handles that are returned. #) Ensure that the LOB locator returned from the object attribute or element is not used directly as freeing it will result in unexpected behavior when the object containing it is itself freed. #) Make a copy of any objects that are acquired from other objects (either as attributes or elements of collections) in order to prevent possible use of the object acquired in such a fashion after the object it came from has been freed. #) Protect global variables on destruction as well since dpiGlobal__finalize() may not be the last method that is called if other methods are registered with atexit(). #) Use cast to avoid assertions with isspace() when using debug libraries on Windows (`issue 52 `__). #) Added file embed/dpi.c to simplify inclusion of ODPI-C in projects. #) Minor changes to satisfy pickier compilers and static analysis tools. #) Added additional test cases. #) Improved documentation. Version 2.1 (December 12, 2017) ------------------------------- #) Connections - Support was added for accessing sharded databases via sharding keys (new in Oracle 12.2). NOTE: the underlying OCI library has a bug when using standalone connections. There is a small memory leak proportional to the number of connections created/dropped. There is no memory leak when using session pools, which is recommended. - Added options for authentication with SYSBACKUP, SYSDG, SYSKM and SYSRAC, as requested (`cx_Oracle issue 101 `__). - Attempts to release statements or free LOBs after the connection has been closed (by, for example, killing the session) are now prevented. - An error message was added when specifying an edition and a connection class since this combination is not supported. - Attempts to close the session for connections created with an external handle are now prevented. - Attempting to ping a database earlier than 10g results in ORA-1010: invalid OCI operation, but that implies a response from the database and therefore a successful ping, so treat it that way! (see ``__ for more information). #) Objects - Support was added for converting numeric values in an object type attribute to integer and text, as requested (`issue 35 `__). - Methods :func:`dpiDeqOptions_setMsgId()` and :func:`dpiMsgProps_setOriginalMsgId()` now set their values correctly. - The overflow check when using double values as input to float attributes of objects or elements of collections was removed as it didn't work anyway and is a well-known issue that cannot be prevented without removing desired functionality. The developer should ensure that the source value falls within the limits of floats, understand the consequent precision loss or use a different data type. #) Variables - Support was added for setting a LOB variable using :func:`dpiVar_setFromBytes()`. - Added support for the case when the time zone minute offset is negative, as requested (`issue 38 `__). - Variables of type DPI_NATIVE_TYPE_BYTES are restricted to 2 bytes less than 1 GB (1,073,741,822 bytes), since OCI cannot handle more than that currently. #) Miscellaneous - Support was added for identifying the id of the transaction which spawned a CQN subscription message, as requested (`issue 32 `__). - Corrected use of subscription port number (`cx_Oracle issue 115 `__). - Added support for getting information about MERGE statements, as requested (`issue 40 `__). - Problems reported with the usage of FormatMessage() on Windows was addressed (`issue 47 `__). - On Windows, if oci.dll cannot be loaded because it is the wrong architecture (32-bit vs 64-bit), attempt to find the offending DLL and include the full path of the DLL in the message, as suggested (`issue 49 `__). #) Debugging - Support was added to the debugging infrastructure to print the thread id and the date/time of messages. Support for an environment variable DPI_DEBUG_PREFIX was also added. See :ref:`debugging`. - Support was added for debugging both entry and exit points of ODPI-C public functions and for memory allocation/deallocation. #) Infrastructure - Dependent libraries were moved to the main Makefile so that applications do not have to do that, as suggested (`issue 33 `__). - Added Makefile.win32 for the use of nmake on Windows and reworked existing Makefiles to support only platforms other than Windows. - Ensure that ODPI-C extended initialization code takes place before any other ODPI-C code can take place, and that it takes place in only one thread. Code was also added to cleanup the global OCI environment on process exit. - The OCI wrapers for using mutexes were eliminated, which improves performance. - Force OCI prefetch to always use the value 2; the OCI default is 1 but setting the ODPI-C default to 2 ensures that single row fetches don't require an extra round trip to determine if there are more rows to fetch; this change also reduces the potential memory consumption when fetchArraySize was set to a large value and also avoids performance issues discovered with larger values of prefetch. - Unused parameters for internal functions were removed where possible and ``__attribute((unused))`` added where not possible, as requested (`issue 39 `__). - The use of OCIThreadKeyInit() in any code other than the global initialization code was removed in order to avoid bugs in the OCI library. - Compiler warnings and Parfait warnings were eliminated. - Added additional test cases. - Documentation improvements. #) Deprecations - The function dpiLob_flushBuffer() is deprecated and will be removed in version 3. It previously always returned an error anyway because of the inability to enable LOB buffering and now always returns the error "DPI-1013: not supported". Version 2.0.3 (November 6, 2017) -------------------------------- #) Prevent use of unitialized data in certain cases (`cx_Oracle issue 77 `__). #) Attempting to ping a database earlier than 10g results in error "ORA-1010: invalid OCI operation", but that implies a response from the database and therefore a successful ping, so treat it that way! #) Some values represented as double do not convert perfectly to float; use FLT_EPSILON to check the difference between the two after conversion, rather than expect the values to convert perfectly. #) Prevent use of NaN with Oracle numbers since it produces corrupt data (`cx_Oracle issue 91 `__). #) Verify that Oracle objects bound to cursors, fetched from cursors, set in object attributes or appended to collection objects are of the correct type. #) Correct handling of NVARCHAR2 when used as attributes of Oracle objects or elements of collections (`issue 45 `__). Version 2.0.2 (August 30, 2017) ------------------------------- #) Don't prevent connection from being explicitly closed when a fatal error has taken place (`cx_Oracle issue 67 `__). #) Correct handling of objects when dynamic binding is performed. #) Process deregistration events without an error. #) Eliminate memory leak when calling dpiObjectType_createObject(). Version 2.0.1 (August 18, 2017) ------------------------------- #) Ensure that any allocated statement increments the open child count (`issue 27 `__). #) Correct parameter subscrId to dpiConn_newSubscription() as `noted `__. There is no OCI documentation for this attribute and should never have been exposed. The parameter is therefore deprecated and will be removed in version 3. The value NULL can now also be passed to this parameter. #) Add script for running valgrind and correct issues found in test suite reported by valgrind (`issue 29 `__). #) Use posix_spawn() instead of system() in the test suite, as requested (`issue 30 `__). #) Add support for DML Returning statements that require dynamically allocated variable data (such as CLOBs being returned as strings). Version 2.0.0 (August 14, 2017) ------------------------------- #) Added new structure :ref:`dpiDataTypeInfo` and modified structures :ref:`dpiQueryInfo`, :ref:`dpiObjectAttrInfo` and :ref:`dpiObjectTypeInfo` in order to add support for fractional seconds precision on timestamps and interval day to second values (`issue 22 `__) and to support additional metadata on object types and attributes (`issue 23 `__). #) Prevent closing the connection when there are any open statements or LOBs and add new error "DPI-1054: connection cannot be closed when open statements or LOBs exist" when this situation is detected; this is needed to prevent crashes under certain conditions when statements or LOBs are being acted upon while at the same time (in another thread) a connection is being closed; it also prevents leaks of statements and LOBs when a connection is returned to a session pool. #) Added support for binding by value for rowids in :func:`dpiStmt_bindValueByPos()` and :func:`dpiStmt_bindValueByName()`. #) On platforms other than Windows, if the regular method for loading the Oracle Client libraries fails, try using $ORACLE_HOME/lib/libclntsh.so (`issue 20 `__). #) Use the environment variable DPI_DEBUG_LEVEL at runtime, not compile time, to add in :ref:`debugging `. #) Added support for DPI_DEBUG_LEVEL_ERRORS (reports errors and has the value 8) and DPI_DEBUG_LEVEL_SQL (reports prepared SQL statement text and has the value 16) in order to further improve the ability to debug issues. #) Ensure that any prefetch activities are performed prior to performing the fetch in :func:`dpiStmt_scroll()`. #) Provide means of disabling thread cleanup for situations where threads are created at startup and never terminated (such as takes place with Node.js). #) Add script sql/TestEnv.sql and read environment variables during test execution in order to simplify the running of tests. #) Add script sql/SampleEnv.sql and read environment variables during sample execution in order to simplify the running of samples. #) Adjust Makefile for tests and samples (`issue 24 `__). #) Added additional test cases. #) Documentation improvements. Version 2.0.0-rc.2 (July 20, 2017) ---------------------------------- #) Improved error messages when initial OCI environment cannot be created. #) On Windows, convert system message to Unicode first, then to UTF-8; otherwise, the error message returned could be in a mix of encodings. #) Added support for converting from text to number in object attributes and collection element values. #) Added checks on all pointers to ensure they are not NULL. #) Added checks on all pointer/length combinations to ensure that they are not NULL and non-zero at the same time. #) Ensure that the thread specific errors are freed properly. #) Corrected handling of connections using DRCP. #) Corrected issue where error getting a pooled connection was masked by error "DPI-1002: invalid OCI handle". #) PL/SQL boolean values are not supported until Oracle Client 12.1 so raise an unsupported error if an attempt is made to use them in Oracle Client 11.2. #) Allow the parameter numQueryColumns to be null in :func:`dpiStmt_execute()` as a convenience to those who do not require that information. #) Added url fragment and whether a 32-bit or 64-bit library is expected to error "DPI-1047: Oracle Client library cannot be loaded" in order to improve the help provided. #) Added prefix "ODPI: " to start of all debug messages to aid in differentiating between them and other messages in log files. #) Added additional test cases. #) Documentation improvements. Version 2.0.0-rc.1 (June 16, 2017) ---------------------------------- #) OCI requires that both :member:`~dpiCommonCreateParams.encoding` and :member:`~dpiCommonCreateParams.nencoding` have values or that both encoding and encoding do not have values. The missing value is set to its default value if one of the values is set and the other is not (`issue 36 `__). #) Add optimization when client and server character sets are identical; in that case the size in bytes reported by the server is sufficient to hold the data that will be transferred from the server and there is no need to expand the buffer for character strings. #) Corrected handling of BFILE LOBs. #) Eliminated errors and warnings when using AIX compiler. #) Documentation improvements. Version 2.0.0-beta.4 (May 24, 2017) ----------------------------------- #) Added support for getting/setting attributes of objects or element values in collections that contain LOBs, BINARY_FLOAT values, BINARY_DOUBLE values and NCHAR and NVARCHAR2 values. The error message for any types that are not supported has been improved as well. #) Enabled temporary LOB caching in order to avoid disk I/O as `suggested `__. #) Changed default native type to DPI_ORACLE_TYPE_INT64 if the column metadata indicates that the values are able to fit inside a 64-bit integer. #) Added function :func:`dpiStmt_defineValue()`, which gives the application the opportunity to specify the data type to use for fetching without having to create a variable. #) Added constant DPI_DEBUG_LEVEL as a set of bit flags which result in messages being printed to stderr. The following levels are defined: - 0x0001 - reports errors during free operations - 0x0002 - reports on reference count changes - 0x0004 - reports on public function calls #) An empty string is just as acceptable as NULL when enabling external authentication in :func:`dpiPool_create()`. #) Avoid changing the OCI actual length values for fixed length types in order to prevent error "ORA-01458: invalid length inside variable character string". #) Ensured that the length set in the dpiBytes structure by the caller is passed through to the actual length buffer used by OCI. #) Added missing documentation for function :func:`dpiVar_setFromBytes()`. #) Handle edge case when an odd number of zeroes trail the decimal point in a value that is effectively zero (`cx_Oracle issue 22 `__). #) Eliminated resource leak when a standalone connection or pool is freed. #) Prevent attempts from binding the cursor being executed to itself. #) Corrected determination of unique bind variable names. The function :func:`dpiStmt_getBindCount()` returns a count of unique bind variable names for PL/SQL statements only. For SQL statements, this count is the total number of bind variables, including duplicates. The function :func:`dpiStmt_getBindNames()` has been adjusted to return the actual number of unique bind variable names (parameter numBindNames is now a pointer instead of a scalar value). #) Added additional test cases. #) Added check for Cygwin, as `suggested `__. Version 2.0.0-beta.3 (April 18, 2017) ------------------------------------- #) Add initial set of `functional test cases `__. #) Add support for smallint and float data types in Oracle objects, as `requested `__. #) Ensure that the actual array size is set to the number of rows returned in a DML Returning statement. #) Remove unneeded function dpiVar_resize(). #) Improve error message when specifying an invalid array position in a variable. #) Add structure :ref:`dpiVersionInfo` to pass version information, rather than separate parameters. This affects functions :func:`dpiContext_getClientVersion()` and :func:`dpiConn_getServerVersion()`. #) Rename functions that use an index to identify elements in a collection to include "ByIndex" in the name. This is clearer and also allows for functions that may be added in the future that will identify elements by other means. This affects functions :func:`dpiObject_deleteElementByIndex()`, :func:`dpiObject_getElementExistsByIndex()`, :func:`dpiObject_getElementValueByIndex()`, and :func:`dpiObject_setElementValueByIndex()`. #) The OCI function OCITypeByFullName() is supported on a 12.1 Oracle Client but will give the error "OCI-22351: This API is not supported by the ORACLE server" when used against an 11.2 Oracle Database. The function :func:`dpiConn_getObjectType()` now checks the server version and calls the correct routine as needed. #) Add parameter "exists" to functions :func:`dpiObject_getFirstIndex()` and :func:`dpiObject_getLastIndex()` which allow a calling program to avoid error "OCI-22166: collection is empty". Version 2.0.0-beta.2 (March 28, 2017) ------------------------------------- #) Use dynamic loading at runtime to load the OCI library and eliminate the need for the OCI header files to be present when building ODPI-C. #) Improve sample Makefile as requested in `issue 1 `__. #) Correct support for handling unsigned integers that are larger than the maximum size that can be represented by a signed integer. This corrects `issue 3 `__. #) Remove type DPI_ORACLE_TYPE_LONG_NVARCHAR which is not needed as noted in `issue 5 `__. #) Increase size of string which can be generated from an OCI number. This corrects `issue 6 `__. #) Ensure that zeroing the check integer on ODPI-C handles is not optimised away by the compiler. #) Silence compiler warnings from the Microsoft C++ compiler. #) Restore support for simple reference count tracing by the use of DPI_TRACE_REFS. #) Add additional error (ORA-56600: an illegal OCI function call was issued) to the list of errors that cause the session to be dropped from the session pool. #) Changed LOB sample to include code to populate both CLOBs and BLOBs in addition to fetching them. Version 2.0.0-beta.1 (January 30, 2017) --------------------------------------- #) Initial release supporting the following features\: - 11.2, 12.1 and 12.2 Oracle Client support - 9.2 and higher Oracle Database support (depending on Oracle Client version) - SQL and PL/SQL execution - Character datatypes (CHAR, VARCHAR2, NCHAR, NVARCHAR2, CLOB, NCLOB, LONG) - Numeric datatypes (NUMBER, BINARY_FLOAT, BINARY_DOUBLE) - Dates, Timestamps, Intervals - Binary types (BLOB, BFILE, RAW, LONG RAW) - PL/SQL datatypes (PLS_INTEGER, BOOLEAN, Collections, Records) - JSON - User Defined Types - REF CURSOR, Nested cursors, Implicit Result Sets - Array fetch - Array bind/execute - Session pools (homogeneous and non-homogeneous with proxy authentication) - Standalone connections - Database Resident Connection Pooling (DRCP) - External authentication - Statement caching (tagging) - End-to-end tracing, mid-tier authentication and auditing (action, module, client identifier, client info, database operation) - Edition Based Redefinition - Scrollable cursors - DML RETURNING - Privileged connection support (SYSDBA, SYSOPER, SYSASM, PRELIM_AUTH) - Database Startup/Shutdown - Session Tagging - Proxy authentication - Batch Errors - Array DML Row Counts - Query Result Caching - Application Continuity (with some limitations) - Query Metadata - Password Change - Two Phase Commit - OCI Client Version and Server Version - Connection Validation (when acquired from session pool or DRCP) - Continuous Query Notification - Advanced Queuing - Easily extensible (via direct OCI calls) odpi-5.6.4/doc/src/structs/000077500000000000000000000000001510466437300155355ustar00rootroot00000000000000odpi-5.6.4/doc/src/structs/dpiAccessToken.rst000066400000000000000000000023431510466437300211700ustar00rootroot00000000000000.. _dpiAccessToken: ODPI-C Structure dpiAccessToken ------------------------------- This structure is used when creating connection pools and standalone connections using token based authentication. Oracle Client libraries must be 19.14 (or later), or 21.5 (or later). The externalAuth must be set to 1 and in addition, homogeneous must be set to 1 when creating a pool. The user (or username) and password properties should not be set. Both token and privateKey (and their lengths) must be set while using IAM for token based authentication. Only token and it's length must be set while using OAuth for token based authentication. .. member:: const char* dpiAccessToken.token Specifies the database authentication token string used for token based authentication. .. member:: uint32_t dpiAccessToken.tokenLength Specifies the database authentication token string length used for token based authentication. .. member:: const char* dpiAccessToken.privateKey Specifies the database authentication private key string used for token based authentication. .. member:: uint32_t dpiAccessToken.privateKeyLength Specifies the database authentication private key string length used for token based authentication. odpi-5.6.4/doc/src/structs/dpiAnnotation.rst000066400000000000000000000016051510466437300211000ustar00rootroot00000000000000.. _dpiAnnotation: ODPI-C Structure dpiAnnotation ------------------------------ This structure is part of the structure :ref:`dpiDataTypeInfo` and provides information about `annotations `__ associated with columns that are fetched from the database. Annotations are only available with Oracle Database 23ai (or later). Oracle Client libraries must also be 23.1 (or later). .. member:: const char* dpiAnnotation.key Specifies the annoation key. .. member:: uint32_t dpiAnnotation.keyLength Specifies the length of the annotation key, in bytes. .. member:: const char* dpiAnnotation.value Specifies the annoation value. .. member:: uint32_t dpiAnnotation.valueLength Specifies the length of the annotation value, in bytes. odpi-5.6.4/doc/src/structs/dpiAppContext.rst000066400000000000000000000035411510466437300210540ustar00rootroot00000000000000.. _dpiAppContext: ODPI-C Structure dpiAppContext ------------------------------ This structure is used for passing application context to the database during the process of creating standalone connections. These values are ignored when acquiring a connection from a session pool or when using DRCP (Database Resident Connection Pooling). All values must be set to valid values prior to being used in the :ref:`dpiConnCreateParams` structure and must remain valid until the execution of :func:`dpiConn_create()` completes. Values set using this structure are available in logon triggers by using the sys_context() SQL function. .. member:: const char* dpiAppContext.namespaceName Specifies the value of the "namespace" parameter to sys_context(). It is expected to be a byte string in the encoding specified in the :ref:`dpiConnCreateParams` structure and must not be NULL. .. member:: uint32_t dpiAppContext.namespaceNameLength Specifies the length of the :member:`dpiAppContext.namespaceName` member, in bytes. .. member:: const char* dpiAppContext.name Specifies the value of the "parameter" parameter to sys_context(). It is expected to be a byte string in the encoding specified in the :ref:`dpiConnCreateParams` structure and must not be NULL. .. member:: uint32_t dpiAppContext.nameLength Specifies the length of the :member:`dpiAppContext.name` member, in bytes. .. member:: const char* dpiAppContext.value Specifies the value that will be returned from sys_context(). It is expected to be a byte string in the encoding specified in the :ref:`dpiConnCreateParams` structure and must not be NULL. .. member:: uint32_t dpiAppContext.valueLength Specifies the length of the :member:`dpiAppContext.value` member, in bytes. odpi-5.6.4/doc/src/structs/dpiBytes.rst000066400000000000000000000015021510466437300200500ustar00rootroot00000000000000.. _dpiBytes: ODPI-C Structure dpiBytes ------------------------- This structure is used for passing byte strings to and from the database in the structure :ref:`dpiData`. .. member:: char* dpiBytes.ptr Specifies the pointer to the memory allocated by ODPI-C for the variable. For strings, data written to this memory should be in the encoding appropriate to the type of data being transferred. When data is transferred from the database it will be in the correct encoding already. .. member:: uint32_t dpiBytes.length Specifies the length of the byte string, in bytes. .. member:: const char* dpiBytes.encoding Specifies the encoding for character data. This value is populated when data is transferred from the database. It is ignored when data is being transferred to the database. odpi-5.6.4/doc/src/structs/dpiCommonCreateParams.rst000066400000000000000000000101401510466437300225000ustar00rootroot00000000000000.. _dpiCommonCreateParams: ODPI-C Structure dpiCommonCreateParams -------------------------------------- This structure is used for creating session pools and standalone connections to the database. All members are initialized to default values using the :func:`dpiContext_initCommonCreateParams()` function. .. member:: dpiCreateMode dpiCommonCreateParams.createMode Specifies the mode used for creating connections. It is expected to be one or more of the values from the enumeration :ref:`dpiCreateMode`, OR'ed together. The default value is `DPI_MODE_CREATE_DEFAULT`. Note that when this structure is used during creation of a pool, the mode `DPI_MODE_CREATE_THREADED` is automatically enabled regardless of what value is set in this member. .. member:: const char* dpiCommonCreateParams.encoding Specifies the encoding to use for CHAR data, as a null-terminated ASCII string. Either an IANA or Oracle specific character set name is expected. NULL is also acceptable which implies the use of the NLS_LANG environment variable (or ASCII, if the NLS_LANG environment variable is not set). The default value is the value of the member :member:`dpiContextCreateParams.defaultEncoding` specified when the call to :func:`dpiContext_createWithParams()` was made. .. member:: const char* dpiCommonCreateParams.nencoding Specifies the encoding to use for NCHAR data, as a null-terminated ASCII string. Either an IANA or Oracle specific character set name is expected. NULL is also acceptable which implies the use of the NLS_NCHAR environment variable (or the same value as the :member:`dpiCommonCreateParams.encoding` member if the NLS_NCHAR environment variable is not set). The default value is the value of the member :member:`dpiContextCreateParams.defaultEncoding` specified when the call to :func:`dpiContext_createWithParams()` was made. .. member:: const char* dpiCommonCreateParams.edition Specifies the edition to be used when creating a standalone connection. It is expected to be NULL (meaning that no edition is set) or a byte string in the encoding specified by the :member:`dpiCommonCreateParams.encoding` member. The default value is NULL. .. member:: uint32_t dpiCommonCreateParams.editionLength Specifies the length of the :member:`dpiCommonCreateParams.edition` member, in bytes. The default value is 0. .. member:: const char* dpiCommonCreateParams.driverName Specifies the name of the driver that is being used. It is expected to be NULL or a byte string in the encoding specified by the :member:`dpiCommonCreateParams.encoding` member. The default value is the value of the member :member:`dpiContextCreateParams.defaultDriverName` specified when the call to :func:`dpiContext_createWithParams()` was made. .. member:: uint32_t dpiCommonCreateParams.driverNameLength Specifies the length of the :member:`dpiCommonCreateParams.driverName` member, in bytes. The default value is the length of the member :member:`dpiContextCreateParams.defaultDriverName` specified when the call to :func:`dpiContext_createWithParams()` was made. .. member:: int dpiCommonCreateParams.sodaMetadataCache Specifies whether to enable the SODA metadata cache or not, which can significantly improve the performance of repeated calls to methods :func:`dpiSodaDb_createCollection()` (when not specifying a value for the metadata parameter) and :func:`dpiSodaDb_openCollection()`. This requires Oracle Client 21.3 or higher (also available in Oracle Client 19 from 19.11). .. member:: uint32_t dpiCommonCreateParams.stmtCacheSize Specifies the number of statements to retain in the statement cache. Use a value of 0 to disable the statement cache completely. .. member:: dpiAccessToken* dpiCommonCreateParams.accessToken Specifies a pointer to a :ref:`dpiAccessToken` structure. Each member of structure is populated with authentication parameters used for token based authentication. This requires Oracle Client 19.4 (or later), or 21.5 (or later). odpi-5.6.4/doc/src/structs/dpiConnCreateParams.rst000066400000000000000000000176351510466437300221650ustar00rootroot00000000000000.. _dpiConnCreateParams: ODPI-C Structure dpiConnCreateParams ------------------------------------ This structure is used for creating connections to the database, whether standalone or acquired from a session pool. All members are initialized to default values using the :func:`dpiContext_initConnCreateParams()` function. Care should be taken to ensure a copy of this structure exists only as long as needed to create the connection since it can contain a clear text copy of credentials used for connecting to the database. .. member:: dpiAuthMode dpiConnCreateParams.authMode Specifies the mode used for authorizing connections. It is expected to be one or more of the values from the enumeration :ref:`dpiAuthMode`, OR'ed together. The default value is DPI_MODE_AUTH_DEFAULT. .. member:: const char* dpiConnCreateParams.connectionClass Specifies the connection class to use when connecting to the database. This is used with DRCP (database resident connection pooling) or to further subdivide a session pool. It is expected to be NULL (meaning that no connection class will be set) or a byte string in the encoding used for CHAR data. The default value is NULL. .. member:: uint32_t dpiConnCreateParams.connectionClassLength Specifies the length of the :member:`dpiConnCreateParams.connectionClass` member, in bytes. The default value is 0. .. member:: dpiPurity dpiConnCreateParams.purity Specifies the level of purity required when creating a connection using a connection class. It is expected to be one of the values from the enumeration :ref:`dpiPurity`. The default value is DPI_PURITY_DEFAULT. .. member:: const char* dpiConnCreateParams.newPassword Specifies the new password to set when creating a connection. This value is only used when creating a standalone connection. It is expected to be NULL or a byte string in the encoding used for CHAR data. The default value of this member is NULL. If specified, the password for the user is changed when the connection is created (useful when the password has expired and a session cannot be established without changing the password). .. member:: uint32_t dpiConnCreateParams.newPasswordLength Specifies the length of the :member:`dpiConnCreateParams.newPassword` member, in bytes. The default value is 0. .. member:: dpiAppContext* dpiConnCreateParams.appContext Specifies the application context that will be set when the connection is created. This value is only used when creating standalone connections. It is expected to be NULL or an array of :ref:`dpiAppContext` structures. The context specified here can be used in logon triggers, for example. The default value is NULL. .. member:: uint32_t dpiConnCreateParams.numAppContext Specifies the number of elements found in the :member:`dpiConnCreateParams.appContext` member. The default value is 0. .. member:: int dpiConnCreateParams.externalAuth Specifies whether external authentication should be used to create the connection. If this value is 0, the user name and password values must be specified in the call to :func:`dpiConn_create()`; otherwise, the user name and password values must be zero length or NULL. The default value is 0. .. member:: void* dpiConnCreateParams.externalHandle Specifies an OCI service context handle created externally that will be used instead of creating a connection from scratch. The default value is NULL. Note that this connection depends on the external handle remaining valid for the lifetime of this connection. It is also important to ensure that the last reference to this connection is released before the external service context handle and environment handle are destroyed. Unlike regular connections, no attempt is made to rollback any outstanding transactions or close any open statements, objects and LOBs when the last reference to this connection is released, since attempts to do so after the external service context handle and environment are destroyed may result in crashes and other undesirable behavior. .. member:: dpiPool* dpiConnCreateParams.pool Specifies the session pool from which to acquire a connection or NULL if a standalone connection should be created. The default value is NULL. If the method :func:`dpiPool_acquireConnection()` is being called, this value is ignored. .. member:: const char* dpiConnCreateParams.tag Specifies the tag to use when acquiring a connection from a session pool. This member is ignored when creating a standalone connection. If specified, the tag restricts the type of session that can be returned to those with that tag or a NULL tag. If the member :member:`dpiConnCreateParams.matchAnyTag` is set, however, any session can be returned if no matching sessions are found. The value is expected to be NULL (any session can be returned) or a byte string in the encoding used for CHAR data. The default value is NULL. If specified, the value should be one or more properties (specified in the form `key=value`) separated by semicolons. .. member:: uint32_t dpiConnCreateParams.tagLength Specifies the length of the :member:`dpiConnCreateParams.tag` member, in bytes. The default value is 0. .. member:: int dpiConnCreateParams.matchAnyTag Specifies whether any tagged session should be accepted when acquiring a connection from a session pool, if no connection using the tag specified in the :member:`dpiConnCreateParams.tag` is available. This value is only used when acquiring a connection from a session pool. The default value is 0. .. member:: const char* dpiConnCreateParams.outTag Specifies the tag of the connection that was acquired from a session pool, or NULL if the session was not tagged. This member is left untouched when creating a standalone connection and is filled in only if the connection acquired from the session pool was tagged. If filled in, it is a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiConnCreateParams.outTagLength Specifies the length of the :member:`dpiConnCreateParams.outTag` member, in bytes. .. member:: int dpiConnCreateParams.outTagFound Specifies if the connection created used the tag specified by the :member:`dpiConnCreateParams.tag` member. It is only filled in if the connection was acquired from a session pool and a tag was initially specified. .. member:: dpiShardingKeyColumn* dpiConnCreateParams.shardingKeyColumns Specifies an array of :ref:`dpiShardingKeyColumn` structures which are used to identify which database shard should be connected to. The number of elements in the array is assumed to contain at least :member:`dpiConnCreateParams.numShardingKeyColumns` elements. .. member:: uint8_t dpiConnCreateParams.numShardingKeyColumns Specifies the number of elements in the array of sharding key columns found in the member :member:`dpiConnCreateParams.shardingKeyColumns`. .. member:: dpiShardingKeyColumn* dpiConnCreateParams.superShardingKeyColumns Specifies an array of :ref:`dpiShardingKeyColumn` structures which are used to identify which database shard should be connected to. The number of elements in the array is assumed to contain at least :member:`dpiConnCreateParams.numSuperShardingKeyColumns` elements. .. member:: uint8_t dpiConnCreateParams.numSuperShardingKeyColumns Specifies the number of elements in the array of sharding key columns found in the member :member:`dpiConnCreateParams.superShardingKeyColumns`. .. member:: int dpiConnCreateParams.outNewSession Specifies if the connection created was newly created by the session pool and has never been acquired from the pool (1) or not (0). It is only filled in if the connection was acquired from a session pool. odpi-5.6.4/doc/src/structs/dpiConnInfo.rst000066400000000000000000000060401510466437300204750ustar00rootroot00000000000000.. _dpiConnInfo: ODPI-C Structure dpiConnInfo ---------------------------- This structure is used for passing information about a connection from ODPI-C. It is used by the function :func:`dpiConn_getInfo()`. .. member:: const char* dpiConnInfo.dbDomain A pointer to the name of the Oracle Database Domain name associated with the connection, encoded in the encoding used for CHAR data. This is the same value returned by the SQL expression ``SELECT VALUE FROM V$PARAMETER WHERE NAME = 'db_domain'``. .. member:: uint32_t dpiConnInfo.dbDomainLength Contains the length of the :member:`dpiConnInfo.dbDomain` member, in bytes. .. member:: const char* dpiConnInfo.dbName A pointer to the Oracle Database name associated with the connection, encoded in the encoding used for CHAR data. This is the same value returned by the SQL expression ``SELECT NAME FROM V$DATABASE``. Note the values may have different cases. .. member:: uint32_t dpiConnInfo.dbNameLength Contains the length of the :member:`dpiConnInfo.dbName` member, in bytes. .. member:: const char* dpiConnInfo.instanceName A pointer to the Oracle Database instance name associated with the connection, encoded in the encoding used for CHAR data. This is the same value returned by the SQL expression ``SELECT SYS_CONTEXT('USERENV', 'INSTANCE_NAME') FROM DUAL``. Note the values may have different cases. .. member:: uint32_t dpiConnInfo.instanceNameLength Contains the length of the :member:`dpiConnInfo.instanceName` member, in bytes. .. member:: const char* dpiConnInfo.serviceName A pointer to the Oracle Database service name associated with the connection, encoded in the encoding used for CHAR data. This is the same value returned by the SQL expression ``SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') FROM DUAL``. .. member:: uint32_t dpiConnInfo.serviceNameLength Contains the length of the :member:`dpiConnInfo.serviceName` member, in bytes. .. member:: uint32_t dpiConnInfo.maxIdentifierLength Specifies the maximum length of identifiers (in bytes) supported by the database to which the connection has been established. See `Database Object Naming Rules `__. The value may be 0, 30, or 128. The value 0 indicates the size cannot be reliably determined by ODPI-C, which occurs when using Oracle Client libraries 12.1 (or older) and also connected to Oracle Database 12.2, or later. .. member:: uint32_t dpiConnInfo.maxOpenCursors Specifies the maximum number of cursors that can be opened. This is the same value returned by the SQL expression ``SELECT VALUE FROM V$PARAMETER WHERE NAME = 'open_cursors'``. The value will be 0 when using Oracle Client libraries 11.2. .. member:: uint8_t dpiConnInfo.serverType Specifies the type of server process used by the connection. This value will be one of the values in the enumeration :ref:`dpiServerType `. odpi-5.6.4/doc/src/structs/dpiContextCreateParams.rst000066400000000000000000000071461510466437300227100ustar00rootroot00000000000000.. _dpiContextCreateParams: ODPI-C Structure dpiContextCreateParams --------------------------------------- This structure is used for specifying parameters when creating an ODPI-C context by calling :func:`dpiContext_createWithParams()`. .. member:: const char* dpiContextCreateParams.defaultDriverName A null-terminated string defining the default driver name to use when creating pools or standalone connections. The standard is to set this value to ``" : "``, where is the name of the driver and is its version. There should be a single space character before and after the colon. This value is shown in database views that give information about connections. For example, it is in the ``CLIENT_DRIVER`` column of ``V$SESSION_CONNECT_INFO``. If this member is NULL, then the default value will be the value of ``DPI_DEFAULT_DRIVER_NAME`` from `dpi.h `__. This member is propagated to the :member:`dpiCommonCreateParams.driverName` and :member:`dpiCommonCreateParams.driverNameLength` members when the function :func:`dpiContext_initCommonCreateParams()` is called. .. member:: const char* dpiContextCreateParams.defaultEncoding A null-terminated string defining the default encoding to use for all string data (including NCHAR, NVARCHAR2 and NCLOB data) passed into or returned from the database. If this member is NULL, then the default value will be "UTF-8". The Oracle equivalent of this is "AL32UTF8". This member is propagated to the :member:`dpiCommonCreateParams.encoding` and :member:`dpiCommonCreateParams.nencoding` members when the function :func:`dpiContext_initCommonCreateParams()` is called. .. member:: const char* dpiContextCreateParams.loadErrorUrl A null-terminated UTF-8 encoded string defining the URL that should be provided in the error message returned when the Oracle Client library cannot be loaded. This URL should direct the user to the installation instructions for the application or driver using ODPI-C. If this value is NULL then the default ODPI-C URL is provided in the error message instead. .. member:: const char* dpiContextCreateParams.oracleClientLibDir A null-terminated UTF-8 encoded string defining the location from which to load the Oracle Client library. If this value is not NULL it is the only location that is searched; otherwise, if this value is NULL the Oracle Client library is searched for in the usual fashion as noted in :ref:`Oracle Client Library Loading `. Also see that section for limitations on using this member. .. member:: const char* dpiContextCreateParams.oracleClientConfigDir A null-terminated UTF-8 encoded string defining the location the Oracle client library will search for configuration files. This is equivalent to setting the environment variable ``TNS_ADMIN``. If this value is not NULL, it overrides any value set by the environment variable ``TNS_ADMIN``. .. member:: int dpiContextCreateParams.sodaUseJsonDesc A boolean value indicating whether or not to use JSON descriptors with SODA. This requires Oracle Client 23.4 or higher and setting this value to 1 in earlier versions will simply be ignored. Once a call to :func:`dpiContext_createWithParams()` is made with this structure, this member will be cleared if JSON descriptors cannot be used. .. member:: int dpiContextCreateParams.useJsonId A boolean value indicating whether or not to treat JSON ID values distinctly from other binary data. odpi-5.6.4/doc/src/structs/dpiData.rst000066400000000000000000000026571510466437300176470ustar00rootroot00000000000000.. _dpiData: ODPI-C Structure dpiData ------------------------ This structure is used for passing data to and from the database in variables and for getting and setting object attributes and collection values. The data that is stored in the structure will remain valid for differing durations depending on the source of the data. For data that is supplied by the application (for passing data into the database) the duration of the data is under the control of the application itself and the application should ensure that it remains valid for as long as any call that uses that data. For data that is supplied by the database in a variable (either fetching data or binding data out) the data will remain valid as long as a reference to the variable is retained; the contents of the data may change however if a statement to which the variable is bound or defined is executed or fetched again. For data that is acquired from an object attribute or a collection element the data will remain valid as long as a reference to the object is retained; the contents of the data may change however if the object is modified. .. member:: int dpiData.isNull Specifies if the value refers to a null value (1) or not (0). .. member:: dpiDataBuffer dpiData.value Specifies the value that is being passed or received. It is only examined when the member :member:`dpiData.isNull` is 0. It is a union of type :ref:`dpiDataBuffer`. odpi-5.6.4/doc/src/structs/dpiDataTypeInfo.rst000066400000000000000000000127431510466437300213220ustar00rootroot00000000000000.. _dpiDataTypeInfo: ODPI-C Structure dpiDataTypeInfo -------------------------------- This structure is used for passing data type information from ODPI-C. It is part of the structures :ref:`dpiObjectAttrInfo`, :ref:`dpiObjectTypeInfo` and :ref:`dpiQueryInfo`. .. member:: dpiOracleTypeNum dpiDataTypeInfo.oracleTypeNum Specifies the type of the data. It will be one of the values from the enumeration :ref:`dpiOracleTypeNum`, or 0 if the type is not supported by ODPI-C. .. member:: dpiNativeTypeNum dpiDataTypeInfo.defaultNativeTypeNum Specifies the default native type for the data. It will be one of the values from the enumeration :ref:`dpiNativeTypeNum`, or 0 if the type is not supported by ODPI-C. .. member:: uint16_t dpiDataTypeInfo.ociTypeCode Specifies the OCI type code for the data, which can be useful if the type is not supported by ODPI-C. .. member:: uint32_t dpiDataTypeInfo.dbSizeInBytes Specifies the size in bytes (from the database's perspective) of the data. This value is only populated for strings and binary data. For all other data the value is zero. .. member:: uint32_t dpiDataTypeInfo.clientSizeInBytes Specifies the size in bytes (from the client's perspective) of the data. This value is only populated for strings and binary data. For all other data the value is zero. .. member:: uint32_t dpiDataTypeInfo.sizeInChars Specifies the size in characters of the data. This value is only populated for string data. For all other data the value is zero. .. member:: int16_t dpiDataTypeInfo.precision Specifies the precision of the data. This value is only populated for numeric and interval data. For all other data the value is zero. .. member:: int8_t dpiDataTypeInfo.scale Specifies the scale of the data. This value is only populated for numeric data. For all other data the value is zero. .. member:: uint8_t dpiDataTypeInfo.fsPrecision Specifies the fractional seconds precision of the data. This value is only populated for timestamp and interval day to second data. For all other data the value is zero. .. member:: dpiObjectType* dpiDataTypeInfo.objectType Specifies a reference to the type of the object. This value is only populated for named type data. For all other data the value is NULL. This reference is owned by the object attribute, object type or statement and a call to :func:`dpiObjectType_addRef()` must be made if the reference is going to be used beyond the lifetime of the owning object. .. member:: int dpiDataTypeInfo.isJson Specifies if the data contains JSON. This is set to true when columns are fetched that are of type ``DPI_ORACLE_TYPE_JSON`` or if the column fetched has the check constraint "IS JSON" enabled. .. member:: const char* dpiDataTypeInfo.domainSchema Specifies the schema of the `SQL domain `__ associated with the column which is being queried, as a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiDataTypeInfo.domainSchemaLength Specifies the length of the :member:`dpiDataTypeInfo.domainSchema` member, in bytes. .. member:: const char* dpiDataTypeInfo.domainName Specifies the name of the `SQL domain `__ associated with the column which is being queried, as a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiDataTypeInfo.domainNameLength Specifies the length of the :member:`dpiDataTypeInfo.domainName` member, in bytes. .. member:: uint32_t dpiDataTypeInfo.numAnnotations Specifies the number of annotations associated with the column which is being fetched. It is the length of :member:`dpiDataTypeInfo.annotations`. .. member:: dpiAnnotation* dpiDataTypeInfo.annotations Specifies an array of structures of type :ref:`dpiAnnotation`. The length of the array is specified in the :member:`dpiDataTypeInfo.numAnnotations` member. .. member:: int dpiDataTypeInfo.isOson Specifies if the data contains binary encoded OSON. This is set to true when columns are fetched that have the check constraint "IS JSON FORMAT OSON" enabled. .. member:: uint32_t dpiDataTypeInfo.vectorDimensions Specifies the number of dimensions that a vector column contains. This value will be 0 if :member:`~dpiDataTypeInfo.oracleTypeNum` is not DPI_ORACLE_TYPE_VECTOR or the vector columns uses a flexible number of dimensions. .. member:: uint8_t dpiDataTypeInfo.vectorFormat Specifies the storage format of the vector column. This value will be 0 if :member:`~dpiDataTypeInfo.oracleTypeNum` is not DPI_ORACLE_TYPE_VECTOR or the vector column uses a flexible storage format. If a value is set it will be one of the values in the eneumeration :ref:`dpiVectorFormat`. .. member:: uint8_t dpiDataTypeInfo.vectorFlags Specifies flags for the vector column. This value will be 0 if :member:`~dpiDataTypeInfo.oracleTypeNum` is not DPI_ORACLE_TYPE_VECTOR or no flags have been set. If flags have been set, they will be one or more of the values in the enumeration :ref:`dpiVectorFlags`, or'ed together. odpi-5.6.4/doc/src/structs/dpiEncodingInfo.rst000066400000000000000000000026071510466437300213330ustar00rootroot00000000000000.. _dpiEncodingInfo: ODPI-C Structure dpiEncodingInfo -------------------------------- This structure is used for transferring encoding information from ODPI-C. All of the information here remains valid as long as a reference is held to the standalone connection (by calling :func:`dpiConn_getEncodingInfo()`) or session pool (by calling :func:`dpiPool_getEncodingInfo()`) from which the information was taken. .. member:: const char* dpiEncodingInfo.encoding The encoding used for CHAR data, as a null-terminated ASCII string. .. member:: int32_t dpiEncodingInfo.maxBytesPerCharacter The maximum number of bytes required for each character in the encoding used for CHAR data. This value is used when calculating the size of buffers required when lengths in characters are provided. .. member:: const char* dpiEncodingInfo.nencoding The encoding used for NCHAR data, as a null-terminated ASCII string. .. member:: int32_t dpiEncodingInfo.nmaxBytesPerCharacter The maximum number of bytes required for each character in the encoding used for NCHAR data. Since this information is not directly available from Oracle it is only accurate if the encodings used for CHAR and NCHAR data are identical or one of ASCII or UTF-8; otherwise a value of 4 is assumed. This value is used when calculating the size of buffers required when lengths in characters are provided. odpi-5.6.4/doc/src/structs/dpiErrorInfo.rst000066400000000000000000000046451510466437300207020ustar00rootroot00000000000000.. _dpiErrorInfo: ODPI-C Structure dpiErrorInfo ----------------------------- This structure is used for transferring error information from ODPI-C. All of the strings referenced here may become invalid as soon as the next ODPI-C call is made. .. member:: int32_t dpiErrorInfo.code The OCI error code if an OCI error has taken place. If no OCI error has taken place the value is 0. .. member:: uint16_t dpiErrorInfo.offset16 The 16-bit value of :member:`~dpiErrorInfo.offset` retained for backwards compatibility. This member will be removed at some point in the future. .. member:: const char* dpiErrorInfo.message The error message as a byte string in the encoding specified by the :member:`dpiErrorInfo.encoding` member. .. member:: uint32_t dpiErrorInfo.messageLength The length of the :member:`dpiErrorInfo.message` member, in bytes. .. member:: const char* dpiErrorInfo.encoding The encoding in which the error message is encoded as a null-terminated string. For OCI errors this is the CHAR encoding used when the connection was created. For ODPI-C specific errors this is UTF-8. .. member:: const char* dpiErrorInfo.fnName The public ODPI-C function name which was called in which the error took place. This is a null-terminated ASCII string. .. member:: const char* dpiErrorInfo.action The internal action that was being performed when the error took place. This is a null-terminated ASCII string. .. member:: const char* dpiErrorInfo.sqlState The SQLSTATE code associated with the error. This is a 5 character null-terminated string. .. member:: int dpiErrorInfo.isRecoverable A boolean value indicating if the error is recoverable. This member always has a value of 0 unless both client and server are at release 12.1 or higher. .. member:: int dpiErrorInfo.isWarning A boolean value indicating if the error information is for a warning returned by Oracle that does not prevent the requested operation from proceeding. Examples include connecting to the database with a password that is about to expire (within the grace period) and creating a stored procedure with compilation errors. .. member:: uint32_t dpiErrorInfo.offset The parse error offset (in bytes) when executing a statement or the row offset when performing bulk operations or fetching batch error information. If neither of these cases are true, the value is 0. odpi-5.6.4/doc/src/structs/dpiIntervalDS.rst000066400000000000000000000013251510466437300210000ustar00rootroot00000000000000.. _dpiIntervalDS: ODPI-C Structure dpiIntervalDS ------------------------------ This structure is used for passing interval (days to seconds) data to and from the database in the structure :ref:`dpiData`. .. member:: int32_t dpiIntervalDS.days Specifies the number of days in the interval. .. member:: int32_t dpiIntervalDS.hours Specifies the number of hours in the interval. .. member:: int32_t dpiIntervalDS.minutes Specifies the number of minutes in the interval. .. member:: int32_t dpiIntervalDS.seconds Specifies the number of seconds in the interval. .. member:: int32_t dpiIntervalDS.fseconds Specifies the number of fractional seconds in the interval (in nanoseconds). odpi-5.6.4/doc/src/structs/dpiIntervalYM.rst000066400000000000000000000006251510466437300210210ustar00rootroot00000000000000.. _dpiIntervalYM: ODPI-C Structure dpiIntervalYM ------------------------------ This structure is used for passing interval (years to months) data to and from the database in the structure :ref:`dpiData`. .. member:: int32_t dpiIntervalYM.years Specifies the number of years in the interval. .. member:: int32_t dpiIntervalYM.months Specifies the number of months in the interval. odpi-5.6.4/doc/src/structs/dpiJsonArray.rst000066400000000000000000000016511510466437300206770ustar00rootroot00000000000000.. _dpiJsonArray: ODPI-C Structure dpiJsonArray ----------------------------- This structure is used for passing JSON objects to and from the database. .. member:: uint32_t dpiJsonArray.numElements Specifies the number of elements that are found in the JSON array. This also identifies the number of elements in each of the remaining arrays. .. member:: dpiJsonNode* dpiJsonArray.elements Specifies an array of JSON nodes that are the values of the elements found in the JSON array. Each of these is a structure of type :ref:`dpiJsonNode`. .. member:: dpiDataBuffer* dpiJsonArray.elementValues Specifies an array of buffers that contain the data for the values of the elements found in the JSON array. This member should not be used directly. Instead, the :member:`dpiJsonNode.value` member of the corresponding node in the member :member:`~dpiJsonArray.elements` should be used. odpi-5.6.4/doc/src/structs/dpiJsonNode.rst000066400000000000000000000014761510466437300205130ustar00rootroot00000000000000.. _dpiJsonNode: ODPI-C Structure dpiJsonNode ---------------------------- This structure is used for passing JSON node data to and from the database in the structure :ref:`dpiData`. Nodes can consist of scalar values, objects, or arrays. .. member:: dpiOracleTypeNum dpiJsonNode.oracleTypeNum The Oracle type of the data that is stored in the node. It will be one of the values from the enumeration :ref:`dpiOracleTypeNum`. .. member:: dpiNativeTypeNum dpiJsonNode.nativeTypeNum The native type of the data that is stored in the node. It will be one of the values from the enumeration :ref:`dpiNativeTypeNum`. .. member:: dpiDataBuffer* dpiJsonNode.value The value that is stored in the node. It is a union of type :ref:`dpiDataBuffer`. odpi-5.6.4/doc/src/structs/dpiJsonObject.rst000066400000000000000000000025101510466437300210220ustar00rootroot00000000000000.. _dpiJsonObject: ODPI-C Structure dpiJsonObject ------------------------------ This structure is used for passing JSON objects to and from the database. .. member:: uint32_t dpiJsonObject.numFields Specifies the number of fields that are found in the JSON object. This also identifies the number of elements in each of the remaining arrays. .. member:: char** dpiJsonObject.fieldNames Specifies an array of field names that are found in the JSON object. Each element is a byte string encoded in UTF-8. The length of each byte string is found in the :member:`~dpiJsonObject.fieldNameLengths` member. .. member:: uint32_t* dpiJsonObject.fieldNameLengths Specifies an array of lengths for the names of the fields found in the JSON object. .. member:: dpiJsonNode* dpiJsonObject.fields Specifies an array of JSON nodes that are the values of the fields found in the JSON object. Each of these is a structure of type :ref:`dpiJsonNode`. .. member:: dpiDataBuffer* dpiJsonObject.fieldValues Specifies an array of buffers that contain the data for the values of the fields found in the JSON object. This member should not be used directly. Instead, the :member:`dpiJsonNode.value` member of the corresponding node in the member :member:`~dpiJsonObject.fields` should be used. odpi-5.6.4/doc/src/structs/dpiMsgRecipient.rst000066400000000000000000000024531510466437300213610ustar00rootroot00000000000000.. _dpiMsgRecipient: ODPI-C Structure dpiMsgRecipient -------------------------------- This structure is used to set recipients for an AQ message. A list of recipient names can be associated with a message at the time a message is enqueued. This allows a limited set of recipients to dequeue each message. The recipient list associated with the message overrides the queue subscriber list, if there is one. The recipient names need not be in the subscriber list but can be, if desired. To dequeue a message, the consumername attribute can be set to one of the recipient names. The original message recipient list is not available on dequeued messages. All recipients have to dequeue a message before it gets removed from the queue. Subscribing to a queue is like subscribing to a magazine: each subscriber can dequeue all the messages placed into a specific queue, just as each magazine subscriber has access to all its articles. Being a recipient, however, is like getting a letter: each recipient is a designated target of a particular message. .. member:: const char* dpiMsgRecipient.name Specifies the name of the message recipient, in the encoding used for CHAR data. .. member:: uint32_t dpiMsgRecipient.nameLength Specifies the length of the :member:`dpiMsgRecipient.name` member, in bytes. odpi-5.6.4/doc/src/structs/dpiObjectAttrInfo.rst000066400000000000000000000012731510466437300216440ustar00rootroot00000000000000.. _dpiObjectAttrInfo: ODPI-C Structure dpiObjectAttrInfo ---------------------------------- This structure is used for passing information about an object type from ODPI-C. It is used by the function :func:`dpiObjectAttr_getInfo()`. .. member:: const char* dpiObjectAttrInfo.name Specifies the name of the attribute, as a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiObjectAttrInfo.nameLength Specifies the length of the :member:`dpiObjectAttrInfo.name` member, in bytes. .. member:: dpiDataTypeInfo dpiObjectAttrInfo.typeInfo Specifies the type of data of the attribute. It is a structure of type :ref:`dpiDataTypeInfo`. odpi-5.6.4/doc/src/structs/dpiObjectTypeInfo.rst000066400000000000000000000032631510466437300216540ustar00rootroot00000000000000.. _dpiObjectTypeInfo: ODPI-C Structure dpiObjectTypeInfo ---------------------------------- This structure is used for passing information about an object type from ODPI-C. It is used by the function :func:`dpiObjectType_getInfo()`. .. member:: const char* dpiObjectTypeInfo.schema Specifies the schema which owns the object type, as a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiObjectTypeInfo.schemaLength Specifies the length of the :member:`dpiObjectTypeInfo.schema` member, in bytes. .. member:: const char* dpiObjectTypeInfo.name Specifies the name of the object type, as a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiObjectTypeInfo.nameLength Specifies the length of the :member:`dpiObjectTypeInfo.name` member, in bytes. .. member:: int dpiObjectTypeInfo.isCollection Specifies if the object type is a collection (1) or not (0). .. member:: dpiDataTypeInfo dpiObjectTypeInfo.elementTypeInfo Specifies the type of data of the elements in the collection. It is a structure of type :ref:`dpiDataTypeInfo` which is only valid if the object type is a collection. .. member:: uint16_t dpiObjectTypeInfo.numAttributes Specifies the number of attributes that the object type has. .. member:: const char* dpiObjectTypeInfo.packageName Specifies the name of the name of the package for a PL/SQL type, as a byte string in the encoding used for CHAR data. If the type is not a PL/SQL type, this value is NULL. .. member:: uint32_t dpiObjectTypeInfo.packageNameLength Specifies the length of the :member:`dpiObjectTypeInfo.packageName` member, in bytes. odpi-5.6.4/doc/src/structs/dpiPoolCreateParams.rst000066400000000000000000000177161510466437300222010ustar00rootroot00000000000000.. _dpiPoolCreateParams: ODPI-C Structure dpiPoolCreateParams ------------------------------------ This structure is used for creating session pools, which can in turn be used to create connections that are acquired from that session pool. All members are initialized to default values using the :func:`dpiContext_initPoolCreateParams()` function. .. member:: uint32_t dpiPoolCreateParams.minSessions Specifies the minimum number of sessions to be created by the session pool. This value is ignored if the :member:`dpiPoolCreateParams.homogeneous` member has a value of 0. The default value is 1. .. member:: uint32_t dpiPoolCreateParams.maxSessions Specifies the maximum number of sessions that can be created by the session pool. Values of 1 and higher are acceptable. The default value is 1. .. member:: uint32_t dpiPoolCreateParams.sessionIncrement Specifies the number of sessions that will be created by the session pool when more sessions are required and the number of sessions is less than the maximum allowed. This value is ignored if the :member:`dpiPoolCreateParams.homogeneous` member has a value of 0. This value added to the :member:`dpiPoolCreateParams.minSessions` member value must not exceed the :member:`dpiPoolCreateParams.maxSessions` member value. The default value is 0. .. member:: int dpiPoolCreateParams.pingInterval Specifies the number of seconds since a connection has last been used before a ping will be performed to verify that the connection is still valid. A negative value disables this check. The default value is 60. .. member:: int dpiPoolCreateParams.pingTimeout Specifies the number of milliseconds to wait when performing a ping to verify the connection is still valid before the connection is considered invalid and is dropped. The default value is 5000 (5 seconds). .. member:: int dpiPoolCreateParams.homogeneous Specifies whether the pool is homogeneous or not. In a homogeneous pool all connections use the same credentials whereas in a heterogeneous pool other credentials are permitted. The default value is 1. .. member:: int dpiPoolCreateParams.externalAuth Specifies whether external authentication should be used to create the sessions in the pool. If this value is 0, the user name and password values must be specified in the call to :func:`dpiPool_create()`; otherwise, the user name and password values must be zero length or NULL. The default value is 0. External authentication cannot be used with homogeneous pools. .. member:: dpiPoolGetMode dpiPoolCreateParams.getMode Specifies the mode to use when sessions are acquired from the pool. It is expected to be one of the values from the enumeration :ref:`dpiPoolGetMode`. The default value is DPI_MODE_POOL_GET_NOWAIT. This value can be set after the pool has been created using the function :func:`dpiPool_setGetMode()` and acquired using the function :func:`dpiPool_getGetMode()`. .. member:: const char* dpiPoolCreateParams.outPoolName This member is populated upon successful creation of a pool using the function :func:`dpiPool_create()`. It is a byte string in the encoding used for CHAR data. Any value specified prior to creating the session pool is ignored. .. member:: uint32_t dpiPoolCreateParams.outPoolNameLength This member is populated upon successful creation of a pool using the function :func:`dpiPool_create()`. It is the length of the :member:`dpiPoolCreateParams.outPoolName` member, in bytes. Any value specified prior to creating the session pool is ignored. .. member:: uint32_t dpiPoolCreateParams.timeout Specifies the length of time (in seconds) after which idle sessions in the pool are terminated. Note that termination only occurs when the pool is accessed. The default value is 0 which means that no idle sessions are terminated. This value can be set after the pool has been created using the function :func:`dpiPool_setTimeout()` and acquired using the function :func:`dpiPool_getTimeout()`. .. member:: uint32_t dpiPoolCreateParams.waitTimeout Specifies the length of time (in milliseconds) that the caller should wait for a session to become available in the pool before returning with an error. This value is only used if the :member:`dpiPoolCreateParams.getMode` member is set to the value DPI_MODE_POOL_GET_TIMEDWAIT. The default value is 0. This value can be set after the pool has been created using the function :func:`dpiPool_setWaitTimeout()` and acquired using the function :func:`dpiPool_getWaitTimeout()`. .. member:: uint32_t dpiPoolCreateParams.maxLifetimeSession Specifies the maximum length of time (in seconds) a pooled session may exist. Sessions in use will not be closed. They become candidates for termination only when they are released back to the pool and have existed for longer than maxLifetimeSession seconds. Session termination only occurs when the pool is accessed. The default value is 0 which means that there is no maximum length of time that a pooled session may exist. This value can be set after the pool has been created using the function :func:`dpiPool_setMaxLifetimeSession()` and acquired using the function :func:`dpiPool_getMaxLifetimeSession()`. .. member:: const char* dpiPoolCreateParams.plsqlFixupCallback Specifies the name of a PL/SQL procedure in the format *schema.package.callback_proc* which will be called when a session is checked out from the pool and the requested tag doesn't match the actual tag assigned to the session. The procedure accepts the desired and actual tags as parameters and it is the responsibility of the procedure to ensure that the session matches the desired state upon completion. See the `OCI documentation `__ for more information. The value is expected to be a byte string in the encoding used for CHAR data. This functionality is only available when Oracle Client is at version 12.2 and higher. .. member:: uint32_t dpiPoolCreateParams.plsqlFixupCallbackLength Specifies the length of the PL/SQL fixup callback, in bytes. .. member:: uint32_t dpiPoolCreateParams.maxSessionsPerShard Specifies the maximum number of sessions that can be created by the session pool for each shard in a sharded database. Set this attribute to a value other than zero to ensure that the pool is balanced towards each shard. A value of zero will not set any maximum number of sessions for each shard. If the Oracle client library version is less than 18.3, this value is ignored. .. member:: dpiAccessTokenCallback dpiPoolCreateParams.accessTokenCallback The callback function which will get called by the connection pool if the pool needs to expand and create new connections but the current authentication token has expired. The function should get a new authentication token and then set :member:`dpiAccessToken.token` and :member:`dpiAccessToken.privateKey` in the accessToken argument. The authentication token can be generated by invoking the Oracle Cloud Infrastructure (OCI) Command Line Interface (CLI). The function should return DPI_SUCCESS for success and DPI_FAILURE for failure. Returning DPI_FAILURE will cause the connection to fail and return ORA-01017 to the application. The callback accepts the following arguments: **context** -- the value of the :member:`dpiPoolCreateParams.accessTokenCallbackContext` member. **accessToken** -- a pointer to the structure :ref:`dpiAccessToken`. .. member:: void* dpiPoolCreateParams.accessTokenCallbackContext Specifies the value that will be used as the first argument to the callback specified in the :member:`dpiPoolCreateParams.accessTokenCallback` member. The default value is NULL. odpi-5.6.4/doc/src/structs/dpiQueryInfo.rst000066400000000000000000000016461510466437300207140ustar00rootroot00000000000000.. _dpiQueryInfo: ODPI-C Structure dpiQueryInfo ----------------------------- This structure is used for passing query metadata from ODPI-C. It is populated by the function :func:`dpiStmt_getQueryInfo()`. All values remain valid as long as a reference is held to the statement and the statement is not re-executed or closed. .. member:: const char* dpiQueryInfo.name Specifies the name of the column which is being queried, as a byte string in the encoding used for CHAR data. .. member:: uint32_t dpiQueryInfo.nameLength Specifies the length of the :member:`dpiQueryInfo.name` member, in bytes. .. member:: dpiDataTypeInfo dpiQueryInfo.typeInfo Specifies the type of data of the column that is being queried. It is a structure of type :ref:`dpiDataTypeInfo`. .. member:: int dpiQueryInfo.nullOk Specifies if the data that is being queried may return null values (1) or not (0). odpi-5.6.4/doc/src/structs/dpiSessionlessTransactionId.rst000066400000000000000000000012561510466437300237650ustar00rootroot00000000000000.. _dpiSessionlessTransactionId: ODPI-C Structure dpiSessionlessTransactionId -------------------------------------------- This structure is used for identifying a sessionless transaction. It is used by the functions :func:`dpiConn_beginSessionlessTransaction()`, :func:`dpiConn_resumeSessionlessTransaction()`, and :func:`suspendSessionlessTransaction()`. .. member:: const char* dpiSessionlessTransactionId.value Specifies the value of the identifier for the sessionless transaction. This value may be up to 64 bytes. .. member:: uint32_t dpiSessionlessTransactionId.length Specifies the length of the :data:`dpiSessionlessTransactionId.value` member, in bytes. odpi-5.6.4/doc/src/structs/dpiShardingKeyColumn.rst000066400000000000000000000023171510466437300223550ustar00rootroot00000000000000.. _dpiShardingKeyColumn: ODPI-C Structure dpiShardingKeyColumn ------------------------------------- This structure is used for passing sharding key column values to the database. It is part of the structure :ref:`dpiConnCreateParams`. .. member:: dpiOracleTypeNum dpiShardingKeyColumn.oracleTypeNum Specifies the Oracle type of the column which makes up the sharding key. It is expected to be one of the values from the enumeration :ref:`dpiOracleTypeNum` but currently only the value DPI_ORACLE_TYPE_VARCHAR is supported. .. member:: dpiNativeTypeNum dpiShardingKeyColumn.nativeTypeNum Specifies the native type of the column which makes up the sharding key. It is expected to be one of the values from the enumeration :ref:`dpiNativeTypeNum` but currently only the value DPI_NATIVE_TYPE_BYTES is supported. .. member:: dpiDataBuffer dpiShardingKeyColumn.value Specifies the value of the column which makes up the sharding key. It is a union of type :ref:`dpiDataBuffer` and the member of the union that is set must correspond to the value of the member :member:`dpiShardingKeyColumn.nativeTypeNum`. odpi-5.6.4/doc/src/structs/dpiSodaOperOptions.rst000066400000000000000000000113011510466437300220500ustar00rootroot00000000000000.. _dpiSodaOperOptions: ODPI-C Structure dpiSodaOperOptions ----------------------------------- This structure is used for passing search criteria to a number of SODA operations. It is initialized using the function :func:`dpiContext_initSodaOperOptions()` and used by the functions :func:`dpiSodaColl_find()`, :func:`dpiSodaColl_findOne()`, :func:`dpiSodaColl_getDocCount()`, :func:`dpiSodaColl_remove()` and :func:`dpiSodaColl_replaceOne()`. .. member:: uint32_t dpiSodaOperOptions.numKeys Specifies the number of elements in the members :member:`~dpiSodaOperOptions.keys` and :member:`~dpiSodaOperOptions.keyLengths`. .. member:: const char** dpiSodaOperOptions.keys Specifies an array of key values which documents in the collection must have in order to be processed by the operation. The length of this array is defined by the member :member:`~dpiSodaOperOptions.numKeys`. .. member:: uint32_t* dpiSodaOperOptions.keyLengths Specifies an array of key length values. Each element corresponds to the length of the key (in bytes) found in the member :member:`~dpiSodaOperOptions.keys` at the same element index. The length of this array is defined by the member :member:`~dpiSodaOperOptions.numKeys`. .. member:: const char* dpiSodaOperOptions.key Specifies the key which the document must have in order to be processed by the operation. .. member:: uint32_t dpiSodaOperOptions.keyLength Specifies the length of the member :member:`~dpiSodaOperOptions.key`, in bytes. .. member:: const char* dpiSodaOperOptions.version Specifies the document version that documents must have in order to be processed by the operation. This is typically used in conjunction with :member:`~dpiSodaOperOptions.key` and allows for opportunistic locking, so that operations do not affect a document that someone else has already modified. .. member:: uint32_t dpiSodaOperOptions.versionLength Specifies the length of the member :member:`~dpiSodaOperOptions.version`, in bytes. .. member:: const char* dpiSodaOperOptions.filter Specifies a filter value which limits the documents processed by the operation. See `Overview of SODA Filter Specifications (QBEs) `__. .. member:: uint32_t dpiSodaOperOptions.filterLength Specifies the length of the member :member:`~dpiSodaOperOptions.filter`, in bytes. .. member:: uint32_t dpiSodaOperOptions.skip Specifies the number of documents to skip before processing documents in the collection. A value of 0 will result in no documents being skipped. .. member:: uint32_t dpiSodaOperOptions.limit Specifies the maximum number of documents to process in the collection. A value of 0 means no limit is enforced. .. member:: uint32_t dpiSodaOperOptions.fetchArraySize Specifies the number of documents that will be fetched at one time from a SODA collection. Increasing this value reduces the number of round-trips to the database but increases the amount of memory allocated. A value of 0 means that the default value (100) is used. This member is only supported in Oracle Client 19.5 and higher. .. member:: const char* dpiSodaOperOptions.hint Specifies a hint that will be passed through to the SODA operation. These hints are the same as the hints used for normal SQL operations but without the enclosing comment characters. This member is only supported in Oracle Client 21.3 and higher (also available in Oracle Client 19 from 19.11). .. member:: uint32_t dpiSodaOperOptions.hintLength Specifies the length of the member :member:`~dpiSodaOperOptions.hint`, in bytes. This member is only supported in Oracle Client 21.3 and higher (also available in Oracle Client 19 from 19.11). .. member:: int dpiSodaOperOptions.lock Specifies whether the documents fetched from the collection should be locked (equivalent to SQL "select for update"). The next commit or rollback on the connection made after the operation is performed will "unlock" the documents. Ensure that the flag ``DPI_SODA_FLAGS_ATOMIC_COMMIT`` is not used for the operation as otherwise the lock will be removed immediately. This member should only be used with read operations (other than :func:`dpiSodaColl_getDocCount()`) and should not be used in conjunction with the :member:`~dpiSodaOperOptions.skip` and :member:`~dpiSodaOperOptions.limit` members. If this member is specified in conjunction with a write operation the value is ignored. This member is only supported in Oracle Client 21.3 and higher (also available in Oracle Client 19 from 19.11). odpi-5.6.4/doc/src/structs/dpiStmtInfo.rst000066400000000000000000000036371510466437300205400ustar00rootroot00000000000000.. _dpiStmtInfo: ODPI-C Structure dpiStmtInfo ---------------------------- This structure is used for passing information about a statement from ODPI-C. It is used by the function :func:`dpiStmt_getInfo()`. .. member:: int dpiStmtInfo.isQuery Specifies if the statement refers to a query (1) or not (0). .. member:: int dpiStmtInfo.isPLSQL Specifies if the statement refers to a PL/SQL block (1) or not (0). .. member:: int dpiStmtInfo.isDDL Specifies if the statement refers to DDL (data definition language) such as creating a table (1) or not (0). .. member:: int dpiStmtInfo.isDML Specifies if the statement refers to DML (data manipulation language) such as inserting, updating and deleting (1) or not (0). .. member:: dpiStatementType dpiStmtInfo.statementType Specifies the type of statement that has been prepared. The members :member:`dpiStmtInfo.isQuery`, :member:`dpiStmtInfo.isPLSQL`, :member:`dpiStmtInfo.isDDL` and :member:`dpiStmtInfo.isDML` are all categorizations of this value. It will be one of the values from the enumeration :ref:`dpiStatementType`. .. member:: int dpiStmtInfo.isReturning Specifies if the statement has a returning clause in it (1) or not (0). .. member:: char* dpiStmtInfo.sqlId A pointer to a string containing the SQL_ID of the statement, if available. The SQL_ID uniquely identifies a SQL statement in the database. This value is only populated when using Oracle Client and Oracle Database 12.2, or later. The string is not null-terminated; use :member:`dpiStmtInfo.sqlIdLength` to determine its size. It will remain valid only as long as the statement from which this statement info was acquired remains valid. .. member:: uint32_t dpiStmtInfo.sqlIdLength The length, in bytes, of the SQL_ID returned in :member:`dpiStmtInfo.sqlId`. This will be zero if the SQL_ID is not available. odpi-5.6.4/doc/src/structs/dpiStringList.rst000066400000000000000000000017041510466437300210700ustar00rootroot00000000000000.. _dpiStringList: ODPI-C Structure dpiStringList ------------------------------ This structure is used for receiving a list of strings from such functions as :func:`dpiSodaDb_getCollectionNames()` and :func:`dpiSodaColl_listIndexes()`. The memory referenced by this structure should be freed by the function :func:`dpiContext_freeStringList()` and should not be manipulated directly. .. member:: uint32_t dpiStringList.numStrings Specifies the number of elements in the strings and stringLengths arrays. .. member:: const char** dpiStringList.strings Specifies an array of pointers to strings. The length of this array is specified by the numStrings attribute. .. member:: uint32_t* dpiStringList.stringLengths Specifies an array of lengths. Each element in this array is the length of the string found in the corresponding element in the strings array, in bytes. The length of this array is specified by the numStrings attribute. odpi-5.6.4/doc/src/structs/dpiSubscrCreateParams.rst000066400000000000000000000146601510466437300225240ustar00rootroot00000000000000.. _dpiSubscrCreateParams: ODPI-C Structure dpiSubscrCreateParams -------------------------------------- This structure is used for creating subscriptions to messages sent for object change notification, query change notification or advanced queuing. All members are initialized to default values using the :func:`dpiContext_initSubscrCreateParams()` function. .. member:: dpiSubscrNamespace dpiSubscrCreateParams.subscrNamespace Specifies the namespace in which the subscription is created. It is expected to be one of the values from the enumeration :ref:`dpiSubscrNamespace`. The default value is DPI_SUBSCR_NAMESPACE_DBCHANGE. .. member:: dpiSubscrProtocol dpiSubscrCreateParams.protocol Specifies the protocol used for sending notifications for the subscription. It is expected to be one of the values from the enumeration :ref:`dpiSubscrProtocol`. The default value is DPI_SUBSCR_PROTO_CALLBACK. .. member:: dpiSubscrQOS dpiSubscrCreateParams.qos Specifies the quality of service flags to use with the subscription. It is expected to be one or more of the values from the enumeration :ref:`dpiSubscrQOS`, OR'ed together. The default value is to have no flags set. .. member:: dpiOpCode dpiSubscrCreateParams.operations Specifies which operations on the registered tables or queries should result in notifications. It is expected to be one or more of the values from the enumeration :ref:`dpiOpCode`, OR'ed together. The default value is DPI_OPCODE_ALL_OPS. .. member:: uint32_t dpiSubscrCreateParams.portNumber Specifies the port number on which to receive notifications. The default value is 0, which means that a port number will be selected by the Oracle client. .. member:: uint32_t dpiSubscrCreateParams.timeout Specifies the length of time, in seconds, before the subscription is unregistered. If the value is 0, the subscription remains active until explicitly unregistered. The default value is 0. .. member:: const char* dpiSubscrCreateParams.name Specifies the name of the subscription, as a byte string in the encoding used for CHAR data. This name must be consistent with the namespace identified in the :member:`dpiSubscrCreateParams.subscrNamespace` member. The default value is NULL. .. member:: uint32_t dpiSubscrCreateParams.nameLength Specifies the length of the :member:`dpiSubscrCreateParams.name` member, in bytes. The default value is 0. .. member:: dpiSubscrCallback dpiSubscrCreateParams.callback Specifies the callback that will be called when a notification is sent to the subscription, if the :member:`dpiSubscrCreateParams.protocol` member is set to DPI_SUBSCR_PROTO_CALLBACK. The callback accepts the following arguments: **context** -- the value of the :member:`dpiSubscrCreateParams.callbackContext` member. **message** -- a pointer to the message that is being sent. The message is in the form :ref:`dpiSubscrMessage`. The default value is NULL. If a callback is specified and a notification is sent, this will be performed on a separate thread. If database operations are going to take place, ensure that the create mode DPI_MODE_CREATE_THREADED is set in the structure :ref:`dpiCommonCreateParams` when creating the session pool or standalone connection that will be used in this callback. .. member:: void* dpiSubscrCreateParams.callbackContext Specifies the value that will be used as the first argument to the callback specified in the :member:`dpiSubscrCreateParams.callback` member. The default value is NULL. .. member:: const char* dpiSubscrCreateParams.recipientName Specifies the name of the recipient to which notifications are sent when the :member:`dpiSubscrCreateParams.protocol` member is not set to DPI_SUBSCR_PROTO_CALLBACK. The value is expected to be a byte string in the encoding used for CHAR data. The default value is NULL. .. member:: uint32_t dpiSubscrCreateParams.recipientNameLength Specifies the length of the :member:`dpiSubscrCreateParams.recipientName` member, in bytes. The default value is 0. .. member:: const char* dpiSubscrCreateParams.ipAddress Specifies the IP address on which the subscription listens to receive notifications. The IP address can be an IPv4 address in dotted decimal format such as 192.1.2.34 or an IPv6 address in hexadecimal format such as 2001:0db8:0000:0000:0217:f2ff:fe4b:4ced. The default value is NULL which means that an IP address will be selected by the Oracle client. .. member:: uint32_t dpiSubscrCreateParams.ipAddressLength Specifies the length of the :member:`dpiSubscrCreateParams.ipAddress` member, in bytes. The default value is 0. .. member:: uint8_t dpiSubscrCreateParams.groupingClass Specifies the grouping class to use when grouping events. It should be one of the values from the enumeration :ref:`dpiSubscrGroupingClass`. The default value is 0. If this value is 0, the groupingValue and groupingType attributes are ignored. .. member:: uint32_t dpiSubscrCreateParams.groupingValue Specifies the value to be used in grouping. The meaning of this value depends on the value of the groupingClass attribute. For time based grouping this value refers to the number of seconds during which events will be grouped together. The default value is 0. .. member:: uint8_t dpiSubscrCreateParams.groupingType Specifies the type of grouping to use when grouping events. It should be one of the values from the enumeration :ref:`dpiSubscrGroupingType`. The default value is DPI_SUBSCR_GROUPING_TYPE_SUMMARY. .. member:: uint64_t dpiSubscrCreateParams.outRegId Specifies the registration id of the subscription that corresponds to the REG_ID column in the USER_SUBSCR_REGISTRATIONS and DBA_SUBSCR_REGISTRATIONS views in the database. It will be populated for CQN registrations after a successful call to :func:`dpiConn_subscribe()`. .. member:: int dpiSubscrCreateParams.clientInitiated Specifies whether a client initiated connection should be created (1) or a server initiated connection should be created (0). The default value is 0. This feature is only available when Oracle Client 19.4 and Oracle Database 19.4 or higher are being used. odpi-5.6.4/doc/src/structs/dpiSubscrMessage.rst000066400000000000000000000110211510466437300215250ustar00rootroot00000000000000.. _dpiSubscrMessage: ODPI-C Structure dpiSubscrMessage --------------------------------- This structure is used for passing messages sent by notifications to subscriptions. It is the second parameter to the callback method specified in the :ref:`dpiSubscrCreateParams` structure. .. member:: dpiEventType dpiSubscrMessage.eventType Specifies the type of event that took place which generated the notification. It will be one of the values from the enumeration :ref:`dpiEventType`. .. member:: const char* dpiSubscrMessage.dbName Specifies the name of the database which generated the notification, as a byte string in the encoding used for CHAR data. This value is not populated when the :member:`~dpiSubscrMessage.eventType` member is set to the values DPI_EVENT_AQ or DPI_EVENT_DEREG. .. member:: uint32_t dpiSubscrMessage.dbNameLength Specifies the length of the :member:`~dpiSubscrMessage.dbName` member, in bytes. .. member:: dpiSubscrMessageTable* dpiSubscrMessage.tables Specifies a pointer to an array of :ref:`dpiSubscrMessageTable` structures representing the list of tables that were modified and generated this notification. This value is only populated when the value of the :member:`~dpiSubscrMessage.eventType` member is set to DPI_EVENT_OBJCHANGE. .. member:: uint32_t dpiSubscrMessage.numTables Specifies the number of structures available in the :member:`~dpiSubscrMessage.tables` member. .. member:: dpiSubscrMessageQuery* dpiSubscrMessage.queries Specifies a pointer to an array of :ref:`dpiSubscrMessageQuery` structures representing the list of queries that were modified and generated this notification. This value is only populated when the value of the :member:`~dpiSubscrMessage.eventType` member is set to DPI_EVENT_QUERYCHANGE. .. member:: uint32_t dpiSubscrMessage.numQueries Specifies the number of structures available in the :member:`~dpiSubscrMessage.queries` member. .. member:: dpiErrorInfo* dpiSubscrMessage.errorInfo Specifies a pointer to a :ref:`dpiErrorInfo` structure. This value will be NULL if no error has taken place. If this value is not NULL the other members in this structure will not be populated. .. member:: const void* dpiSubscrMessage.txId Specifies the id of the transaction which generated the notification, as a series of bytes. This value is not populated when the :member:`~dpiSubscrMessage.eventType` member is set to the values DPI_EVENT_AQ or DPI_EVENT_DEREG. .. member:: uint32_t dpiSubscrMessage.txIdLength Specifies the length of the :member:`~dpiSubscrMessage.txId` member, in bytes. .. member:: int dpiSubscrMessage.registered Specifies whether the subscription is registered with the database (1) or not (0). The subscription is automatically deregistered with the database when the subscription timeout value is reached or when the first notification is sent (when the quality of service flag DPI_SUBSCR_QOS_DEREG_NFY is used). .. member:: const char* dpiSubscrMessage.queueName Specifies the name of the queue which has messages available to dequeue, as a byte string in the encoding used for CHAR data. This value is only populated when the :member:`~dpiSubscrMessage.eventType` member is set to the value DPI_EVENT_AQ. .. member:: uint32_t dpiSubscrMessage.queueNameLength Specifies the length of the :member:`~dpiSubscrMessage.queueName` member, in bytes. .. member:: const char* dpiSubscrMessage.consumerName Specifies the consumer name of the queue which has messages available to dequeue, as a byte string in the encoding used for CHAR data. This value is only populated when the :member:`~dpiSubscrMessage.eventType` member is set to the value DPI_EVENT_AQ. It is also only populated if the queue that has messages to dequeue is a multi-consumer queue. .. member:: uint32_t dpiSubscrMessage.consumerNameLength Specifies the length of the :member:`~dpiSubscrMessage.consumerName` member, in bytes. .. member:: const void* dpiSubscrMessage.aqMsgId Specifies message id of the message which is available to dequeue, as a series of bytes. This value is only populated when the :member:`~dpiSubscrMessage.eventType` member is set to the value DPI_EVENT_AQ. .. member:: uint32_t dpiSubscrMessage.aqMsgIdLength Specifies the length of the :member:`~dpiSubscrMessage.aqMsgId` member, in bytes. odpi-5.6.4/doc/src/structs/dpiSubscrMessageQuery.rst000066400000000000000000000021241510466437300225570ustar00rootroot00000000000000.. _dpiSubscrMessageQuery: ODPI-C Structure dpiSubscrMessageQuery -------------------------------------- This structure is used for passing information on query change notification events and is part of the :ref:`dpiSubscrMessage` structure. .. member:: uint64_t dpiSubscrMessageQuery.id Specifies the id of the query that was registered as part of the subscription that generated this notification. .. member:: dpiOpCode dpiSubscrMessageQuery.operation Specifies the operations that took place on the registered query. It will be one or more of the values from the enumeration :ref:`dpiOpCode`, OR'ed together. .. member:: dpiSubscrMessageTable* dpiSubscrMessageQuery.tables Specifies a pointer to an array of :ref:`dpiSubscrMessageTable` structures representing the list of tables that were modified by the event which generated this notification. .. member:: uint32_t dpiSubscrMessageQuery.numTables Specifies the number of structures available in the :member:`dpiSubscrMessageQuery.tables` member. odpi-5.6.4/doc/src/structs/dpiSubscrMessageRow.rst000066400000000000000000000014131510466437300222210ustar00rootroot00000000000000.. _dpiSubscrMessageRow: ODPI-C Structure dpiSubscrMessageRow ------------------------------------ This structure is used for passing information on the rows that were changed and resulted in the notification message of which this structure is a part. .. member:: dpiOpCode dpiSubscrMessageRow.operation Specifies the operations that took place on the registered query. It will be one or more of the values from the enumeration :ref:`dpiOpCode`, OR'ed together. .. member:: const char* dpiSubscrMessageRow.rowid Specifies the rowid of the row that was changed, in the encoding used for CHAR data. .. member:: uint32_t dpiSubscrMessageRow.rowidLength Specifies the length of the :member:`dpiSubscrMessageRow.rowid` member, in bytes. odpi-5.6.4/doc/src/structs/dpiSubscrMessageTable.rst000066400000000000000000000022741510466437300225070ustar00rootroot00000000000000.. _dpiSubscrMessageTable: ODPI-C Structure dpiSubscrMessageTable -------------------------------------- This structure is used for passing information on the tables that were changed and resulted in the notification message of which this structure is a part. .. member:: dpiOpCode dpiSubscrMessageTable.operation Specifies the operations that took place on the modified table. It will be one or more of the values from the enumeration :ref:`dpiOpCode`, OR'ed together. .. member:: const char* dpiSubscrMessageRow.name Specifies the name of the table that was changed, in the encoding used for CHAR data. .. member:: uint32_t dpiSubscrMessageRow.nameLength Specifies the length of the :member:`dpiSubscrMessageRow.name` member, in bytes. .. member:: dpiSubscrMessageRow* dpiSubscrMessageTable.rows Specifies a pointer to an array of :ref:`dpiSubscrMessageRow` structures representing the list of rows that were modified by the event which generated this notification. .. member:: uint32_t dpiSubscrMessageTable.numRows Specifies the number of structures available in the :member:`dpiSubscrMessageTable.rows` member. odpi-5.6.4/doc/src/structs/dpiTimestamp.rst000066400000000000000000000027771510466437300207440ustar00rootroot00000000000000.. _dpiTimestamp: ODPI-C Structure dpiTimestamp ----------------------------- This structure is used for passing timestamp data to and from the database in the structure :ref:`dpiData`. .. member:: int16_t dpiTimestamp.year Specifies the year for the timestamp. .. member:: uint8_t dpiTimestamp.month Specifies the month for the timestamp. This should be between 1 and 12. .. member:: uint8_t dpiTimestamp.day Specifies the day for the timestamp. This should be between 1 and 31. .. member:: uint8_t dpiTimestamp.hour Specifies the hour for the timestamp. This should be between 0 and 23. .. member:: uint8_t dpiTimestamp.minute Specifies the minute for the timestamp. This should be between 0 and 59. .. member:: uint8_t dpiTimestamp.second Specifies the second for the timestamp. This should be between 0 and 59. .. member:: uint32_t dpiTimestamp.fsecond Specifies the fractional seconds for the timestamp, in nanoseconds. .. member:: int8_t dpiTimestamp.tzHourOffset Specifies the hours offset from UTC. This value is only used for timestamp with time zone and timestamp with local time zone columns. .. member:: int8_t dpiTimestamp.tzMinuteOffset Specifies the minutes offset from UTC. This value is only used for timestamp with time zone and timestamp with local time zone columns. Note that this value will be negative in the western hemisphere. For example, when the timezone is -03:30, tzHourOffset will be -3 and tzMinuteOffset will be -30. odpi-5.6.4/doc/src/structs/dpiVectorInfo.rst000066400000000000000000000035521510466437300210470ustar00rootroot00000000000000.. _dpiVectorInfo: ODPI-C Structure dpiVectorInfo ------------------------------- This structure is used for providing or receiving information about a vector. .. member:: uint8_t dpiVectorInfo.format Specifies the storage format for the vector. It should be one of the values from the enumeration :ref:`dpiVectorFormat`. .. member:: uint32_t dpiVectorInfo.numDimensions Specifies the number of dimensions the vector contains. .. member:: uint8_t dpiVectorInfo.dimensionSize Specifies the size (in bytes) of each dimension of the vector. This value does not need to be specified on input but is populated on output as a convenience. .. member:: dpiVectorDimensionBuffer dpiVectorInfo.dimensions Specifies the buffer for the dimensions. On input the buffer must remain valid for the duration of the call into ODPI-C. On output the buffer will remain valid as long as the vector object remains valid and the contents of the vector are not changed. See the :ref:`dpiVectorDimensionBuffer` union for more information. For dense vectors, the length of this array is defined by the :member:`~dpiVectorInfo.numDimensions` member. For sparse vectors, the length of this array is defined by the :member:`~dpiVectorInfo.numSparseValues` member. .. member:: uint32_t dpiVectorInfo.numSparseValues Specifies the number of values that a sparse vector contains that are non-zero. If this value is 0, the vector is considered a dense vector. .. member:: uint32_t* dpiVectorInfo.sparseIndices Specifies an array of sparse vector indices. Each element in this array is the index of a non-zero value in the vector. The length of this array is defined by the :member:`~dpiVectorInfo.numSparseValues` member. If the vector is not a sparse vector, this value will be NULL. odpi-5.6.4/doc/src/structs/dpiVersionInfo.rst000066400000000000000000000020771510466437300212330ustar00rootroot00000000000000.. _dpiVersionInfo: ODPI-C Structure dpiVersionInfo ------------------------------- This structure is used for returning Oracle version information about the Oracle Client (:func:`dpiContext_getClientVersion()`) and Oracle Database (:func:`dpiConn_getServerVersion()`). .. member:: int dpiVersionInfo.versionNum Specifies the major version of the Oracle Client or Database. .. member:: int dpiVersionInfo.releaseNum Specifies the release version of the Oracle Client or Database. .. member:: int dpiVersionInfo.updateNum Specifies the update version of the Oracle Client or Database. .. member:: int dpiVersionInfo.portReleaseNum Specifies the port specific release version of the Oracle Client or Database. .. member:: int dpiVersionInfo.portUpdateNum Specifies the port specific update version of the Oracle Client or Database. .. member:: uint32_t dpiVersionInfo.fullVersionNum Specifies the full version (all five components) as a number that is suitable for comparison with the result of the macro DPI_ORACLE_VERSION_TO_NUMBER. odpi-5.6.4/doc/src/structs/dpiXid.rst000066400000000000000000000021111510466437300175030ustar00rootroot00000000000000.. _dpiXid: ODPI-C Structure dpiXid ------------------------------- This structure is used for identifying a TPC (two-phase commit) transaction. It is used by the TPC functions :func:`dpiConn_tpcBegin()`, :func:`dpiConn_tpcCommit()`, :func:`dpiConn_tpcEnd()`, :func:`dpiConn_tpcForget()`, :func:`dpiConn_tpcPrepare()` and :func:`dpiConn_tpcRollback()`. .. member:: long dpiXid.formatId An integer identifying the format the transaction id is expected to take. A value of -1 implies that the XID value is NULL. .. member:: const char* dpiXid.globalTransactionId Specifies the global transaction identifier of the XID. .. member:: uint32_t dpiXid.globalTransactionIdLength Specifies the length of the :data:`dpiXid.globalTransactionId` member, in bytes. The maximum supported length is 64 bytes. .. member:: const char* dpiXid.branchQualifier Specifies the branch qualifier of the XID. .. member:: uint32_t dpiXid.branchQualifierLength Specifies the length of the :data:`dpiXid.branchQualifier` member, in bytes. The maximum supported length is 64 bytes. odpi-5.6.4/doc/src/structs/index.rst000066400000000000000000000031651510466437300174030ustar00rootroot00000000000000***************** ODPI-C Structures ***************** This chapter details the structures available in the ODPI-C library. .. toctree:: :maxdepth: 1 :hidden: dpiAccessToken dpiAnnotation dpiAppContext dpiBytes dpiCommonCreateParams dpiConnCreateParams dpiConnInfo dpiContextCreateParams dpiData dpiDataTypeInfo dpiEncodingInfo dpiErrorInfo dpiIntervalDS dpiIntervalYM dpiJsonArray dpiJsonNode dpiJsonObject dpiMsgRecipient dpiObjectAttrInfo dpiObjectTypeInfo dpiPoolCreateParams dpiQueryInfo dpiSessionlessTransactionId dpiShardingKeyColumn dpiSodaOperOptions dpiStmtInfo dpiStringList dpiSubscrCreateParams dpiSubscrMessage dpiSubscrMessageQuery dpiSubscrMessageRow dpiSubscrMessageTable dpiTimestamp dpiVectorInfo dpiVersionInfo dpiXid odpi-5.6.4/doc/src/unions/000077500000000000000000000000001510466437300153415ustar00rootroot00000000000000odpi-5.6.4/doc/src/unions/dpiDataBuffer.rst000066400000000000000000000102051510466437300205710ustar00rootroot00000000000000.. _dpiDataBuffer: ODPI-C Union dpiDataBuffer -------------------------- This union is used for passing data to and from the database without requiring casts. .. member:: int dpiDataBuffer.asBoolean Value that is used when the native type that is being used is DPI_NATIVE_TYPE_BOOLEAN. The value should be either 1 (true) or 0 (false). .. member:: uint8_t dpiDataBuffer.asUint8 Only used for getting/setting OCI attributes of 1 byte in length. .. member:: uint16_t dpiDataBuffer.asUint16 Only used for getting/setting OCI attributes of 2 bytes in length. .. member:: uint32_t dpiDataBuffer.asUint32 Only used for getting/setting OCI attributes of 4 bytes in length. .. member:: int64_t dpiDataBuffer.asInt64 Value that is used when the native type that is being used is DPI_NATIVE_TYPE_INT64. .. member:: uint64_t dpiDataBuffer.asUint64 Value that is used when the native type that is being used is DPI_NATIVE_TYPE_UINT64. .. member:: float dpiDataBuffer.asFloat Value that is used when the native type that is being used is DPI_NATIVE_TYPE_FLOAT. .. member:: double dpiDataBuffer.asDouble Value that is used when the native type that is being used is DPI_NATIVE_TYPE_DOUBLE. .. member:: char* dpiDataBuffer.asString Only used for getting/setting OCI attributes of type string. .. member:: void* dpiDataBuffer.asRaw Raw pointer used for getting/setting all OCI attributes. .. member:: dpiBytes dpiDataBuffer.asBytes Value that is used when the native type that is being used is DPI_NATIVE_TYPE_BYTES. This is a structure of type :ref:`dpiBytes`. .. member:: dpiTimestamp dpiDataBuffer.asTimestamp Value that is used when the native type that is being used is DPI_NATIVE_TYPE_TIMESTAMP. This is a structure of type :ref:`dpiTimestamp`. .. member:: dpiIntervalDS dpiDataBuffer.asIntervalDS Value that is used when the native type that is being used is DPI_NATIVE_TYPE_INTERVAL_DS. This is a structure of type :ref:`dpiIntervalDS`. .. member:: dpiIntervalYM dpiDataBuffer.asIntervalYM Value that is used when the native type that is being used is DPI_NATIVE_TYPE_INTERVAL_YM. This is a structure of type :ref:`dpiIntervalYM`. .. member:: dpiJson* dpiDataBuffer.asJson Value that is used when the native type that is being used is DPI_NATIVE_TYPE_JSON. This is a reference to a JSON value which can be used for reading and writing the data that belongs to it. .. member:: dpiJsonObject dpiDataBuffer.asJsonObject Value this is used when the native type that is being used is DPI_NATIVE_TYPE_JSON_OBJECT. This is a structure of type :ref:`dpiJsonObject`. .. member:: dpiJsonArray dpiDataBuffer.asJsonArray Value this is used when the native type that is being used is DPI_NATIVE_TYPE_JSON_ARRAY. This is a structure of type :ref:`dpiJsonArray`. .. member:: dpiLob* dpiDataBuffer.asLOB Value that is used when the native type that is being used is DPI_NATIVE_TYPE_LOB. This is a reference to a LOB (large object) which can be used for reading and writing the data that belongs to it. .. member:: dpiObject* dpiDataBuffer.asObject Value that is used when the native type that is being used is DPI_NATIVE_TYPE_OBJECT. This is a reference to an object which can be used for reading and writing its attributes or element values. .. member:: dpiStmt* dpiDataBuffer.asStmt Value that is used when the native type that is being used is DPI_NATIVE_TYPE_STMT. This is a reference to a statement which can be used to query data from the database. .. member:: dpiRowid* dpiDataBuffer.asRowid Value that is used when the native type that is being used is DPI_NATIVE_TYPE_ROWID. This is a reference to a rowid which is used to uniquely identify a row in a table in the database. .. member:: dpiVector* dpiDataBuffer.asVector Value that is used when the native type that is being used is DPI_NATIVE_TYPE_VECTOR. This is a reference to a vector value which can be used for reading and writing the data that belongs to it. odpi-5.6.4/doc/src/unions/dpiVectorDimensionBuffer.rst000066400000000000000000000012601510466437300230310ustar00rootroot00000000000000.. _dpiVectorDimensionBuffer: ODPI-C Union dpiVectorDimensionBuffer -------------------------------------- This union is used for passing vector dimensions to and from the database without requiring casts. .. member:: void* dpiVectorDimensionBuffer.asPtr Raw pointer to dimension buffer. .. member:: int8_t* dpiVectorDimensionBuffer.asInt8 Pointer to dimension buffer when vector format is VECTOR_FORMAT_INT8. .. member:: float* dpiVectorDimensionBuffer.asFloat Pointer to dimension buffer when vector format is VECTOR_FORMAT_FLOAT32. .. member:: double* dpiVectorDimensionBuffer.asDouble Pointer to dimension buffer when vector format is VECTOR_FORMAT_FLOAT64. odpi-5.6.4/doc/src/unions/index.rst000066400000000000000000000003711510466437300172030ustar00rootroot00000000000000************* ODPI-C Unions ************* This chapter details the unions available in the ODPI-C library. .. toctree:: :maxdepth: 1 :hidden: dpiDataBuffer dpiVectorDimensionBuffer odpi-5.6.4/doc/src/user_guide/000077500000000000000000000000001510466437300161615ustar00rootroot00000000000000odpi-5.6.4/doc/src/user_guide/data_types.rst000066400000000000000000000110301510466437300210430ustar00rootroot00000000000000.. _data_types: ************************ ODPI-C Data Type Support ************************ The following table identifies each Oracle type from the enumeration :ref:`dpiOracleTypeNum` and the native C types from the enumeration :ref:`dpiNativeTypeNum` that can be used with them when creating variables using the method :func:`dpiConn_newVar()`. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 10 10 30 :summary: The first column displays the Oracle type. The second column displays the supported native C types. The third column displays the notes. * - Oracle Type - Supported Native C Types [*]_ - Notes * - DPI_ORACLE_TYPE_BFILE - DPI_NATIVE_TYPE_LOB - Use method :func:`dpiVar_setFromLob()` to set values. * - DPI_ORACLE_TYPE_BOOLEAN - DPI_NATIVE_TYPE_BOOLEAN - This type is only usable in PL/SQL. * - DPI_ORACLE_TYPE_BLOB - DPI_NATIVE_TYPE_LOB - Use method :func:`dpiVar_setFromLob()` to set values. * - DPI_ORACLE_TYPE_CHAR - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. * - DPI_ORACLE_TYPE_CLOB - DPI_NATIVE_TYPE_LOB - Use method :func:`dpiVar_setFromLob()` to set values. * - DPI_ORACLE_TYPE_DATE - DPI_NATIVE_TYPE_TIMESTAMP - No relevant notes * - DPI_ORACLE_TYPE_INTERVAL_DS - DPI_NATIVE_TYPE_INTERVAL_DS - No relevant notes * - DPI_ORACLE_TYPE_INTERVAL_YM - DPI_NATIVE_TYPE_INTERVAL_YM - No relevant notes * - DPI_ORACLE_TYPE_LONG_RAW - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. * - DPI_ORACLE_TYPE_LONG_VARCHAR - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. * - DPI_ORACLE_TYPE_NATIVE_DOUBLE - DPI_NATIVE_TYPE_DOUBLE - No relevant notes * - DPI_ORACLE_TYPE_NATIVE_INT - DPI_NATIVE_TYPE_INT64 - No relevant notes * - DPI_ORACLE_TYPE_NATIVE_FLOAT - DPI_NATIVE_TYPE_FLOAT - No relevant notes * - DPI_ORACLE_TYPE_NATIVE_UINT - DPI_NATIVE_TYPE_UINT64 - No relevant notes * - DPI_ORACLE_TYPE_NCHAR - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. * - DPI_ORACLE_TYPE_NCLOB - DPI_NATIVE_TYPE_LOB - Use method :func:`dpiVar_setFromLob()` to set values. * - DPI_ORACLE_TYPE_NUMBER - DPI_NATIVE_TYPE_DOUBLE, DPI_NATIVE_TYPE_BYTES, DPI_NATIVE_TYPE_INT64, DPI_NATIVE_TYPE_UINT64 - Use method :func:`dpiVar_setFromBytes()` to set values when using DPI_NATIVE_TYPE_BYTES. Note that Oracle Database number values use a decimal format and that accurately transferring the value from the database can only be guaranteed with DPI_NATIVE_TYPE_BYTES. DPI_NATIVE_TYPE_INT64 and DPI_NATIVE_TYPE_UINT64 can only represent integers and DPI_NATIVE_TYPE_DOUBLE can only represent numbers accurately if they contain at most between 15 and 17 decimal digits. [*]_ * - DPI_ORACLE_TYPE_NVARCHAR - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. * - DPI_ORACLE_TYPE_OBJECT - DPI_NATIVE_TYPE_OBJECT - Use method :func:`dpiVar_setFromObject()` to set values. * - DPI_ORACLE_TYPE_RAW - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. * - DPI_ORACLE_TYPE_ROWID - DPI_NATIVE_TYPE_ROWID - Use method :func:`dpiVar_setFromRowid()` to set values. * - DPI_ORACLE_TYPE_STMT - DPI_NATIVE_TYPE_STMT - Use method :func:`dpiVar_setFromStmt()` to set values. * - DPI_ORACLE_TYPE_TIMESTAMP - DPI_NATIVE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_DOUBLE - When using DPI_NATIVE_TYPE_DOUBLE the value corresponds to the number of seconds since Jan 1, 1970. * - DPI_ORACLE_TYPE_TIMESTAMP_LTZ - DPI_NATIVE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_DOUBLE - When using DPI_NATIVE_TYPE_DOUBLE the value corresponds to the number of seconds since Jan 1, 1970. * - DPI_ORACLE_TYPE_TIMESTAMP_TZ - DPI_NATIVE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_DOUBLE - When using DPI_NATIVE_TYPE_DOUBLE the value corresponds to the number of seconds since Jan 1, 1970. * - DPI_ORACLE_TYPE_VARCHAR - DPI_NATIVE_TYPE_BYTES - Use method :func:`dpiVar_setFromBytes()` to set values. .. [*] The first type listed is the default type. .. [*] https://en.wikipedia.org/wiki/Double-precision_floating-point_format odpi-5.6.4/doc/src/user_guide/debugging.rst000066400000000000000000000063711510466437300206550ustar00rootroot00000000000000.. _debugging: **************** ODPI-C Debugging **************** .. _level: Level ===== The environment variable DPI_DEBUG_LEVEL can be used to selectively turn on the printing of various logging messages as defined in the following table. All messages are printed to stderr. Each level is independent of all other levels and the values of each level can be added to one another to choose which messages will be printed. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 10 5 7 30 :summary: The first column displays the level. The second column displays the hex value. The third column displays the decimal value. The fourth column displays the description of the debug level. * - Level - Hex Value - Decimal Value - Description * - DPI_DEBUG_LEVEL_UNREPORTED_ERRORS - 0x0001 - 1 - Prints messages when unreported errors take place (such as when an error takes place during the freeing of OCI handles and descriptors). * - DPI_DEBUG_LEVEL_REFS - 0x0002 - 2 - Prints messages when reference counts are added and released. * - DPI_DEBUG_LEVEL_FNS - 0x0004 - 4 - Prints messages when a public ODPI-C function is called. * - DPI_DEBUG_LEVEL_ERRORS - 0x0008 - 8 - Prints messages when an error is raised. * - DPI_DEBUG_LEVEL_SQL - 0x0010 - 16 - Prints the text of all SQL that is prepared. Bind values are not displayed. * - DPI_DEBUG_LEVEL_MEM - 0x0020 - 32 - Prints the location and size of all memory allocations and frees performed by the library. * - DPI_DEBUG_LEVEL_LOAD_LIB - 0x0040 - 64 - Prints the methods and locations searched for the Oracle Client library in addition to any errors that took place. .. _prefix: Prefix ====== The environment variable DPI_DEBUG_PREFIX can be used to specify the prefix that is printed in front of each debugging message. If not set, the default prefix is ``"ODPI [%i] %d %t: "``. The maximum length of the prefix string that can be set is 64 characters. If an attempt is made to set a value longer than that, it is ignored and the default prefix is used instead. The following directives can be used within the prefix: .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 15 30 :summary: The first column displays the directive. The second column displays the comments. * - Directive - Comments * - %i - Replaced by the identifier of the thread that is printing the message * - %d - Replaced by the date the message is printed, in the format YYYY/MM/DD * - %t - Replaced by the time the message is printed, in the format HH:MM:SS.SSS All other characters in the prefix are copied unchanged to the output. .. _memtracing: Memory Tracing ============== The Python script `mem_leak.py `__ can be used to search for memory leaks. The script's argument should be the name of a file containing trace output when DPI_DEBUG_LEVEL is set to DPI_DEBUG_LEVEL_MEM:: export DPI_DEBUG_LEVEL=32 ./myprog >& mem.log python mem_leak.py mem.log odpi-5.6.4/doc/src/user_guide/installation.rst000066400000000000000000000652371510466437300214310ustar00rootroot00000000000000.. _installation: ***************** Installing ODPI-C ***************** .. _overview: Overview ======== To use ODPI-C in your own project, download its source from `GitHub `__. A sample Makefile is provided if you wish to build ODPI-C as a shared library. Otherwise, add the ODPI-C source code to your project. On Windows, Visual Studio 2008 or higher is required. On macOS, Xcode 6 or higher is required. On Linux, GCC 4.4 or higher is required. ODPI-C has been tested on Linux, Windows and macOS. Other platforms should also work but have not been tested. Projects using ODPI-C require Oracle Client libraries to be installed. The libraries provide the necessary network connectivity allowing applications to access an Oracle Database instance. They also provide basic and advanced connection management and data features to ODPI-C applications. .. _clientlibloading: Oracle Client Library Loading ----------------------------- The simplest Oracle Client is the free `Oracle Instant Client `__. Only the "Basic" or "Basic Light" package is required. Oracle Client libraries are also available in any Oracle Database installation or full Oracle Client installation. ODPI-C dynamically loads available Oracle Client libraries at runtime. This allows code using ODPI-C to be built only once, and then run using any available Oracle Client 21, 19, 18, 12, or 11.2 libraries. If Oracle Client libraries are not found, the error "DPI-1047: Cannot locate an Oracle Client library" is raised. If an Oracle Client library is found but the version cannot be determined, the error "DPI-1072: the Oracle Client library version is unsupported" is raised. For example, this could be because the Oracle Client library version is too old (prior to 10g) or entirely unsupported (such as Oracle Client 19 on Windows 7). If the member :member:`dpiContextCreateParams.oracleClientLibDir` is specified when calling :func:`dpiContext_createWithParams()`, then only that directory is searched for the Oracle Client libraries. If no directory is specified, then the Oracle Client libraries are looked for in the same directory that the ODPI-C library (or application binary) is located in. If they are not found, then they are searched for in the standard operating system search path, for example ``PATH`` on Windows or ``LD_LIBRARY_PATH`` on Linux. See `standard Windows library search order `__ or `standard Linux library search order `__. Finally, on platforms other than Windows, ``$ORACLE_HOME/lib`` is also searched. .. note:: - When using Instant Client on Linux and related operating systems, then that directory must always be in the system library search path. - When using the library directory from a full client or database installation, then you additionally need to set the application environment to use this software, for example by setting the ``ORACLE_HOME`` environment variable. This should be done prior to ODPI-C initialization. Make sure the application has directory and file access permissions for the Oracle Client libraries. On Linux ensure ``libclntsh.so`` exists. On macOS ensure ``libclntsh.dylib`` exists. ODPI-C will not directly load ``libclntsh.*.XX.1`` files in :member:`dpiContextCreateParams.oracleClientLibDir` or from the directory where the ODPI-C library (or application binary) is. Note other files used by ``libclntsh*`` are also required. To trace the loading of Oracle Client libraries, the environment variable ``DPI_DEBUG_LEVEL`` can be set to 64 before starting your application. See :ref:`debugging`. The following sections explain how to ensure the Oracle Client is installed and configured correctly on the various platforms so that ODPI-C is able to find it. Oracle Client and Oracle Database Interoperability -------------------------------------------------- Oracle's standard client-server network interoperability allows connections between different versions of Oracle Client and Oracle Database. For certified configurations see Oracle Support's `Doc ID 207303.1 `__. In summary, Oracle Client 21 can connect to Oracle Database 12.1 or later. Oracle Client 19, 18 and 12.2 can connect to Oracle Database 11.2 or greater. Oracle Client 12.1 can connect to Oracle Database 10.2 or greater. Oracle Client 11.2 can connect to Oracle Database 9.2 or greater. The technical restrictions on creating connections may be more flexible. For example Oracle Client 12.2 can successfully connect to Oracle Database 10.2. Since a single ODPI-C binary can use multiple client versions and access multiple database versions, it is important your application is tested in your intended release environments. Newer Oracle clients support new features, such as the `oraaccess.xml `__ external configuration file available with 12.1 or later clients, session pool improvements, call timeouts with 18 or later clients, and `other enhancements `__. The function :func:`dpiContext_getClientVersion()` can be used to determine which Oracle Client version is in use and the function :func:`dpiConn_getServerVersion()` can be used to determine which Oracle Database version a connection is accessing. These can then be used to adjust application behavior accordingly. Attempts to use some Oracle features that are not supported by a particular client/server combination may result in runtime errors. These include: - when attempting to access attributes that are not supported by the current Oracle Client library you will get the error "ORA-24315: illegal attribute type" - when attempting to use implicit results with Oracle Client 11.2 against Oracle Database 12c you will get the error "ORA-29481: Implicit results cannot be returned to client" - when attempting to get array DML row counts with Oracle Client 11.2 you will get the error "DPI-1050: Oracle Client library must be at version 12.1 or higher" .. _linuxinstall: Linux ===== ODPI-C requires Oracle Client libraries, which are found in Oracle Instant Client, or an Oracle Database installation, or in a full Oracle Client installation, see :ref:`clientlibloading`. The libraries must be either 32-bit or 64-bit, matching your application and ODPI-C library (if one is created separately). .. _instzip: Oracle Instant Client Zip Files ------------------------------- To run ODPI-C applications with Oracle Instant Client zip files: 1. Download an Oracle 21, 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip file matching your application 64-bit or 32-bit architecture: - `x86-64 64-bit `__ - `x86 32-bit `__ - `ARM (aarch64) 64-bit `__ 2. Unzip the package into a directory that is accessible to your application. For example:: mkdir -p /opt/oracle cd /opt/oracle unzip instantclient-basic-linux.x64-21.1.0.0.0.zip 3. Install the operating system ``libaio`` package with sudo or as the root user. For example:: sudo yum install libaio On some Linux distributions this package is called ``libaio1`` instead. On recent Linux versions, such as Oracle Linux 8, you may also need to install the ``libnsl`` package when using Oracle Instant Client 19. 4. If there is no other Oracle software on the machine that will be impacted, permanently add Instant Client to the runtime link path. For example, with sudo or as the root user:: sudo sh -c "echo /opt/oracle/instantclient_21_1 > /etc/ld.so.conf.d/oracle-instantclient.conf" sudo ldconfig Alternatively, set the environment variable ``LD_LIBRARY_PATH`` to the appropriate directory for the Instant Client version. For example:: export LD_LIBRARY_PATH=/opt/oracle/instantclient_21_1:$LD_LIBRARY_PATH 5. If you use optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml``, put the files in an accessible directory. Then set the member :member:`dpiContextCreateParams.oracleClientConfigDir` when calling :func:`dpiContext_createWithParams()`. Alternatively, set the environment variable ``TNS_ADMIN`` to that directory name. Alternatively, create a ``network/admin`` subdirectory of Instant Client, if it does not exist. For example, with Instant Client 12.2:: mkdir -p /opt/oracle/instantclient_12_2/network/admin Put the files in this directory. This is the default Oracle configuration directory for applications linked with this Instant Client. .. _instrpm: Oracle Instant Client RPM Files ------------------------------- To run ODPI-C applications with Oracle Instant Client RPMs: 1. Download an Oracle 21,19, 18, 12, or 11.2 "Basic" or "Basic Light" RPM matching your application architecture: - `x86-64 64-bit `__ - `x86 32-bit `__ - `ARM (aarch64) 64-bit `__ Oracle's yum server has convenient repositories: - `Instant Client 21 RPMs for Oracle Linux x86-64 8 `__, `Older Instant Client RPMs for Oracle Linux x86-64 8 `__ - `Instant Client 21 RPMs for Oracle Linux x86-64 7 `__, `Older Instant Client RPMs for Oracle Linux x86-64 7 `__ - `Instant Client RPMs for Oracle Linux x86-64 6 `__ - `Instant Client RPMs for Oracle Linux ARM (aarch64) 8 `__ - `Instant Client RPMs for Oracle Linux ARM (aarch64) 7 `__ 2. Install the downloaded RPM with sudo or as the root user. For example:: sudo yum install oracle-instantclient-basic-21.1.0.0.0-1.x86_64.rpm On recent Linux versions, such as Oracle Linux 8, you may also need to manually install the ``libnsl`` package package when using Oracle Instant Client 19. Yum will automatically install other required dependencies, such as ``libaio``. Oracle Linux users can alternatively automate download and installation. For example:: yum install oracle-instantclient-release-el7 yum install oracle-instantclient-basic Refer to `Instant Client for Oracle Linux `__ for details. 3. For Instant Client 19, or later, RPMs, the system library search path is automatically configured during installation. For older versions, if there is no other Oracle software on the machine that will be impacted, permanently add Instant Client to the runtime link path. For example, with sudo or as the root user:: sudo sh -c "echo /usr/lib/oracle/18.5/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf" sudo ldconfig Alternatively, for version 18 and earlier, every shell will need to have the environment variable ``LD_LIBRARY_PATH`` set to the appropriate directory for the Instant Client version. For example:: export LD_LIBRARY_PATH=/usr/lib/oracle/18.5/client64/lib:$LD_LIBRARY_PATH 4. If you use optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml``, put the files in an accessible directory. Then set the member :member:`dpiContextCreateParams.oracleClientConfigDir` when calling :func:`dpiContext_createWithParams()`. Alternatively, set the environment variable ``TNS_ADMIN`` to that directory name. Alternatively, create a ``network/admin`` subdirectory of Instant Client, if it does not exist. For example, with Instant Client 12.2:: sudo mkdir -p /usr/lib/oracle/12.2/client64/lib/network/admin Put the files in this directory. This is the default Oracle configuration directory for applications linked with this Instant Client. .. _instoh: Local Database or Full Oracle Client ------------------------------------ ODPI-C applications can use Oracle Client 21, 19, 18, 12, or 11.2 libraries from a local Oracle Database or full Oracle Client installation. The libraries must be either 32-bit or 64-bit, matching your application and ODPI-C library (if one is created separately). 1. Set required Oracle environment variables by running the Oracle environment script. For example:: source /usr/local/bin/oraenv For Oracle Database XE 11.2, run:: source /u01/app/oracle/product/11.2.0/xe/bin/oracle_env.sh 2. Optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` can be placed in ``$ORACLE_HOME/network/admin``. Alternatively, Oracle configuration files can be put in another, accessible directory. Then set the member :member:`dpiContextCreateParams.oracleClientConfigDir` when calling :func:`dpiContext_createWithParams()`, or set the environment variable ``TNS_ADMIN`` to that directory name. .. _containers: Containers ---------- Dockerfiles +++++++++++ ODPI-C applications can easily be used in containers by basing your deployments on the Instant Client Dockerfiles on `GitHub `__. To build an Instant Client image, create a Dockerfile, for example:: FROM oraclelinux:8-slim RUN microdnf install oracle-instantclient-release-el8 && \ microdnf install oracle-instantclient-basic oracle-instantclient-devel oracle-instantclient-sqlplus && \ microdnf clean all Then run:: docker build -t oracle/instantclient:21 . The new image can be used as the basis for your application. Pre-built Containers ++++++++++++++++++++ Pre-built images for Instant Client are in the GitHub Container Registry: - https://github.com/orgs/oracle/packages/container/package/oraclelinux8-instantclient - https://github.com/orgs/oracle/packages/container/package/oraclelinux7-instantclient These are easily used. For example, to pull an Oracle Linux 8 image with Oracle Instant Client 21c already installed, execute:: docker pull ghcr.io/oracle/oraclelinux8-instantclient:21 .. _windowsinstallation: Windows ======= ODPI-C requires Oracle Client libraries, which are found in Oracle Instant Client, or an Oracle Database installation, or in a full Oracle Client installation, see :ref:`clientlibloading`. The libraries must be either 32-bit or 64-bit, matching your application and ODPI-C library (if one is created separately). Oracle Client libraries require the presence of the correct Visual Studio redistributable: - For Instant Client 21 install `VS 2019 `__ or later. - For Instant Client 19 install `VS 2017 `__. - For Instant Client 18 or 12.2 install `VS 2013 `__ - For Instant Client 12.1 install `VS 2010 `__ - For Instant Client 11.2 install `VS 2005 64-bit `__ .. _instwin: Oracle Instant Client Zip Files ------------------------------- To run ODPI-C applications with Oracle Instant Client zip files: 1. Download an Oracle 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip file: `64-bit `__ or `32-bit `__, matching your application architecture. Note that 19c is not supported on Windows 7. 2. Unzip the package into a directory that is accessible to your application. For example unzip ``instantclient-basic-windows.x64-19.11.0.0.0dbru.zip`` to ``C:\oracle\instantclient_19_11``. Configure Oracle Instant Client +++++++++++++++++++++++++++++++ 1. There are several alternative ways to tell your application where your Oracle Instant Client libraries are. * Set this directory in the member :member:`dpiContextCreateParams.oracleClientLibDir` when calling :func:`dpiContext_createWithParams()`. * Alternatively, move the unzipped Instant Client files to the directory containing ODPIC.DLL (or into the directory of the application's binary, if ODPI-C is compiled into the application). * Alternatively, add the Instant Client directory to the ``PATH`` environment variable. For example, on Windows 7, update ``PATH`` in Control Panel -> System -> Advanced System Settings -> Advanced -> Environment Variables -> System Variables -> PATH. The Instant Client directory must occur in ``PATH`` before any other Oracle directories. Restart any open command prompt windows. To avoid interfering with existing tools that require other Oracle Client versions, instead of updating the system-wide ``PATH`` variable, you may prefer to write a batch file that sets ``PATH``, for example:: REM mywrapper.bat SET PATH=C:\oracle\instantclient_19_11;%PATH% myapp %* Invoke this batch file every time you want to run your application. Or simply use ``SET`` to change your ``PATH`` in each command prompt window before you run your application. 2. If you use optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml``, put the files in an accessible directory. Then set the member :member:`dpiContextCreateParams.oracleClientConfigDir` when calling :func:`dpiContext_createWithParams()`. Alternatively, set the environment variable ``TNS_ADMIN`` to that directory name. Alternatively, create a ``network\admin`` subdirectory of Instant Client, if it does not exist. For example ``C:\oracle\instantclient_19_11\network\admin``. Put the files in this directory. This is the default Oracle configuration directory for applications linked with this Instant Client. If you wish to package Instant Client with your application, you can move the Instant Client libraries to the same directory as the ODPI-C library (or application). Refer to the `Instant Client documentation `__ for the minimal set of Instant Client files required. There is no need to set :member:`dpiContextCreateParams.oracleClientConfigDir` or to set ``PATH``. .. _instwinoh: Local Database or Full Oracle Client ------------------------------------ ODPI-C applications can use Oracle Client 19, 18, 12, or 11.2 libraries from a local Oracle Database or full Oracle Client installation. The Oracle libraries must be either 32-bit or 64-bit, matching your application and ODPI-C library (if one is created separately). To run ODPI-C applications using client libraries from a local Oracle Database (or full Oracle Client) 19, 18, 12, or 11.2 installation: 1. Set the environment variable ``PATH`` to include the path that contains OCI.dll, if it is not already set. For example, on Windows 7, update ``PATH`` in Control Panel -> System -> Advanced System Settings -> Advanced -> Environment Variables -> System Variables -> PATH. Restart any open command prompt windows. 2. Optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml`` can be placed in the ``network/admin`` subdirectory of the Oracle software. Alternatively, Oracle configuration files can be put in another, accessible directory. Then set the member :member:`dpiContextCreateParams.oracleClientConfigDir` when calling :func:`dpiContext_createWithParams()`, or set the environment variable ``TNS_ADMIN`` to that directory name. .. _instmacos: macOS ===== ODPI-C requires Oracle Client libraries, which are found in Oracle Instant Client for macOS. The Instant Client DMG packages are notarized and are recommended for all newer macOS versions. In some future Oracle release, only DMG packages will be available. .. _dmg: Oracle Instant Client DMG Files ------------------------------- Manual or scripted installation of Oracle Instant Client DMG files can be performed. Manual Installation +++++++++++++++++++ * Download the **Basic** or **Basic Light** 64-bit DMG from `Oracle `__. * In Finder, double click on the DMG to mount it. * Open a terminal window and run the install script in the mounted package, for example: .. code-block:: shell /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh This copies the contents to ``$HOME/Downloads/instantclient_19_8``. Applications may not have access to the ``Downloads`` directory, so you should move Instant Client somewhere convenient. * In Finder, eject the mounted Instant Client package. If you have multiple Instant Client DMG packages mounted, you only need to run ``install_ic.sh`` once. It will copy all mounted Instant Client DMG packages at the same time. Scripted Installation +++++++++++++++++++++ Instant Client installation can alternatively be scripted, for example: .. code-block:: shell cd $HOME/Downloads curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg hdiutil mount instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru The Instant Client directory will be ``$HOME/Downloads/instantclient_19_8``. Applications may not have access to the ``Downloads`` directory, so you should move Instant Client somewhere convenient. .. _macoszip: Oracle Instant Client Zip Files ------------------------------- To install Oracle Instant Client zip files: 1. Download the 19, 18, 12, or 11.2 "Basic" or "Basic Light" zip file from `Oracle `__. Choose either a 64-bit or 32-bit package, matching your application architecture. Most applications use 64-bit. 2. Unzip the package into a single directory that is accessible to your application. For example, in Terminal you could unzip: .. code-block:: shell mkdir /opt/oracle cd /opt/oracle unzip /your/path/to/instantclient-basic-macos.x64-19.8.0.0.0dbru.zip Configure Oracle Instant Client ------------------------------- 1. There are several alternative ways to tell your application where your Oracle Instant Client libraries are. * Use the extracted directory for the member :member:`dpiContextCreateParams.oracleClientLibDir` in a call to :func:`dpiContext_createWithParams()` * Alternatively, copy Oracle Instant Client to the directory containing the ODPI-C module binary. For example, if ``libodpic.dylib`` (or your binary containing the ODPI-C code) is in ``~/myprograms`` you can then run ``ln -s ~/Downloads/instantclient_19_8/libclntsh.dylib ~/myprograms``. You can also copy the Instant Client libraries to that directory. * Alternatively, set ``DYLD_LIBRARY_PATH`` to the Instant Client directory. Note this variable does not propagate to sub-shells. * Alternatively, you might decide to compile the ODPI-C library with an RPATH option like ``-Wl,-rpath,/usr/local/lib``. Then you can link Oracle Instant Client to this directory, for example:: ln -s /opt/oracle/instantclient_19_8/libclntsh.dylib /usr/local/lib/ Or, instead of a link you can copy the required OCI libraries. For example:: cp /opt/oracle/instantclient_19_8/{libclntsh.dylib.19.1,libclntshcore.dylib.19.1,libons.dylib,libnnz12.dylib,libociei.dylib} /usr/local/lib/ * Alternatively, on older versions of macOS, you could add a link to ``$HOME/lib`` or ``/usr/local/lib`` to enable applications to find Instant Client. If the ``lib`` sub-directory does not exist, you can create it. For example: .. code-block:: shell mkdir ~/lib ln -s ~/Downloads/instantclient_19_8/libclntsh.dylib ~/lib/ Instead of linking, you can copy the required OCI libraries. For example: .. code-block:: shell mkdir ~/lib cp ~/Downloads/instantclient_19_8/{libclntsh.dylib.19.1,libclntshcore.dylib.19.1,libnnz19.dylib,libociei.dylib} ~/lib/ For Instant Client 11.2, the OCI libraries must be copied. For example: .. code-block:: shell mkdir ~/lib cp ~/Downloads/instantclient_11_2/{libclntsh.dylib.11.1,libnnz11.dylib,libociei.dylib} ~/lib/ 2. If you use optional Oracle configuration files such as ``tnsnames.ora``, ``sqlnet.ora`` or ``oraaccess.xml``, put the files in an accessible directory. Then set the member :member:`dpiContextCreateParams.oracleClientConfigDir` when calling :func:`dpiContext_createWithParams()`. Alternatively, set the environment variable ``TNS_ADMIN`` to that directory name. Alternatively, create a ``network/admin`` subdirectory of Instant Client, if it does not exist. For example:: mkdir -p ~/Downloads/instantclient_19_8/network/admin Put the files in this directory. This is the default Oracle configuration directory for applications linked with this Instant Client. .. _other: Other Platforms =============== To run ODPI-C applications on other platforms (such as Solaris and AIX), follow the same general directions as for Linux Instant Client zip files or Local Database. Add the Oracle libraries to the appropriate library path variable, such as ``LD_LIBRARY_PATH`` on Solaris, or ``LIBPATH`` on AIX. odpi-5.6.4/doc/src/user_guide/introduction.rst000066400000000000000000000011161510466437300214330ustar00rootroot00000000000000.. _introduction: Introduction to ODPI-C ---------------------- Oracle Database Programming Interface for C (ODPI-C) is an open source library of C code that simplifies access to Oracle Database for applications written in C or C++. It is a wrapper over `Oracle Call Interface (OCI) `__ that makes applications and language interfaces easier to develop. ODPI-C supports basic and advanced features of Oracle Database and Oracle Client. A complete list of features can be seen `here `__. odpi-5.6.4/doc/src/user_guide/round_trips.rst000066400000000000000000001060361510466437300212710ustar00rootroot00000000000000.. _round_trips: *************************** ODPI-C Function Round-Trips *************************** The following table identifies if round-trips to the database are required when calling each of the functions that ODPI-C supports. A round-trip is defined as the trip from the Oracle Client libraries (used by ODPI-C) to the database and back. .. list-table-with-summary:: :header-rows: 1 :class: wy-table-responsive :widths: 10 10 30 :summary: The first column displays the function. The second column indicates if round-trips to the database are required. The third column displays the relevant notes. * - Function - Round-Trips? - Notes * - :func:`dpiConn_addRef()` - No - No relevant notes * - :func:`dpiConn_beginSessionlessTransaction` - No - No relevant notes * - :func:`dpiConn_breakExecution()` - Yes - No relevant notes * - :func:`dpiConn_changePassword()` - Yes - No relevant notes * - :func:`dpiConn_close()` - Maybe - If the connection was acquired from a pool, a round-trip is only required if the parameter *mode* is set to the value **DPI_MODE_CONN_CLOSE_DROP**. For standalone connections, a round-trip is always required. If there is an open transaction, a round-trip is also required to perform the implicit rollback that takes place. * - :func:`dpiConn_commit()` - Yes - No relevant notes * - :func:`dpiConn_create()` - Maybe - If a standalone connection is being created, one round-trip is required. If a connection is being acquired from a pool, no round-trips are required if an unused connection is available in the pool; otherwise, a round trip is required for each connection that is added to the pool (see :member:`dpiPoolCreateParams.sessionIncrement`). * - :func:`dpiConn_deqObject()` - Yes - No relevant notes * - :func:`dpiConn_enqObject()` - Yes - No relevant notes * - :func:`dpiConn_getCallTimeout()` - No - No relevant notes * - :func:`dpiConn_getCurrentSchema()` - No - No relevant notes * - :func:`dpiConn_getDbDomain()` - No - No relevant notes * - :func:`dpiConn_getDbName()` - No - No relevant notes * - :func:`dpiConn_getEdition()` - No - No relevant notes * - :func:`dpiConn_getEncodingInfo()` - No - No relevant notes * - :func:`dpiConn_getExternalName()` - No - No relevant notes * - :func:`dpiConn_getHandle()` - No - No relevant notes * - :func:`dpiConn_getInfo()` - No - No relevant notes * - :func:`dpiConn_getInstanceName()` - No - No relevant notes * - :func:`dpiConn_getInternalName()` - No - No relevant notes * - :func:`dpiConn_getIsHealthy()` - No - No relevant notes * - :func:`dpiConn_getLTXID()` - No - No relevant notes * - :func:`dpiConn_getMaxOpenCursors()` - No - No relevant notes * - :func:`dpiConn_getObjectType()` - Maybe - If the type information is already available in the Oracle Client object cache, only one round trip is required; otherwise, two round-trips are required unless the type contains embedded types or is a collection. In that case additional round-trips are required to fetch the additional type information. * - :func:`dpiConn_getOciAttr()` - No - No relevant notes * - :func:`dpiConn_getServerVersion()` - Maybe - The first call when requesting the release string always requires a round-trip. If the release string is not requested and Oracle Client 20.3 or higher is being used, no round-trip is required. Similarly for earlier versions, if the release string is not requested and a pooled connection is used that previously had a call to this function made, no round-trip is required; otherwise, a round-trip is required. Subsequent calls with any client version do not require a round-trip. * - :func:`dpiConn_getServiceName()` - No - No relevant notes * - :func:`dpiConn_getSodaDb()` - Maybe - An internal call to check the server version is made. The notes on the function :func:`dpiConn_getServerVersion()` apply. * - :func:`dpiConn_getStmtCacheSize()` - No - No relevant notes * - :func:`dpiConn_getTransactionInProgress()` - No - No relevant notes * - :func:`dpiConn_newDeqOptions()` - No - No relevant notes * - :func:`dpiConn_newEnqOptions()` - No - No relevant notes * - :func:`dpiConn_newJson()` - No - No relevant notes * - :func:`dpiConn_newJsonQueue()` - No - No relevant notes * - :func:`dpiConn_newMsgProps()` - No - No relevant notes * - :func:`dpiConn_newQueue()` - No - No relevant notes * - :func:`dpiConn_newTempLob()` - Yes - No relevant notes * - :func:`dpiConn_newVar()` - No - No relevant notes * - :func:`dpiConn_newVector()` - No - No relevant notes * - :func:`dpiConn_ping()` - Yes - No relevant notes * - :func:`dpiConn_prepareStmt()` - No - No relevant notes * - :func:`dpiConn_release()` - Maybe - If the number of references exceeds 1 or the connection has already been closed by a call to :func:`dpiConn_close()` then no round-trips are required; otherwise, the connection is closed at this point and the notes on the function :func:`dpiConn_close()` apply. * - :func:`dpiConn_resumeSessionlessTransaction()` - No - No relevant notes * - :func:`dpiConn_rollback()` - Yes - No relevant notes * - :func:`dpiConn_setAction()` - No - No relevant notes * - :func:`dpiConn_setCallTimeout()` - No - No relevant notes * - :func:`dpiConn_setClientIdentifier()` - No - No relevant notes * - :func:`dpiConn_setClientInfo()` - No - No relevant notes * - :func:`dpiConn_setCurrentSchema()` - No - No relevant notes * - :func:`dpiConn_setDbOp()` - No - No relevant notes * - :func:`dpiConn_setEcontextId()` - No - No relevant notes * - :func:`dpiConn_setExternalName()` - No - No relevant notes * - :func:`dpiConn_setInternalName()` - No - No relevant notes * - :func:`dpiConn_setModule()` - No - No relevant notes * - :func:`dpiConn_setOciAttr()` - No - No relevant notes * - :func:`dpiConn_setStmtCacheSize()` - No - No relevant notes * - :func:`dpiConn_shutdownDatabase()` - Yes - No relevant notes * - :func:`dpiConn_startupDatabase()` - Yes - No relevant notes * - :func:`dpiConn_startupDatabaseWithPfile()` - Yes - No relevant notes * - :func:`dpiConn_subscribe()` - Yes - No relevant notes * - :func:`suspendSessionlessTransaction()` - Yes - No relevant notes * - :func:`dpiConn_tpcBegin()` - Yes - No relevant notes * - :func:`dpiConn_tpcCommit()` - Yes - No relevant notes * - :func:`dpiConn_tpcEnd()` - Yes - No relevant notes * - :func:`dpiConn_tpcForget()` - Yes - No relevant notes * - :func:`dpiConn_tpcPrepare()` - Yes - No relevant notes * - :func:`dpiConn_tpcRollback()` - Yes - No relevant notes * - :func:`dpiConn_unsubscribe()` - Yes - No relevant notes * - :func:`dpiContext_createWithParams()` - No - No relevant notes * - :func:`dpiContext_destroy()` - No - No relevant notes * - :func:`dpiContext_freeStringList()` - No - No relevant notes * - :func:`dpiContext_getClientVersion()` - No - No relevant notes * - :func:`dpiContext_getError()` - No - No relevant notes * - :func:`dpiContext_initCommonCreateParams()` - No - No relevant notes * - :func:`dpiContext_initConnCreateParams()` - No - No relevant notes * - :func:`dpiContext_initPoolCreateParams()` - No - No relevant notes * - :func:`dpiContext_initSodaOperOptions()` - No - No relevant notes * - :func:`dpiContext_initSubscrCreateParams()` - No - No relevant notes * - :func:`dpiData_getBool()` - No - No relevant notes * - :func:`dpiData_getBytes()` - No - No relevant notes * - :func:`dpiData_getDouble()` - No - No relevant notes * - :func:`dpiData_getFloat()` - No - No relevant notes * - :func:`dpiData_getInt64()` - No - No relevant notes * - :func:`dpiData_getIntervalDS()` - No - No relevant notes * - :func:`dpiData_getIntervalYM()` - No - No relevant notes * - :func:`dpiData_getIsNull()` - No - No relevant notes * - :func:`dpiData_getJson()` - No - No relevant notes * - :func:`dpiData_getJsonArray()` - No - No relevant notes * - :func:`dpiData_getJsonObject()` - No - No relevant notes * - :func:`dpiData_getLOB()` - No - No relevant notes * - :func:`dpiData_getObject()` - No - No relevant notes * - :func:`dpiData_getStmt()` - No - No relevant notes * - :func:`dpiData_getTimestamp()` - No - No relevant notes * - :func:`dpiData_getUint64()` - No - No relevant notes * - :func:`dpiData_getVector()` - No - No relevant notes * - :func:`dpiData_setBool()` - No - No relevant notes * - :func:`dpiData_setBytes()` - No - No relevant notes * - :func:`dpiData_setDouble()` - No - No relevant notes * - :func:`dpiData_setFloat()` - No - No relevant notes * - :func:`dpiData_setInt64()` - No - No relevant notes * - :func:`dpiData_setIntervalDS()` - No - No relevant notes * - :func:`dpiData_setIntervalYM()` - No - No relevant notes * - :func:`dpiData_setLOB()` - No - No relevant notes * - :func:`dpiData_setNull()` - No - No relevant notes * - :func:`dpiData_setObject()` - No - No relevant notes * - :func:`dpiData_setStmt()` - No - No relevant notes * - :func:`dpiData_setTimestamp()` - No - No relevant notes * - :func:`dpiData_setUint64()` - No - No relevant notes * - :func:`dpiDeqOptions_addRef()` - No - No relevant notes * - :func:`dpiDeqOptions_getCondition()` - No - No relevant notes * - :func:`dpiDeqOptions_getConsumerName()` - No - No relevant notes * - :func:`dpiDeqOptions_getCorrelation()` - No - No relevant notes * - :func:`dpiDeqOptions_getMode()` - No - No relevant notes * - :func:`dpiDeqOptions_getMsgId()` - No - No relevant notes * - :func:`dpiDeqOptions_getNavigation()` - No - No relevant notes * - :func:`dpiDeqOptions_getTransformation()` - No - No relevant notes * - :func:`dpiDeqOptions_getVisibility()` - No - No relevant notes * - :func:`dpiDeqOptions_getWait()` - No - No relevant notes * - :func:`dpiDeqOptions_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiDeqOptions_setCondition()` - No - No relevant notes * - :func:`dpiDeqOptions_setConsumerName()` - No - No relevant notes * - :func:`dpiDeqOptions_setCorrelation()` - No - No relevant notes * - :func:`dpiDeqOptions_setDeliveryMode()` - No - No relevant notes * - :func:`dpiDeqOptions_setMode()` - No - No relevant notes * - :func:`dpiDeqOptions_setMsgId()` - No - No relevant notes * - :func:`dpiDeqOptions_setNavigation()` - No - No relevant notes * - :func:`dpiDeqOptions_setTransformation()` - No - No relevant notes * - :func:`dpiDeqOptions_setVisibility()` - No - No relevant notes * - :func:`dpiDeqOptions_setWait()` - No - No relevant notes * - :func:`dpiEnqOptions_addRef()` - No - No relevant notes * - :func:`dpiEnqOptions_getTransformation()` - No - No relevant notes * - :func:`dpiEnqOptions_getVisibility()` - No - No relevant notes * - :func:`dpiEnqOptions_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiEnqOptions_setDeliveryMode()` - No - No relevant notes * - :func:`dpiEnqOptions_setTransformation()` - No - No relevant notes * - :func:`dpiEnqOptions_setVisibility()` - No - No relevant notes * - :func:`dpiJson_addRef()` - No - No relevant notes * - :func:`dpiJson_getValue()` - Maybe - A round trip is needed if the JSON data has not yet been fetched from the server. * - :func:`dpiJson_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiJson_setFromText()` - No - No relevant notes * - :func:`dpiJson_setValue()` - No - No relevant notes * - :func:`dpiLob_addRef()` - No - No relevant notes * - :func:`dpiLob_close()` - Maybe - If the LOB is a temporary LOB, one round-trip is required to free the temporary LOB; otherwise, no round-trips are required. * - :func:`dpiLob_closeResource()` - Yes - No relevant notes * - :func:`dpiLob_copy()` - Yes - No relevant notes * - :func:`dpiLob_getBufferSize()` - No - No relevant notes * - :func:`dpiLob_getChunkSize()` - Yes - No relevant notes * - :func:`dpiLob_getDirectoryAndFileName()` - No - No relevant notes * - :func:`dpiLob_getFileExists()` - Yes - No relevant notes * - :func:`dpiLob_getIsResourceOpen()` - Yes - No relevant notes * - :func:`dpiLob_getSize()` - Yes - No relevant notes * - :func:`dpiLob_getType()` - No - No relevant notes * - :func:`dpiLob_openResource()` - Yes - No relevant notes * - :func:`dpiLob_readBytes()` - Yes - No relevant notes * - :func:`dpiLob_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiLob_setDirectoryAndFileName()` - No - No relevant notes * - :func:`dpiLob_setFromBytes()` - Yes - No relevant notes * - :func:`dpiLob_trim()` - Yes - No relevant notes * - :func:`dpiLob_writeBytes()` - Yes - No relevant notes * - :func:`dpiMsgProps_addRef()` - No - No relevant notes * - :func:`dpiMsgProps_getCorrelation()` - No - No relevant notes * - :func:`dpiMsgProps_getDelay()` - No - No relevant notes * - :func:`dpiMsgProps_getDeliveryMode()` - No - No relevant notes * - :func:`dpiMsgProps_getEnqTime()` - No - No relevant notes * - :func:`dpiMsgProps_getExceptionQ()` - No - No relevant notes * - :func:`dpiMsgProps_getExpiration()` - No - No relevant notes * - :func:`dpiMsgProps_getMsgId()` - No - No relevant notes * - :func:`dpiMsgProps_getNumAttempts()` - No - No relevant notes * - :func:`dpiMsgProps_getOriginalMsgId()` - No - No relevant notes * - :func:`dpiMsgProps_getPayload()` - No - No relevant notes * - :func:`dpiMsgProps_getPayloadJson()` - No - No relevant notes * - :func:`dpiMsgProps_getPriority()` - No - No relevant notes * - :func:`dpiMsgProps_getState()` - No - No relevant notes * - :func:`dpiMsgProps_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiMsgProps_setCorrelation()` - No - No relevant notes * - :func:`dpiMsgProps_setDelay()` - No - No relevant notes * - :func:`dpiMsgProps_setExceptionQ()` - No - No relevant notes * - :func:`dpiMsgProps_setExpiration()` - No - No relevant notes * - :func:`dpiMsgProps_setOriginalMsgId()` - No - No relevant notes * - :func:`dpiMsgProps_setPayloadBytes()` - No - No relevant notes * - :func:`dpiMsgProps_setPayloadJson()` - No - No relevant notes * - :func:`dpiMsgProps_setPayloadObject()` - No - No relevant notes * - :func:`dpiMsgProps_setPriority()` - No - No relevant notes * - :func:`dpiMsgProps_setRecipients()` - No - No relevant notes * - :func:`dpiObject_addRef()` - No - No relevant notes * - :func:`dpiObject_appendElement()` - No - No relevant notes * - :func:`dpiObject_copy()` - No - No relevant notes * - :func:`dpiObject_deleteElementByIndex()` - No - No relevant notes * - :func:`dpiObject_getAttributeValue()` - No - No relevant notes * - :func:`dpiObject_getElementExistsByIndex()` - No - No relevant notes * - :func:`dpiObject_getElementValueByIndex()` - No - No relevant notes * - :func:`dpiObject_getFirstIndex()` - No - No relevant notes * - :func:`dpiObject_getLastIndex()` - No - No relevant notes * - :func:`dpiObject_getNextIndex()` - No - No relevant notes * - :func:`dpiObject_getPrevIndex()` - No - No relevant notes * - :func:`dpiObject_getSize()` - No - No relevant notes * - :func:`dpiObject_release()` - Maybe - No round trips are required unless the last reference is being released, the internal reference to the object type is the last reference being released and the object type's internal reference to the connection is the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiObject_setAttributeValue()` - No - No relevant notes * - :func:`dpiObject_setElementValueByIndex()` - No - No relevant notes * - :func:`dpiObject_trim()` - No - No relevant notes * - :func:`dpiObjectAttr_addRef()` - No - No relevant notes * - :func:`dpiObjectAttr_getInfo()` - No - No relevant notes * - :func:`dpiObjectAttr_release()` - Maybe - No round trips are required unless the last reference is being released, the internal reference to the object type is the last reference being released and the object type's internal reference to the connection is the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiObjectType_addRef()` - No - No relevant notes * - :func:`dpiObjectType_createObject()` - No - No relevant notes * - :func:`dpiObjectType_getAttributes()` - No - No relevant notes * - :func:`dpiObjectType_getInfo()` - No - No relevant notes * - :func:`dpiObjectType_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiPool_acquireConnection()` - Maybe - No round-trips are required if an unused connection is available in the pool; otherwise, a round trip is required for each connection that is added to the pool (see :member:`dpiPoolCreateParams.sessionIncrement`). A round-trip may also be required if a PL/SQL fixup callback is specified (see :member:`dpiPoolCreateParams.plsqlFixupCallback`). * - :func:`dpiPool_addRef()` - No - No relevant notes * - :func:`dpiPool_close()` - Maybe - One round trip is required for each session in the pool that needs to be closed. * - :func:`dpiPool_create()` - Maybe - One round trip is required for each session that is initially added to the pool (see :member:`dpiPoolCreateParams.minSessions`). * - :func:`dpiPool_getBusyCount()` - No - No relevant notes * - :func:`dpiPool_getEncodingInfo()` - No - No relevant notes * - :func:`dpiPool_getGetMode()` - No - No relevant notes * - :func:`dpiPool_getMaxLifetimeSession()` - No - No relevant notes * - :func:`dpiPool_getMaxSessionsPerShard()` - No - No relevant notes * - :func:`dpiPool_getOpenCount()` - No - No relevant notes * - :func:`dpiPool_getPingInterval()` - No - No relevant notes * - :func:`dpiPool_getSodaMetadataCache()` - No - No relevant notes * - :func:`dpiPool_getStmtCacheSize()` - No - No relevant notes * - :func:`dpiPool_getTimeout()` - No - No relevant notes * - :func:`dpiPool_getWaitTimeout()` - No - No relevant notes * - :func:`dpiPool_reconfigure()` - Maybe - If the minimum size of the pool is not being increased, no round-trips are required; otherwise, round-trips are required for each session in the pool that needs to be added to reach the new minimum. * - :func:`dpiPool_release()` - Maybe - If the number of references exceeds 1 or the pool has already been closed by a call to :func:`dpiPool_close()` then no round-trips are required; otherwise, the pool is closed at this point and the notes on the function :func:`dpiPool_close()` apply. * - :func:`dpiPool_setAccessToken()` - No - No relevant notes * - :func:`dpiPool_setGetMode()` - No - No relevant notes * - :func:`dpiPool_setMaxLifetimeSession()` - No - No relevant notes * - :func:`dpiPool_setMaxSessionsPerShard()` - No - No relevant notes * - :func:`dpiPool_setPingInterval()` - No - No relevant notes * - :func:`dpiPool_setSodaMetadataCache()` - No - No relevant notes * - :func:`dpiPool_setStmtCacheSize()` - No - No relevant notes * - :func:`dpiPool_setTimeout()` - No - No relevant notes * - :func:`dpiPool_setWaitTimeout()` - No - No relevant notes * - :func:`dpiQueue_addRef()` - No - No relevant notes * - :func:`dpiQueue_deqMany()` - Yes - No relevant notes * - :func:`dpiQueue_deqOne()` - Yes - No relevant notes * - :func:`dpiQueue_enqMany()` - Yes - No relevant notes * - :func:`dpiQueue_enqOne()` - Yes - No relevant notes * - :func:`dpiQueue_getDeqOptions()` - No - No relevant notes * - :func:`dpiQueue_getEnqOptions()` - No - No relevant notes * - :func:`dpiQueue_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiRowid_addRef()` - No - No relevant notes * - :func:`dpiRowid_getStringValue()` - No - No relevant notes * - :func:`dpiRowid_release()` - No - No relevant notes * - :func:`dpiSodaColl_addRef()` - No - No relevant notes * - :func:`dpiSodaColl_createIndex()` - Yes - No relevant notes * - :func:`dpiSodaColl_drop()` - Yes - No relevant notes * - :func:`dpiSodaColl_dropIndex()` - Yes - No relevant notes * - :func:`dpiSodaColl_find()` - Yes - No relevant notes * - :func:`dpiSodaColl_findOne()` - Yes - No relevant notes * - :func:`dpiSodaColl_getDataGuide()` - Yes - No relevant notes * - :func:`dpiSodaColl_getDocCount()` - Yes - No relevant notes * - :func:`dpiSodaColl_getMetadata()` - No - No relevant notes * - :func:`dpiSodaColl_getName()` - No - No relevant notes * - :func:`dpiSodaColl_insertMany()` - Yes - No relevant notes * - :func:`dpiSodaColl_insertManyWithOptions()` - Yes - No relevant notes * - :func:`dpiSodaColl_insertOne()` - Yes - No relevant notes * - :func:`dpiSodaColl_insertOneWithOptions()` - Yes - No relevant notes * - :func:`dpiSodaColl_listIndexes()` - Yes - No relevant notes * - :func:`dpiSodaColl_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiSodaColl_remove()` - Yes - No relevant notes * - :func:`dpiSodaColl_replaceOne()` - Yes - No relevant notes * - :func:`dpiSodaColl_save()` - Yes - No relevant notes * - :func:`dpiSodaColl_saveWithOptions()` - Yes - No relevant notes * - :func:`dpiSodaColl_truncate()` - Yes - No relevant notes * - :func:`dpiSodaCollCursor_addRef()` - No - No relevant notes * - :func:`dpiSodaCollCursor_close()` - No - No relevant notes * - :func:`dpiSodaCollCursor_getNext()` - Yes - No relevant notes * - :func:`dpiSodaCollCursor_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiSodaDb_addRef()` - No - No relevant notes * - :func:`dpiSodaDb_createCollection()` - Maybe - If the SODA metadata cache has been enabled and no metadata has been specified, a round trip is not required after the first time that a collection with a particular name is opened. * - :func:`dpiSodaDb_createDocument()` - No - No relevant notes * - :func:`dpiSodaDb_createJsonDocument()` - No - No relevant notes * - :func:`dpiSodaDb_getCollections()` - Yes - No relevant notes * - :func:`dpiSodaDb_getCollectionNames()` - Yes - No relevant notes * - :func:`dpiSodaDb_openCollection()` - Maybe - If the SODA metadata cache has been enabled, a round trip is not required after the first time that a collection with a particular name is opened. * - :func:`dpiSodaDb_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiSodaDoc_addRef()` - No - No relevant notes * - :func:`dpiSodaDoc_getContent()` - No - No relevant notes * - :func:`dpiSodaDoc_getCreatedOn()` - No - No relevant notes * - :func:`dpiSodaDoc_getIsJson()` - No - No relevant notes * - :func:`dpiSodaDoc_getJsonContent()` - No - No relevant notes * - :func:`dpiSodaDoc_getKey()` - No - No relevant notes * - :func:`dpiSodaDoc_getLastModified()` - No - No relevant notes * - :func:`dpiSodaDoc_getMediaType()` - No - No relevant notes * - :func:`dpiSodaDoc_getVersion()` - No - No relevant notes * - :func:`dpiSodaDoc_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiSodaDocCursor_addRef()` - No - No relevant notes * - :func:`dpiSodaDocCursor_close()` - No - No relevant notes * - :func:`dpiSodaDocCursor_getNext()` - Yes - No relevant notes * - :func:`dpiSodaDocCursor_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiStmt_addRef()` - No - No relevant notes * - :func:`dpiStmt_bindByName()` - No - No relevant notes * - :func:`dpiStmt_bindByPos()` - No - No relevant notes * - :func:`dpiStmt_bindValueByName()` - No - No relevant notes * - :func:`dpiStmt_bindValueByPos()` - No - No relevant notes * - :func:`dpiStmt_close()` - No - No relevant notes * - :func:`dpiStmt_define()` - No - No relevant notes * - :func:`dpiStmt_defineValue()` - No - No relevant notes * - :func:`dpiStmt_deleteFromCache()` - No - No relevant notes * - :func:`dpiStmt_execute()` - Yes - No relevant notes * - :func:`dpiStmt_executeMany()` - Yes - No relevant notes * - :func:`dpiStmt_fetch()` - Maybe - An internal array of rows corresponding to the value set by a call to :func:`dpiStmt_setFetchArraySize()` is maintained. A round trip is only required when this array has been exhausted and new rows are required to be fetched from the database. * - :func:`dpiStmt_fetchRows()` - Maybe - An internal array of rows corresponding to the value set by a call to :func:`dpiStmt_setFetchArraySize()` is maintained. If any rows exist in this array, no round trip is required; otherwise, a round trip is required. * - :func:`dpiStmt_getBatchErrorCount()` - No - No relevant notes * - :func:`dpiStmt_getBatchErrors()` - No - No relevant notes * - :func:`dpiStmt_getBindCount()` - No - No relevant notes * - :func:`dpiStmt_getBindNames()` - No - No relevant notes * - :func:`dpiStmt_getFetchArraySize()` - No - No relevant notes * - :func:`dpiStmt_getImplicitResult()` - No - No relevant notes * - :func:`dpiStmt_getInfo()` - No - No relevant notes * - :func:`dpiStmt_getLastRowid()` - No - No relevant notes * - :func:`dpiStmt_getNumQueryColumns()` - No - No relevant notes * - :func:`dpiStmt_getOciAttr()` - No - No relevant notes * - :func:`dpiStmt_getPrefetchRows()` - No - No relevant notes * - :func:`dpiStmt_getQueryInfo()` - No - No relevant notes * - :func:`dpiStmt_getQueryValue()` - No - No relevant notes * - :func:`dpiStmt_getRowCount()` - No - No relevant notes * - :func:`dpiStmt_getRowCounts()` - No - No relevant notes * - :func:`dpiStmt_getSubscrQueryId()` - No - No relevant notes * - :func:`dpiStmt_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiStmt_scroll()` - Yes - No relevant notes * - :func:`dpiStmt_setFetchArraySize()` - No - No relevant notes * - :func:`dpiStmt_setOciAttr()` - No - No relevant notes * - :func:`dpiStmt_setPrefetchRows()` - No - No relevant notes * - :func:`dpiSubscr_addRef()` - No - No relevant notes * - :func:`dpiSubscr_prepareStmt()` - No - No relevant notes * - :func:`dpiSubscr_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiVar_addRef()` - No - No relevant notes * - :func:`dpiVar_copyData()` - No - No relevant notes * - :func:`dpiVar_getNumElementsInArray()` - No - No relevant notes * - :func:`dpiVar_getReturnedData()` - No - No relevant notes * - :func:`dpiVar_getSizeInBytes()` - No - No relevant notes * - :func:`dpiVar_release()` - Maybe - No round trips are required unless the last reference is being released and the internal reference to the connection is also the last reference to that connection. In that case, the notes on the function :func:`dpiConn_release()` apply. * - :func:`dpiVar_setFromBytes()` - Maybe - If the variable refers to a LOB, one round-trip is required; otherwise, no round trips are required. * - :func:`dpiVar_setFromJson()` - No - No relevant notes * - :func:`dpiVar_setFromLob()` - No - No relevant notes * - :func:`dpiVar_setFromObject()` - No - No relevant notes * - :func:`dpiVar_setFromRowid()` - No - No relevant notes * - :func:`dpiVar_setFromStmt()` - No - No relevant notes * - :func:`dpiVar_setFromVector()` - No - No relevant notes * - :func:`dpiVar_setNumElementsInArray()` - No - No relevant notes * - :func:`dpiVector_addRef()` - No - No relevant notes * - :func:`dpiVector_getValue()` - No - No relevant notes * - :func:`dpiVector_release()` - No - No relevant notes * - :func:`dpiVector_setValue()` - No - No relevant notes odpi-5.6.4/embed/000077500000000000000000000000001510466437300135465ustar00rootroot00000000000000odpi-5.6.4/embed/README.md000066400000000000000000000003501510466437300150230ustar00rootroot00000000000000This directory contains the file dpi.c which can be used to embed ODPI-C within your project without having to manage the individual files that make up the library. The files can also be compiled independently if that is preferred. odpi-5.6.4/embed/dpi.c000066400000000000000000000051111510466437300144640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpi.c // Include this file in your project in order to embed ODPI-C source without // having to compile files individually. Only the definitions in the file // include/dpi.h are intended to be used publicly. Each file can also be // compiled independently if that is preferable. //----------------------------------------------------------------------------- #include "../src/dpiConn.c" #include "../src/dpiContext.c" #include "../src/dpiData.c" #include "../src/dpiDebug.c" #include "../src/dpiDeqOptions.c" #include "../src/dpiEnqOptions.c" #include "../src/dpiEnv.c" #include "../src/dpiError.c" #include "../src/dpiGen.c" #include "../src/dpiGlobal.c" #include "../src/dpiHandleList.c" #include "../src/dpiHandlePool.c" #include "../src/dpiJson.c" #include "../src/dpiLob.c" #include "../src/dpiMsgProps.c" #include "../src/dpiObjectAttr.c" #include "../src/dpiObject.c" #include "../src/dpiObjectType.c" #include "../src/dpiOci.c" #include "../src/dpiOracleType.c" #include "../src/dpiPool.c" #include "../src/dpiQueue.c" #include "../src/dpiRowid.c" #include "../src/dpiSodaColl.c" #include "../src/dpiSodaCollCursor.c" #include "../src/dpiSodaDb.c" #include "../src/dpiSodaDoc.c" #include "../src/dpiSodaDocCursor.c" #include "../src/dpiStmt.c" #include "../src/dpiStringList.c" #include "../src/dpiSubscr.c" #include "../src/dpiUtils.c" #include "../src/dpiVar.c" #include "../src/dpiVector.c" odpi-5.6.4/include/000077500000000000000000000000001510466437300141155ustar00rootroot00000000000000odpi-5.6.4/include/dpi.h000066400000000000000000002553261510466437300150570ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpi.h // Include file for users of the ODPI-C library. //----------------------------------------------------------------------------- #ifndef DPI_PUBLIC #define DPI_PUBLIC // Avoid name-mangling when using C++ #ifdef __cplusplus extern "C" { #endif // define standard integer types for older versions of Microsoft Visual Studio #ifdef _MSC_VER #if _MSC_VER < 1600 #define int8_t signed __int8 #define int16_t signed __int16 #define int32_t signed __int32 #define int64_t signed __int64 #define uint8_t unsigned __int8 #define uint16_t unsigned __int16 #define uint32_t unsigned __int32 #define uint64_t unsigned __int64 #endif #endif #ifndef int8_t #include #endif // define __func__ for older versions of Microsoft Visual Studio #ifdef _MSC_VER #if _MSC_VER < 1900 #define __func__ __FUNCTION__ #endif #endif // define macro for exporting functions on Windows #if defined(_MSC_VER) && defined(DPI_EXPORTS) #define DPI_EXPORT __declspec(dllexport) #else #define DPI_EXPORT #endif // define ODPI-C version information #define DPI_MAJOR_VERSION 5 #define DPI_MINOR_VERSION 6 #define DPI_PATCH_LEVEL 4 #define DPI_VERSION_SUFFIX #define DPI_STR_HELPER(x) #x #define DPI_STR(x) DPI_STR_HELPER(x) #define DPI_VERSION_STRING \ DPI_STR(DPI_MAJOR_VERSION) "." \ DPI_STR(DPI_MINOR_VERSION) "." \ DPI_STR(DPI_PATCH_LEVEL) \ DPI_VERSION_SUFFIX #define DPI_DEFAULT_DRIVER_NAME "ODPI-C : " DPI_VERSION_STRING #define DPI_VERSION_TO_NUMBER(major, minor, patch) \ ((major * 10000) + (minor * 100) + patch) #define DPI_VERSION_NUMBER \ DPI_VERSION_TO_NUMBER(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, \ DPI_PATCH_LEVEL) #define DPI_ORACLE_VERSION_TO_NUMBER(versionNum, releaseNum, updateNum, \ portReleaseNum, portUpdateNum) \ ((versionNum * 100000000) + (releaseNum * 1000000) + \ (updateNum * 10000) + (portReleaseNum * 100) + (portUpdateNum)) // define default array size to use #define DPI_DEFAULT_FETCH_ARRAY_SIZE 100 // define default number of rows to prefetch #define DPI_DEFAULT_PREFETCH_ROWS 2 // define default ping interval (in seconds) used when getting connections #define DPI_DEFAULT_PING_INTERVAL 60 // define default ping timeout (in milliseconds) used when getting connections #define DPI_DEFAULT_PING_TIMEOUT 5000 // define default statement cache size #define DPI_DEFAULT_STMT_CACHE_SIZE 20 // define constants for dequeue wait (AQ) #define DPI_DEQ_WAIT_NO_WAIT 0 #define DPI_DEQ_WAIT_FOREVER ((uint32_t) -1) // define maximum precision that can be supported by an int64_t value #define DPI_MAX_INT64_PRECISION 18 // define constants for success and failure of methods #define DPI_SUCCESS 0 #define DPI_FAILURE -1 // set debug level (DPI_DEBUG_LEVEL) as a bitmask of desired flags // reporting is to stderr // 0x0001: reports errors during free // 0x0002: reports on reference count changes // 0x0004: reports on public function calls // 0x0008: reports on all errors // 0x0010: reports on all SQL statements // 0x0020: reports on all memory allocations/frees // 0x0040: reports on all attempts to load the Oracle Client library #define DPI_DEBUG_LEVEL_UNREPORTED_ERRORS 0x0001 #define DPI_DEBUG_LEVEL_REFS 0x0002 #define DPI_DEBUG_LEVEL_FNS 0x0004 #define DPI_DEBUG_LEVEL_ERRORS 0x0008 #define DPI_DEBUG_LEVEL_SQL 0x0010 #define DPI_DEBUG_LEVEL_MEM 0x0020 #define DPI_DEBUG_LEVEL_LOAD_LIB 0x0040 //----------------------------------------------------------------------------- // Enumerations //----------------------------------------------------------------------------- // connection/pool authorization modes typedef uint32_t dpiAuthMode; #define DPI_MODE_AUTH_DEFAULT 0x00000000 #define DPI_MODE_AUTH_SYSDBA 0x00000002 #define DPI_MODE_AUTH_SYSOPER 0x00000004 #define DPI_MODE_AUTH_PRELIM 0x00000008 #define DPI_MODE_AUTH_SYSASM 0x00008000 #define DPI_MODE_AUTH_SYSBKP 0x00020000 #define DPI_MODE_AUTH_SYSDGD 0x00040000 #define DPI_MODE_AUTH_SYSKMT 0x00080000 #define DPI_MODE_AUTH_SYSRAC 0x00100000 // connection close modes typedef uint32_t dpiConnCloseMode; #define DPI_MODE_CONN_CLOSE_DEFAULT 0x0000 #define DPI_MODE_CONN_CLOSE_DROP 0x0001 #define DPI_MODE_CONN_CLOSE_RETAG 0x0002 // connection/pool creation modes typedef uint32_t dpiCreateMode; #define DPI_MODE_CREATE_DEFAULT 0x00000000 #define DPI_MODE_CREATE_THREADED 0x00000001 #define DPI_MODE_CREATE_EVENTS 0x00000004 // dequeue modes for advanced queuing typedef uint32_t dpiDeqMode; #define DPI_MODE_DEQ_BROWSE 1 #define DPI_MODE_DEQ_LOCKED 2 #define DPI_MODE_DEQ_REMOVE 3 #define DPI_MODE_DEQ_REMOVE_NO_DATA 4 // dequeue navigation flags for advanced queuing typedef uint32_t dpiDeqNavigation; #define DPI_DEQ_NAV_FIRST_MSG 1 #define DPI_DEQ_NAV_NEXT_TRANSACTION 2 #define DPI_DEQ_NAV_NEXT_MSG 3 // event types typedef uint32_t dpiEventType; #define DPI_EVENT_NONE 0 #define DPI_EVENT_STARTUP 1 #define DPI_EVENT_SHUTDOWN 2 #define DPI_EVENT_SHUTDOWN_ANY 3 #define DPI_EVENT_DEREG 5 #define DPI_EVENT_OBJCHANGE 6 #define DPI_EVENT_QUERYCHANGE 7 #define DPI_EVENT_AQ 100 // JSON conversion options #define DPI_JSON_OPT_DEFAULT 0x00 #define DPI_JSON_OPT_NUMBER_AS_STRING 0x01 #define DPI_JSON_OPT_DATE_AS_DOUBLE 0x02 // statement execution modes typedef uint32_t dpiExecMode; #define DPI_MODE_EXEC_DEFAULT 0x00000000 #define DPI_MODE_EXEC_SUSPEND_ON_SUCCESS 0x00000004 #define DPI_MODE_EXEC_DESCRIBE_ONLY 0x00000010 #define DPI_MODE_EXEC_COMMIT_ON_SUCCESS 0x00000020 #define DPI_MODE_EXEC_BATCH_ERRORS 0x00000080 #define DPI_MODE_EXEC_PARSE_ONLY 0x00000100 #define DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS 0x00100000 // statement fetch modes typedef uint16_t dpiFetchMode; #define DPI_MODE_FETCH_NEXT 0x0002 #define DPI_MODE_FETCH_FIRST 0x0004 #define DPI_MODE_FETCH_LAST 0x0008 #define DPI_MODE_FETCH_PRIOR 0x0010 #define DPI_MODE_FETCH_ABSOLUTE 0x0020 #define DPI_MODE_FETCH_RELATIVE 0x0040 // message delivery modes in advanced queuing typedef uint16_t dpiMessageDeliveryMode; #define DPI_MODE_MSG_PERSISTENT 1 #define DPI_MODE_MSG_BUFFERED 2 #define DPI_MODE_MSG_PERSISTENT_OR_BUFFERED 3 // message states in advanced queuing typedef uint32_t dpiMessageState; #define DPI_MSG_STATE_READY 0 #define DPI_MSG_STATE_WAITING 1 #define DPI_MSG_STATE_PROCESSED 2 #define DPI_MSG_STATE_EXPIRED 3 // native C types typedef uint32_t dpiNativeTypeNum; #define DPI_NATIVE_TYPE_INT64 3000 #define DPI_NATIVE_TYPE_UINT64 3001 #define DPI_NATIVE_TYPE_FLOAT 3002 #define DPI_NATIVE_TYPE_DOUBLE 3003 #define DPI_NATIVE_TYPE_BYTES 3004 #define DPI_NATIVE_TYPE_TIMESTAMP 3005 #define DPI_NATIVE_TYPE_INTERVAL_DS 3006 #define DPI_NATIVE_TYPE_INTERVAL_YM 3007 #define DPI_NATIVE_TYPE_LOB 3008 #define DPI_NATIVE_TYPE_OBJECT 3009 #define DPI_NATIVE_TYPE_STMT 3010 #define DPI_NATIVE_TYPE_BOOLEAN 3011 #define DPI_NATIVE_TYPE_ROWID 3012 #define DPI_NATIVE_TYPE_JSON 3013 #define DPI_NATIVE_TYPE_JSON_OBJECT 3014 #define DPI_NATIVE_TYPE_JSON_ARRAY 3015 #define DPI_NATIVE_TYPE_NULL 3016 #define DPI_NATIVE_TYPE_VECTOR 3017 // operation codes (database change and continuous query notification) typedef uint32_t dpiOpCode; #define DPI_OPCODE_ALL_OPS 0x0 #define DPI_OPCODE_ALL_ROWS 0x1 #define DPI_OPCODE_INSERT 0x2 #define DPI_OPCODE_UPDATE 0x4 #define DPI_OPCODE_DELETE 0x8 #define DPI_OPCODE_ALTER 0x10 #define DPI_OPCODE_DROP 0x20 #define DPI_OPCODE_UNKNOWN 0x40 // Oracle types typedef uint32_t dpiOracleTypeNum; #define DPI_ORACLE_TYPE_NONE 2000 #define DPI_ORACLE_TYPE_VARCHAR 2001 #define DPI_ORACLE_TYPE_NVARCHAR 2002 #define DPI_ORACLE_TYPE_CHAR 2003 #define DPI_ORACLE_TYPE_NCHAR 2004 #define DPI_ORACLE_TYPE_ROWID 2005 #define DPI_ORACLE_TYPE_RAW 2006 #define DPI_ORACLE_TYPE_NATIVE_FLOAT 2007 #define DPI_ORACLE_TYPE_NATIVE_DOUBLE 2008 #define DPI_ORACLE_TYPE_NATIVE_INT 2009 #define DPI_ORACLE_TYPE_NUMBER 2010 #define DPI_ORACLE_TYPE_DATE 2011 #define DPI_ORACLE_TYPE_TIMESTAMP 2012 #define DPI_ORACLE_TYPE_TIMESTAMP_TZ 2013 #define DPI_ORACLE_TYPE_TIMESTAMP_LTZ 2014 #define DPI_ORACLE_TYPE_INTERVAL_DS 2015 #define DPI_ORACLE_TYPE_INTERVAL_YM 2016 #define DPI_ORACLE_TYPE_CLOB 2017 #define DPI_ORACLE_TYPE_NCLOB 2018 #define DPI_ORACLE_TYPE_BLOB 2019 #define DPI_ORACLE_TYPE_BFILE 2020 #define DPI_ORACLE_TYPE_STMT 2021 #define DPI_ORACLE_TYPE_BOOLEAN 2022 #define DPI_ORACLE_TYPE_OBJECT 2023 #define DPI_ORACLE_TYPE_LONG_VARCHAR 2024 #define DPI_ORACLE_TYPE_LONG_RAW 2025 #define DPI_ORACLE_TYPE_NATIVE_UINT 2026 #define DPI_ORACLE_TYPE_JSON 2027 #define DPI_ORACLE_TYPE_JSON_OBJECT 2028 #define DPI_ORACLE_TYPE_JSON_ARRAY 2029 #define DPI_ORACLE_TYPE_UROWID 2030 #define DPI_ORACLE_TYPE_LONG_NVARCHAR 2031 #define DPI_ORACLE_TYPE_XMLTYPE 2032 #define DPI_ORACLE_TYPE_VECTOR 2033 #define DPI_ORACLE_TYPE_JSON_ID 2034 #define DPI_ORACLE_TYPE_MAX 2035 // session pool close modes typedef uint32_t dpiPoolCloseMode; #define DPI_MODE_POOL_CLOSE_DEFAULT 0x0000 #define DPI_MODE_POOL_CLOSE_FORCE 0x0001 // modes used when acquiring a connection from a session pool typedef uint8_t dpiPoolGetMode; #define DPI_MODE_POOL_GET_WAIT 0 #define DPI_MODE_POOL_GET_NOWAIT 1 #define DPI_MODE_POOL_GET_FORCEGET 2 #define DPI_MODE_POOL_GET_TIMEDWAIT 3 // purity values when acquiring a connection from a pool typedef uint32_t dpiPurity; #define DPI_PURITY_DEFAULT 0 #define DPI_PURITY_NEW 1 #define DPI_PURITY_SELF 2 // database shutdown modes typedef uint32_t dpiShutdownMode; #define DPI_MODE_SHUTDOWN_DEFAULT 0 #define DPI_MODE_SHUTDOWN_TRANSACTIONAL 1 #define DPI_MODE_SHUTDOWN_TRANSACTIONAL_LOCAL 2 #define DPI_MODE_SHUTDOWN_IMMEDIATE 3 #define DPI_MODE_SHUTDOWN_ABORT 4 #define DPI_MODE_SHUTDOWN_FINAL 5 // SODA flags #define DPI_SODA_FLAGS_DEFAULT 0x00 #define DPI_SODA_FLAGS_ATOMIC_COMMIT 0x01 #define DPI_SODA_FLAGS_CREATE_COLL_MAP 0x02 #define DPI_SODA_FLAGS_INDEX_DROP_FORCE 0x04 // database startup modes typedef uint32_t dpiStartupMode; #define DPI_MODE_STARTUP_DEFAULT 0 #define DPI_MODE_STARTUP_FORCE 1 #define DPI_MODE_STARTUP_RESTRICT 2 // server types typedef uint8_t dpiServerType; #define DPI_SERVER_TYPE_UNKNOWN 0 #define DPI_SERVER_TYPE_DEDICATED 1 #define DPI_SERVER_TYPE_SHARED 2 #define DPI_SERVER_TYPE_POOLED 4 // statement types typedef uint16_t dpiStatementType; #define DPI_STMT_TYPE_UNKNOWN 0 #define DPI_STMT_TYPE_SELECT 1 #define DPI_STMT_TYPE_UPDATE 2 #define DPI_STMT_TYPE_DELETE 3 #define DPI_STMT_TYPE_INSERT 4 #define DPI_STMT_TYPE_CREATE 5 #define DPI_STMT_TYPE_DROP 6 #define DPI_STMT_TYPE_ALTER 7 #define DPI_STMT_TYPE_BEGIN 8 #define DPI_STMT_TYPE_DECLARE 9 #define DPI_STMT_TYPE_CALL 10 #define DPI_STMT_TYPE_EXPLAIN_PLAN 15 #define DPI_STMT_TYPE_MERGE 16 #define DPI_STMT_TYPE_ROLLBACK 17 #define DPI_STMT_TYPE_COMMIT 21 // subscription grouping classes typedef uint8_t dpiSubscrGroupingClass; #define DPI_SUBSCR_GROUPING_CLASS_TIME 1 // subscription grouping types typedef uint8_t dpiSubscrGroupingType; #define DPI_SUBSCR_GROUPING_TYPE_SUMMARY 1 #define DPI_SUBSCR_GROUPING_TYPE_LAST 2 // subscription namespaces typedef uint32_t dpiSubscrNamespace; #define DPI_SUBSCR_NAMESPACE_AQ 1 #define DPI_SUBSCR_NAMESPACE_DBCHANGE 2 // subscription protocols typedef uint32_t dpiSubscrProtocol; #define DPI_SUBSCR_PROTO_CALLBACK 0 #define DPI_SUBSCR_PROTO_MAIL 1 #define DPI_SUBSCR_PROTO_PLSQL 2 #define DPI_SUBSCR_PROTO_HTTP 3 // subscription quality of service typedef uint32_t dpiSubscrQOS; #define DPI_SUBSCR_QOS_RELIABLE 0x01 #define DPI_SUBSCR_QOS_DEREG_NFY 0x02 #define DPI_SUBSCR_QOS_ROWIDS 0x04 #define DPI_SUBSCR_QOS_QUERY 0x08 #define DPI_SUBSCR_QOS_BEST_EFFORT 0x10 // two-phase commit (flags for dpiConn_tpcBegin()) typedef uint32_t dpiTpcBeginFlags; #define DPI_TPC_BEGIN_JOIN 0x00000002 #define DPI_TPC_BEGIN_NEW 0x00000001 #define DPI_TPC_BEGIN_PROMOTE 0x00000008 #define DPI_TPC_BEGIN_RESUME 0x00000004 // two-phase commit (flags for dpiConn_tpcEnd()) typedef uint32_t dpiTpcEndFlags; #define DPI_TPC_END_NORMAL 0 #define DPI_TPC_END_SUSPEND 0x00100000 // vector flags typedef uint8_t dpiVectorFlags; #define DPI_VECTOR_FLAGS_FLEXIBLE_DIM 0x01 #define DPI_VECTOR_FLAGS_SPARSE 0x02 // vector formats typedef uint8_t dpiVectorFormat; #define DPI_VECTOR_FORMAT_FLOAT32 2 #define DPI_VECTOR_FORMAT_FLOAT64 3 #define DPI_VECTOR_FORMAT_INT8 4 #define DPI_VECTOR_FORMAT_BINARY 5 // visibility of messages in advanced queuing typedef uint32_t dpiVisibility; #define DPI_VISIBILITY_IMMEDIATE 1 #define DPI_VISIBILITY_ON_COMMIT 2 //----------------------------------------------------------------------------- // Handle Types //----------------------------------------------------------------------------- typedef struct dpiConn dpiConn; typedef struct dpiContext dpiContext; typedef struct dpiDeqOptions dpiDeqOptions; typedef struct dpiEnqOptions dpiEnqOptions; typedef struct dpiJson dpiJson; typedef struct dpiLob dpiLob; typedef struct dpiMsgProps dpiMsgProps; typedef struct dpiObject dpiObject; typedef struct dpiObjectAttr dpiObjectAttr; typedef struct dpiObjectType dpiObjectType; typedef struct dpiPool dpiPool; typedef struct dpiQueue dpiQueue; typedef struct dpiRowid dpiRowid; typedef struct dpiSodaColl dpiSodaColl; typedef struct dpiSodaCollCursor dpiSodaCollCursor; typedef struct dpiSodaDb dpiSodaDb; typedef struct dpiSodaDoc dpiSodaDoc; typedef struct dpiSodaDocCursor dpiSodaDocCursor; typedef struct dpiStmt dpiStmt; typedef struct dpiSubscr dpiSubscr; typedef struct dpiVar dpiVar; typedef struct dpiVector dpiVector; //----------------------------------------------------------------------------- // Forward Declarations of Other Types //----------------------------------------------------------------------------- typedef struct dpiAccessToken dpiAccessToken; typedef struct dpiAnnotation dpiAnnotation; typedef struct dpiAppContext dpiAppContext; typedef struct dpiCommonCreateParams dpiCommonCreateParams; typedef struct dpiConnCreateParams dpiConnCreateParams; typedef struct dpiConnInfo dpiConnInfo; typedef struct dpiContextCreateParams dpiContextCreateParams; typedef struct dpiData dpiData; typedef union dpiDataBuffer dpiDataBuffer; typedef struct dpiDataTypeInfo dpiDataTypeInfo; typedef struct dpiEncodingInfo dpiEncodingInfo; typedef struct dpiErrorInfo dpiErrorInfo; typedef struct dpiJsonNode dpiJsonNode; typedef struct dpiMsgRecipient dpiMsgRecipient; typedef struct dpiObjectAttrInfo dpiObjectAttrInfo; typedef struct dpiObjectTypeInfo dpiObjectTypeInfo; typedef struct dpiPoolCreateParams dpiPoolCreateParams; typedef struct dpiQueryInfo dpiQueryInfo; typedef struct dpiSessionlessTransactionId dpiSessionlessTransactionId; typedef struct dpiShardingKeyColumn dpiShardingKeyColumn; typedef struct dpiStringList dpiSodaCollNames; typedef struct dpiSodaOperOptions dpiSodaOperOptions; typedef struct dpiStmtInfo dpiStmtInfo; typedef struct dpiStringList dpiStringList; typedef struct dpiSubscrCreateParams dpiSubscrCreateParams; typedef struct dpiSubscrMessage dpiSubscrMessage; typedef struct dpiSubscrMessageQuery dpiSubscrMessageQuery; typedef struct dpiSubscrMessageRow dpiSubscrMessageRow; typedef struct dpiSubscrMessageTable dpiSubscrMessageTable; typedef struct dpiVectorInfo dpiVectorInfo; typedef union dpiVectorDimensionBuffer dpiVectorDimensionBuffer; typedef struct dpiVersionInfo dpiVersionInfo; typedef struct dpiXid dpiXid; //----------------------------------------------------------------------------- // Declaration for function pointers //----------------------------------------------------------------------------- typedef int (*dpiAccessTokenCallback)(void *context, dpiAccessToken *accessToken); //----------------------------------------------------------------------------- // Complex Native Data Types (used for transferring data to/from ODPI-C) //----------------------------------------------------------------------------- // structure used for transferring byte strings to/from ODPI-C typedef struct { char *ptr; uint32_t length; const char *encoding; } dpiBytes; // structure used for transferring day/seconds intervals to/from ODPI-C typedef struct { int32_t days; int32_t hours; int32_t minutes; int32_t seconds; int32_t fseconds; } dpiIntervalDS; // structure used for transferring years/months intervals to/from ODPI-C typedef struct { int32_t years; int32_t months; } dpiIntervalYM; // structure used for transferring JSON nodes to/from ODPI-C struct dpiJsonNode { dpiOracleTypeNum oracleTypeNum; dpiNativeTypeNum nativeTypeNum; dpiDataBuffer *value; }; // structure used for transferring JSON object values to/from ODPI-C typedef struct { uint32_t numFields; char **fieldNames; uint32_t *fieldNameLengths; dpiJsonNode *fields; dpiDataBuffer *fieldValues; } dpiJsonObject; // structure used for transferring JSON array values to/from ODPI-C typedef struct { uint32_t numElements; dpiJsonNode *elements; dpiDataBuffer *elementValues; } dpiJsonArray; // structure used for transferring dates to/from ODPI-C typedef struct { int16_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; uint32_t fsecond; int8_t tzHourOffset; int8_t tzMinuteOffset; } dpiTimestamp; //----------------------------------------------------------------------------- // Other Types //----------------------------------------------------------------------------- // union used for providing a buffer of any data type union dpiDataBuffer { int asBoolean; uint8_t asUint8; uint16_t asUint16; uint32_t asUint32; int64_t asInt64; uint64_t asUint64; float asFloat; double asDouble; char *asString; void *asRaw; dpiBytes asBytes; dpiTimestamp asTimestamp; dpiIntervalDS asIntervalDS; dpiIntervalYM asIntervalYM; dpiJson *asJson; dpiJsonObject asJsonObject; dpiJsonArray asJsonArray; dpiLob *asLOB; dpiObject *asObject; dpiStmt *asStmt; dpiRowid *asRowid; dpiVector *asVector; }; // structure used for annotations struct dpiAnnotation { const char *key; uint32_t keyLength; const char *value; uint32_t valueLength; }; // structure used for application context struct dpiAppContext { const char *namespaceName; uint32_t namespaceNameLength; const char *name; uint32_t nameLength; const char *value; uint32_t valueLength; }; // structure used for common parameters used for creating standalone // connections and session pools struct dpiCommonCreateParams { dpiCreateMode createMode; const char *encoding; const char *nencoding; const char *edition; uint32_t editionLength; const char *driverName; uint32_t driverNameLength; int sodaMetadataCache; uint32_t stmtCacheSize; dpiAccessToken *accessToken; }; // structure used for creating connections struct dpiConnCreateParams { dpiAuthMode authMode; const char *connectionClass; uint32_t connectionClassLength; dpiPurity purity; const char *newPassword; uint32_t newPasswordLength; dpiAppContext *appContext; uint32_t numAppContext; int externalAuth; void *externalHandle; dpiPool *pool; const char *tag; uint32_t tagLength; int matchAnyTag; const char *outTag; uint32_t outTagLength; int outTagFound; dpiShardingKeyColumn *shardingKeyColumns; uint8_t numShardingKeyColumns; dpiShardingKeyColumn *superShardingKeyColumns; uint8_t numSuperShardingKeyColumns; int outNewSession; }; // structure used for transferring connection information from ODPI-C struct dpiConnInfo { const char *dbDomain; uint32_t dbDomainLength; const char *dbName; uint32_t dbNameLength; const char *instanceName; uint32_t instanceNameLength; const char *serviceName; uint32_t serviceNameLength; uint32_t maxIdentifierLength; uint32_t maxOpenCursors; uint8_t serverType; }; // structure used for creating a context struct dpiContextCreateParams { const char *defaultDriverName; const char *defaultEncoding; const char *loadErrorUrl; const char *oracleClientLibDir; const char *oracleClientConfigDir; int sodaUseJsonDesc; int useJsonId; }; // structure used for transferring data to/from ODPI-C struct dpiData { int isNull; dpiDataBuffer value; }; // structure used for providing metadata about data types struct dpiDataTypeInfo { dpiOracleTypeNum oracleTypeNum; dpiNativeTypeNum defaultNativeTypeNum; uint16_t ociTypeCode; uint32_t dbSizeInBytes; uint32_t clientSizeInBytes; uint32_t sizeInChars; int16_t precision; int8_t scale; uint8_t fsPrecision; dpiObjectType *objectType; int isJson; const char *domainSchema; uint32_t domainSchemaLength; const char *domainName; uint32_t domainNameLength; uint32_t numAnnotations; dpiAnnotation *annotations; int isOson; uint32_t vectorDimensions; uint8_t vectorFormat; uint8_t vectorFlags; }; // structure used for storing token authentication data struct dpiAccessToken { const char *token; uint32_t tokenLength; const char *privateKey; uint32_t privateKeyLength; }; // structure used for transferring encoding information from ODPI-C struct dpiEncodingInfo { const char *encoding; int32_t maxBytesPerCharacter; const char *nencoding; int32_t nmaxBytesPerCharacter; }; // structure used for transferring error information from ODPI-C struct dpiErrorInfo { int32_t code; uint16_t offset16; const char *message; uint32_t messageLength; const char *encoding; const char *fnName; const char *action; const char *sqlState; int isRecoverable; int isWarning; uint32_t offset; }; // structure used for transferring object attribute information from ODPI-C struct dpiObjectAttrInfo { const char *name; uint32_t nameLength; dpiDataTypeInfo typeInfo; }; // structure used for transferring object type information from ODPI-C struct dpiObjectTypeInfo { const char *schema; uint32_t schemaLength; const char *name; uint32_t nameLength; int isCollection; dpiDataTypeInfo elementTypeInfo; uint16_t numAttributes; const char *packageName; uint32_t packageNameLength; }; // structure used for creating pools struct dpiPoolCreateParams { uint32_t minSessions; uint32_t maxSessions; uint32_t sessionIncrement; int pingInterval; int pingTimeout; int homogeneous; int externalAuth; dpiPoolGetMode getMode; const char *outPoolName; uint32_t outPoolNameLength; uint32_t timeout; uint32_t waitTimeout; uint32_t maxLifetimeSession; const char *plsqlFixupCallback; uint32_t plsqlFixupCallbackLength; uint32_t maxSessionsPerShard; dpiAccessTokenCallback accessTokenCallback; void *accessTokenCallbackContext; }; // structure used for transferring query metadata from ODPI-C struct dpiQueryInfo { const char *name; uint32_t nameLength; dpiDataTypeInfo typeInfo; int nullOk; }; // structure used for recipients list struct dpiMsgRecipient { const char *name; uint32_t nameLength; }; // structure used for storing sessionless transaction ids struct dpiSessionlessTransactionId { char value[64]; uint32_t length; }; // structure used for sharding key columns struct dpiShardingKeyColumn { dpiOracleTypeNum oracleTypeNum; dpiNativeTypeNum nativeTypeNum; dpiDataBuffer value; }; // structure used for getting an array of strings from the database; the unions // are for aliases for the names used when the structure was called // dpiSodaCollNames instead struct dpiStringList { union { uint32_t numStrings; uint32_t numNames; }; union { const char **strings; const char **names; }; union { uint32_t *stringLengths; uint32_t *nameLengths; }; }; // structure used for SODA operations (find/replace/remove) struct dpiSodaOperOptions { uint32_t numKeys; const char **keys; uint32_t *keyLengths; const char *key; uint32_t keyLength; const char *version; uint32_t versionLength; const char *filter; uint32_t filterLength; uint32_t skip; uint32_t limit; uint32_t fetchArraySize; const char *hint; uint32_t hintLength; int lock; }; // structure used for transferring statement information from ODPI-C struct dpiStmtInfo { int isQuery; int isPLSQL; int isDDL; int isDML; dpiStatementType statementType; int isReturning; char *sqlId; uint32_t sqlIdLength; }; // callback for subscriptions typedef void (*dpiSubscrCallback)(void* context, dpiSubscrMessage *message); // structure used for creating subscriptions struct dpiSubscrCreateParams { dpiSubscrNamespace subscrNamespace; dpiSubscrProtocol protocol; dpiSubscrQOS qos; dpiOpCode operations; uint32_t portNumber; uint32_t timeout; const char *name; uint32_t nameLength; dpiSubscrCallback callback; void *callbackContext; const char *recipientName; uint32_t recipientNameLength; const char *ipAddress; uint32_t ipAddressLength; uint8_t groupingClass; uint32_t groupingValue; uint8_t groupingType; uint64_t outRegId; int clientInitiated; }; // structure used for transferring messages in subscription callbacks struct dpiSubscrMessage { dpiEventType eventType; const char *dbName; uint32_t dbNameLength; dpiSubscrMessageTable *tables; uint32_t numTables; dpiSubscrMessageQuery *queries; uint32_t numQueries; dpiErrorInfo *errorInfo; const void *txId; uint32_t txIdLength; int registered; const char *queueName; uint32_t queueNameLength; const char *consumerName; uint32_t consumerNameLength; const void *aqMsgId; uint32_t aqMsgIdLength; }; // structure used for transferring query information in messages in // subscription callbacks (continuous query notification) struct dpiSubscrMessageQuery { uint64_t id; dpiOpCode operation; dpiSubscrMessageTable *tables; uint32_t numTables; }; // structure used for transferring row information in messages in // subscription callbacks struct dpiSubscrMessageRow { dpiOpCode operation; const char *rowid; uint32_t rowidLength; }; // structure used for transferring table information in messages in // subscription callbacks struct dpiSubscrMessageTable { dpiOpCode operation; const char *name; uint32_t nameLength; dpiSubscrMessageRow *rows; uint32_t numRows; }; // structure used for transferring version information struct dpiVersionInfo { int versionNum; int releaseNum; int updateNum; int portReleaseNum; int portUpdateNum; uint32_t fullVersionNum; }; // union used for providing a buffer for vector dimensions union dpiVectorDimensionBuffer { void* asPtr; int8_t* asInt8; float* asFloat; double* asDouble; }; // structure used for transferring vector information struct dpiVectorInfo { uint8_t format; uint32_t numDimensions; uint8_t dimensionSize; dpiVectorDimensionBuffer dimensions; uint32_t numSparseValues; uint32_t *sparseIndices; }; // structure used for defining two-phase commit transaction ids (XIDs) struct dpiXid { long formatId; const char *globalTransactionId; uint32_t globalTransactionIdLength; const char *branchQualifier; uint32_t branchQualifierLength; }; //----------------------------------------------------------------------------- // Context Methods (dpiContext) //----------------------------------------------------------------------------- // define macro for backwards compatibility #define dpiContext_create(majorVersion, minorVersion, context, errorInfo) \ dpiContext_createWithParams(majorVersion, minorVersion, NULL, context, \ errorInfo) // create a context handle and validate the version information (with params) DPI_EXPORT int dpiContext_createWithParams(unsigned int majorVersion, unsigned int minorVersion, dpiContextCreateParams *params, dpiContext **context, dpiErrorInfo *errorInfo); // destroy context handle DPI_EXPORT int dpiContext_destroy(dpiContext *context); // free string list contents DPI_EXPORT int dpiContext_freeStringList(dpiContext *context, dpiStringList *list); // return the OCI client version in use DPI_EXPORT int dpiContext_getClientVersion(const dpiContext *context, dpiVersionInfo *versionInfo); // get error information DPI_EXPORT void dpiContext_getError(const dpiContext *context, dpiErrorInfo *errorInfo); // initialize context parameters to default values DPI_EXPORT int dpiContext_initCommonCreateParams(const dpiContext *context, dpiCommonCreateParams *params); // initialize connection create parameters to default values DPI_EXPORT int dpiContext_initConnCreateParams(const dpiContext *context, dpiConnCreateParams *params); // initialize pool create parameters to default values DPI_EXPORT int dpiContext_initPoolCreateParams(const dpiContext *context, dpiPoolCreateParams *params); // initialize SODA operation options to default values DPI_EXPORT int dpiContext_initSodaOperOptions(const dpiContext *context, dpiSodaOperOptions *options); // initialize subscription create parameters to default values DPI_EXPORT int dpiContext_initSubscrCreateParams(const dpiContext *context, dpiSubscrCreateParams *params); //----------------------------------------------------------------------------- // Connection Methods (dpiConn) //----------------------------------------------------------------------------- // add a reference to a connection DPI_EXPORT int dpiConn_addRef(dpiConn *conn); // break execution of the statement running on the connection DPI_EXPORT int dpiConn_breakExecution(dpiConn *conn); // change the password for the specified user DPI_EXPORT int dpiConn_changePassword(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *oldPassword, uint32_t oldPasswordLength, const char *newPassword, uint32_t newPasswordLength); // close the connection now, not when the reference count reaches zero DPI_EXPORT int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag, uint32_t tagLength); // commits the current active transaction DPI_EXPORT int dpiConn_commit(dpiConn *conn); // create a connection and return a reference to it DPI_EXPORT int dpiConn_create(const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiConn **conn); // dequeue a message from a queue DPI_EXPORT int dpiConn_deqObject(dpiConn *conn, const char *queueName, uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props, dpiObject *payload, const char **msgId, uint32_t *msgIdLength); // enqueue a message to a queue DPI_EXPORT int dpiConn_enqObject(dpiConn *conn, const char *queueName, uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props, dpiObject *payload, const char **msgId, uint32_t *msgIdLength); // get call timeout in place for round-trips with this connection DPI_EXPORT int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value); // get current schema associated with the connection DPI_EXPORT int dpiConn_getCurrentSchema(dpiConn *conn, const char **value, uint32_t *valueLength); // get database domain name DPI_EXPORT int dpiConn_getDbDomain(dpiConn *conn, const char **value, uint32_t *valueLength); // get database name DPI_EXPORT int dpiConn_getDbName(dpiConn *conn, const char **value, uint32_t *valueLength); // get edition associated with the connection DPI_EXPORT int dpiConn_getEdition(dpiConn *conn, const char **value, uint32_t *valueLength); // return the encoding information used by the connection DPI_EXPORT int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info); // get external name associated with the connection DPI_EXPORT int dpiConn_getExternalName(dpiConn *conn, const char **value, uint32_t *valueLength); // get the OCI service context handle associated with the connection DPI_EXPORT int dpiConn_getHandle(dpiConn *conn, void **handle); // return information about the connection DPI_EXPORT int dpiConn_getInfo(dpiConn *conn, dpiConnInfo *info); // get instance name associated with the connection DPI_EXPORT int dpiConn_getInstanceName(dpiConn *conn, const char **value, uint32_t *valueLength); // get internal name associated with the connection DPI_EXPORT int dpiConn_getInternalName(dpiConn *conn, const char **value, uint32_t *valueLength); // get the health of a connection DPI_EXPORT int dpiConn_getIsHealthy(dpiConn *conn, int *isHealthy); // get logical transaction id associated with the connection DPI_EXPORT int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength); // get the maximum number of open cursors allowed by the database DPI_EXPORT int dpiConn_getMaxOpenCursors(dpiConn *conn, uint32_t *maxOpenCursors); // create a new object type and return it for subsequent object creation DPI_EXPORT int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength, dpiObjectType **objType); // generic method for getting an OCI connection attribute // WARNING: use only as directed by Oracle DPI_EXPORT int dpiConn_getOciAttr(dpiConn *conn, uint32_t handleType, uint32_t attribute, dpiDataBuffer *value, uint32_t *valueLength); // return information about the server version in use DPI_EXPORT int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString, uint32_t *releaseStringLength, dpiVersionInfo *versionInfo); // get the service name used to connect to the database DPI_EXPORT int dpiConn_getServiceName(dpiConn *conn, const char **value, uint32_t *valueLength); // get SODA interface object DPI_EXPORT int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db); // return the statement cache size DPI_EXPORT int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize); // get whether or not a transaction is in progress DPI_EXPORT int dpiConn_getTransactionInProgress(dpiConn *conn, int *txnInProgress); // create a new dequeue options object and return it DPI_EXPORT int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options); // create a new enqueue options object and return it DPI_EXPORT int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options); // create a new, empty JSON DPI_EXPORT int dpiConn_newJson(dpiConn *conn, dpiJson **json); // create a new AQ queue with JSON payload DPI_EXPORT int dpiConn_newJsonQueue(dpiConn *conn, const char *name, uint32_t nameLength, dpiQueue **queue); // create a new message properties object and return it DPI_EXPORT int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props); // create a new AQ queue DPI_EXPORT int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength, dpiObjectType *payloadType, dpiQueue **queue); // create a new temporary LOB DPI_EXPORT int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob); // create a new variable and return it for subsequent binding/defining DPI_EXPORT int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, dpiData **data); // create a new vector DPI_EXPORT int dpiConn_newVector(dpiConn *conn, dpiVectorInfo *info, dpiVector **vector); // ping the connection to see if it is still alive DPI_EXPORT int dpiConn_ping(dpiConn *conn); // prepare a statement and return it for subsequent execution/fetching DPI_EXPORT int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql, uint32_t sqlLength, const char *tag, uint32_t tagLength, dpiStmt **stmt); // release a reference to the connection DPI_EXPORT int dpiConn_release(dpiConn *conn); // rolls back the current active transaction DPI_EXPORT int dpiConn_rollback(dpiConn *conn); // set action associated with the connection DPI_EXPORT int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength); // set call timeout for subsequent round-trips with this connection DPI_EXPORT int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value); // set client identifier associated with the connection DPI_EXPORT int dpiConn_setClientIdentifier(dpiConn *conn, const char *value, uint32_t valueLength); // set client info associated with the connection DPI_EXPORT int dpiConn_setClientInfo(dpiConn *conn, const char *value, uint32_t valueLength); // set current schema associated with the connection DPI_EXPORT int dpiConn_setCurrentSchema(dpiConn *conn, const char *value, uint32_t valueLength); // set database operation associated with the connection DPI_EXPORT int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength); // set execution context id associated with the connection DPI_EXPORT int dpiConn_setEcontextId(dpiConn *conn, const char *value, uint32_t valueLength); // set external name associated with the connection DPI_EXPORT int dpiConn_setExternalName(dpiConn *conn, const char *value, uint32_t valueLength); // set internal name associated with the connection DPI_EXPORT int dpiConn_setInternalName(dpiConn *conn, const char *value, uint32_t valueLength); // set module associated with the connection DPI_EXPORT int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength); // generic method for setting an OCI connection attribute // WARNING: use only as directed by Oracle DPI_EXPORT int dpiConn_setOciAttr(dpiConn *conn, uint32_t handleType, uint32_t attribute, void *value, uint32_t valueLength); // set the statement cache size DPI_EXPORT int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize); // shutdown the database DPI_EXPORT int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode); // startup the database DPI_EXPORT int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode); // startup the database with a PFILE DPI_EXPORT int dpiConn_startupDatabaseWithPfile(dpiConn *conn, const char *pfile, uint32_t pfileLength, dpiStartupMode mode); // subscribe to events in the database DPI_EXPORT int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params, dpiSubscr **subscr); // begin a TPC (two-phase commit) transaction DPI_EXPORT int dpiConn_tpcBegin(dpiConn *conn, dpiXid *xid, uint32_t transactionTimeout, uint32_t flags); // commit a TPC (two-phase commit) transaction DPI_EXPORT int dpiConn_tpcCommit(dpiConn *conn, dpiXid *xid, int onePhase); // end (detach from) a TPC (two-phase commit) transaction DPI_EXPORT int dpiConn_tpcEnd(dpiConn *conn, dpiXid *xid, uint32_t flags); // forget a TPC (two-phase commit) transaction DPI_EXPORT int dpiConn_tpcForget(dpiConn *conn, dpiXid *xid); // prepare a TPC (two-phase commit) transaction for commit DPI_EXPORT int dpiConn_tpcPrepare(dpiConn *conn, dpiXid *xid, int *commitNeeded); // rollback a TPC (two-phase commit) transaction DPI_EXPORT int dpiConn_tpcRollback(dpiConn *conn, dpiXid *xid); // unsubscribe from events in the database DPI_EXPORT int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr); // start a sessionless transaction DPI_EXPORT int dpiConn_beginSessionlessTransaction(dpiConn *conn, dpiSessionlessTransactionId* transactionId, uint32_t timeout, int deferRoundTrip); // resume a sessionless transaction DPI_EXPORT int dpiConn_resumeSessionlessTransaction(dpiConn *conn, dpiSessionlessTransactionId* transactionId, uint32_t timeout, int deferRoundTrip); // suspend a sessionless transaction DPI_EXPORT int dpiConn_suspendSessionlessTransaction(dpiConn *conn); //----------------------------------------------------------------------------- // Data Methods (dpiData) //----------------------------------------------------------------------------- // return the boolean portion of the data DPI_EXPORT int dpiData_getBool(dpiData *data); // return the bytes portion of the data DPI_EXPORT dpiBytes *dpiData_getBytes(dpiData *data); // return the double portion of the data DPI_EXPORT double dpiData_getDouble(dpiData *data); // return the float portion of the data DPI_EXPORT float dpiData_getFloat(dpiData *data); // return the integer portion of the data DPI_EXPORT int64_t dpiData_getInt64(dpiData *data); // return the interval (days/seconds) portion of the data DPI_EXPORT dpiIntervalDS *dpiData_getIntervalDS(dpiData *data); // return the interval (years/months) portion of the data DPI_EXPORT dpiIntervalYM *dpiData_getIntervalYM(dpiData *data); // return whether data value is null or not DPI_EXPORT int dpiData_getIsNull(dpiData *data); // return the JSON portion of the data DPI_EXPORT dpiJson *dpiData_getJson(dpiData *data); // return the JSON Array portion of the data DPI_EXPORT dpiJsonArray *dpiData_getJsonArray(dpiData *data); // return the JSON Object portion of the data DPI_EXPORT dpiJsonObject *dpiData_getJsonObject(dpiData *data); // return the LOB portion of the data DPI_EXPORT dpiLob *dpiData_getLOB(dpiData *data); // return the object portion of the data DPI_EXPORT dpiObject *dpiData_getObject(dpiData *data); // return the statement portion of the data DPI_EXPORT dpiStmt *dpiData_getStmt(dpiData *data); // return the timestamp portion of the data DPI_EXPORT dpiTimestamp *dpiData_getTimestamp(dpiData *data); // return the unsigned integer portion of the data DPI_EXPORT uint64_t dpiData_getUint64(dpiData *data); // return the VECTOR portion of the data DPI_EXPORT dpiVector *dpiData_getVector(dpiData *data); // set the boolean portion of the data DPI_EXPORT void dpiData_setBool(dpiData *data, int value); // set the bytes portion of the data DPI_EXPORT void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length); // set the double portion of the data DPI_EXPORT void dpiData_setDouble(dpiData *data, double value); // set the float portion of the data DPI_EXPORT void dpiData_setFloat(dpiData *data, float value); // set the integer portion of the data DPI_EXPORT void dpiData_setInt64(dpiData *data, int64_t value); // set the interval (days/seconds) portion of the data DPI_EXPORT void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours, int32_t minutes, int32_t seconds, int32_t fseconds); // set the interval (years/months) portion of the data DPI_EXPORT void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months); // set the LOB portion of the data DPI_EXPORT void dpiData_setLOB(dpiData *data, dpiLob *lob); // set data to the null value DPI_EXPORT void dpiData_setNull(dpiData *data); // set the object portion of the data DPI_EXPORT void dpiData_setObject(dpiData *data, dpiObject *obj); // set the statement portion of the data DPI_EXPORT void dpiData_setStmt(dpiData *data, dpiStmt *stmt); // set the timestamp portion of the data DPI_EXPORT void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset); // set the unsigned integer portion of the data DPI_EXPORT void dpiData_setUint64(dpiData *data, uint64_t value); //----------------------------------------------------------------------------- // Dequeue Option Methods (dpiDeqOptions) //----------------------------------------------------------------------------- // add a reference to dequeue options DPI_EXPORT int dpiDeqOptions_addRef(dpiDeqOptions *options); // return condition associated with dequeue options DPI_EXPORT int dpiDeqOptions_getCondition(dpiDeqOptions *options, const char **value, uint32_t *valueLength); // return consumer name associated with dequeue options DPI_EXPORT int dpiDeqOptions_getConsumerName(dpiDeqOptions *options, const char **value, uint32_t *valueLength); // return correlation associated with dequeue options DPI_EXPORT int dpiDeqOptions_getCorrelation(dpiDeqOptions *options, const char **value, uint32_t *valueLength); // return mode associated with dequeue options DPI_EXPORT int dpiDeqOptions_getMode(dpiDeqOptions *options, dpiDeqMode *value); // return message id associated with dequeue options DPI_EXPORT int dpiDeqOptions_getMsgId(dpiDeqOptions *options, const char **value, uint32_t *valueLength); // return navigation associated with dequeue options DPI_EXPORT int dpiDeqOptions_getNavigation(dpiDeqOptions *options, dpiDeqNavigation *value); // return transformation associated with dequeue options DPI_EXPORT int dpiDeqOptions_getTransformation(dpiDeqOptions *options, const char **value, uint32_t *valueLength); // return visibility associated with dequeue options DPI_EXPORT int dpiDeqOptions_getVisibility(dpiDeqOptions *options, dpiVisibility *value); // return wait time associated with dequeue options DPI_EXPORT int dpiDeqOptions_getWait(dpiDeqOptions *options, uint32_t *value); // release a reference from dequeue options DPI_EXPORT int dpiDeqOptions_release(dpiDeqOptions *options); // set condition associated with dequeue options DPI_EXPORT int dpiDeqOptions_setCondition(dpiDeqOptions *options, const char *value, uint32_t valueLength); // set consumer name associated with dequeue options DPI_EXPORT int dpiDeqOptions_setConsumerName(dpiDeqOptions *options, const char *value, uint32_t valueLength); // set correlation associated with dequeue options DPI_EXPORT int dpiDeqOptions_setCorrelation(dpiDeqOptions *options, const char *value, uint32_t valueLength); // set delivery mode associated with dequeue options DPI_EXPORT int dpiDeqOptions_setDeliveryMode(dpiDeqOptions *options, dpiMessageDeliveryMode value); // set mode associated with dequeue options DPI_EXPORT int dpiDeqOptions_setMode(dpiDeqOptions *options, dpiDeqMode value); // set message id associated with dequeue options DPI_EXPORT int dpiDeqOptions_setMsgId(dpiDeqOptions *options, const char *value, uint32_t valueLength); // set navigation associated with dequeue options DPI_EXPORT int dpiDeqOptions_setNavigation(dpiDeqOptions *options, dpiDeqNavigation value); // set transformation associated with dequeue options DPI_EXPORT int dpiDeqOptions_setTransformation(dpiDeqOptions *options, const char *value, uint32_t valueLength); // set visibility associated with dequeue options DPI_EXPORT int dpiDeqOptions_setVisibility(dpiDeqOptions *options, dpiVisibility value); // set wait time associated with dequeue options DPI_EXPORT int dpiDeqOptions_setWait(dpiDeqOptions *options, uint32_t value); //----------------------------------------------------------------------------- // Enqueue Option Methods (dpiEnqOptions) //----------------------------------------------------------------------------- // add a reference to enqueue options DPI_EXPORT int dpiEnqOptions_addRef(dpiEnqOptions *options); // return transformation associated with enqueue options DPI_EXPORT int dpiEnqOptions_getTransformation(dpiEnqOptions *options, const char **value, uint32_t *valueLength); // return visibility associated with enqueue options DPI_EXPORT int dpiEnqOptions_getVisibility(dpiEnqOptions *options, dpiVisibility *value); // release a reference from enqueue options DPI_EXPORT int dpiEnqOptions_release(dpiEnqOptions *options); // set delivery mode associated with enqueue options DPI_EXPORT int dpiEnqOptions_setDeliveryMode(dpiEnqOptions *options, dpiMessageDeliveryMode value); // set transformation associated with enqueue options DPI_EXPORT int dpiEnqOptions_setTransformation(dpiEnqOptions *options, const char *value, uint32_t valueLength); // set visibility associated with enqueue options DPI_EXPORT int dpiEnqOptions_setVisibility(dpiEnqOptions *options, dpiVisibility value); //----------------------------------------------------------------------------- // JSON Methods (dpiJson) //----------------------------------------------------------------------------- // add a reference to the JSON DPI_EXPORT int dpiJson_addRef(dpiJson *json); // return the value of the JSON object, as a hierarchy of nodes DPI_EXPORT int dpiJson_getValue(dpiJson *json, uint32_t options, dpiJsonNode **topNode); // release a reference to the JSON DPI_EXPORT int dpiJson_release(dpiJson *json); // parse textual JSON into JSON handle DPI_EXPORT int dpiJson_setFromText(dpiJson *json, const char *value, uint64_t valueLength, uint32_t flags); // set the value of the JSON object, given a hierarchy of nodes DPI_EXPORT int dpiJson_setValue(dpiJson *json, dpiJsonNode *topNode); //----------------------------------------------------------------------------- // LOB Methods (dpiLob) //----------------------------------------------------------------------------- // add a reference to the LOB DPI_EXPORT int dpiLob_addRef(dpiLob *lob); // close the LOB DPI_EXPORT int dpiLob_close(dpiLob *lob); // close the LOB's resources DPI_EXPORT int dpiLob_closeResource(dpiLob *lob); // create a copy of the LOB DPI_EXPORT int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob); // get buffer size in bytes for a LOB DPI_EXPORT int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars, uint64_t *sizeInBytes); // return the chunk size for the LOB DPI_EXPORT int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size); // return the directory alias name and file name of a BFILE LOB DPI_EXPORT int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias, uint32_t *directoryAliasLength, const char **fileName, uint32_t *fileNameLength); // return if the file associated with a BFILE LOB exists DPI_EXPORT int dpiLob_getFileExists(dpiLob *lob, int *exists); // return if the LOB's resources are currently open DPI_EXPORT int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen); // return the current size of the LOB DPI_EXPORT int dpiLob_getSize(dpiLob *lob, uint64_t *size); // return the type of the LOB DPI_EXPORT int dpiLob_getType(dpiLob *lob, dpiOracleTypeNum *type); // open the LOB's resources (used to improve performance of multiple // read/writes operations) DPI_EXPORT int dpiLob_openResource(dpiLob *lob); // read bytes from the LOB at the specified offset DPI_EXPORT int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, char *value, uint64_t *valueLength); // release a reference to the LOB DPI_EXPORT int dpiLob_release(dpiLob *lob); // set the directory name and file name of the BFILE LOB DPI_EXPORT int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias, uint32_t directoryAliasLength, const char *fileName, uint32_t fileNameLength); // sets the contents of a LOB from a byte string DPI_EXPORT int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength); // trim the LOB to the specified size DPI_EXPORT int dpiLob_trim(dpiLob *lob, uint64_t newSize); // write bytes to the LOB at the specified offset DPI_EXPORT int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value, uint64_t valueLength); //----------------------------------------------------------------------------- // Message Properties Methods (dpiMsgProps) //----------------------------------------------------------------------------- // add a reference to message properties DPI_EXPORT int dpiMsgProps_addRef(dpiMsgProps *props); // return the number of attempts made to deliver the message DPI_EXPORT int dpiMsgProps_getNumAttempts(dpiMsgProps *props, int32_t *value); // return correlation associated with the message DPI_EXPORT int dpiMsgProps_getCorrelation(dpiMsgProps *props, const char **value, uint32_t *valueLength); // return the number of seconds the message was delayed DPI_EXPORT int dpiMsgProps_getDelay(dpiMsgProps *props, int32_t *value); // return the mode used for delivering the message DPI_EXPORT int dpiMsgProps_getDeliveryMode(dpiMsgProps *props, dpiMessageDeliveryMode *value); // return the time the message was enqueued DPI_EXPORT int dpiMsgProps_getEnqTime(dpiMsgProps *props, dpiTimestamp *value); // return the name of the exception queue associated with the message DPI_EXPORT int dpiMsgProps_getExceptionQ(dpiMsgProps *props, const char **value, uint32_t *valueLength); // return the number of seconds until the message expires DPI_EXPORT int dpiMsgProps_getExpiration(dpiMsgProps *props, int32_t *value); // return the message id for the message (after enqueuing or dequeuing) DPI_EXPORT int dpiMsgProps_getMsgId(dpiMsgProps *props, const char **value, uint32_t *valueLength); // return the original message id for the message DPI_EXPORT int dpiMsgProps_getOriginalMsgId(dpiMsgProps *props, const char **value, uint32_t *valueLength); // return the payload of the message (object or bytes) DPI_EXPORT int dpiMsgProps_getPayload(dpiMsgProps *props, dpiObject **obj, const char **value, uint32_t *valueLength); // return the payload of the message (JSON) DPI_EXPORT int dpiMsgProps_getPayloadJson(dpiMsgProps *props, dpiJson **json); // return the priority of the message DPI_EXPORT int dpiMsgProps_getPriority(dpiMsgProps *props, int32_t *value); // return the state of the message DPI_EXPORT int dpiMsgProps_getState(dpiMsgProps *props, dpiMessageState *value); // release a reference from message properties DPI_EXPORT int dpiMsgProps_release(dpiMsgProps *props); // set correlation associated with the message DPI_EXPORT int dpiMsgProps_setCorrelation(dpiMsgProps *props, const char *value, uint32_t valueLength); // set the number of seconds to delay the message DPI_EXPORT int dpiMsgProps_setDelay(dpiMsgProps *props, int32_t value); // set the name of the exception queue associated with the message DPI_EXPORT int dpiMsgProps_setExceptionQ(dpiMsgProps *props, const char *value, uint32_t valueLength); // set the number of seconds until the message expires DPI_EXPORT int dpiMsgProps_setExpiration(dpiMsgProps *props, int32_t value); // set the original message id for the message DPI_EXPORT int dpiMsgProps_setOriginalMsgId(dpiMsgProps *props, const char *value, uint32_t valueLength); // set the payload of the message (as a series of bytes) DPI_EXPORT int dpiMsgProps_setPayloadBytes(dpiMsgProps *props, const char *value, uint32_t valueLength); // set the payload of the message (as JSON) DPI_EXPORT int dpiMsgProps_setPayloadJson(dpiMsgProps *props, dpiJson *json); // set the payload of the message (as an object) DPI_EXPORT int dpiMsgProps_setPayloadObject(dpiMsgProps *props, dpiObject *obj); // set the priority of the message DPI_EXPORT int dpiMsgProps_setPriority(dpiMsgProps *props, int32_t value); // set recipients associated with the message DPI_EXPORT int dpiMsgProps_setRecipients(dpiMsgProps *props, dpiMsgRecipient *recipients, uint32_t numRecipients); //----------------------------------------------------------------------------- // Object Methods (dpiObject) //----------------------------------------------------------------------------- // add a reference to the object DPI_EXPORT int dpiObject_addRef(dpiObject *obj); // append an element to the collection DPI_EXPORT int dpiObject_appendElement(dpiObject *obj, dpiNativeTypeNum nativeTypeNum, dpiData *value); // copy the object and return the copied object DPI_EXPORT int dpiObject_copy(dpiObject *obj, dpiObject **copiedObj); // delete an element from the collection DPI_EXPORT int dpiObject_deleteElementByIndex(dpiObject *obj, int32_t index); // get the value of the specified attribute DPI_EXPORT int dpiObject_getAttributeValue(dpiObject *obj, dpiObjectAttr *attr, dpiNativeTypeNum nativeTypeNum, dpiData *value); // return whether an element exists in a collection at the specified index DPI_EXPORT int dpiObject_getElementExistsByIndex(dpiObject *obj, int32_t index, int *exists); // get the value of the element in a collection at the specified index DPI_EXPORT int dpiObject_getElementValueByIndex(dpiObject *obj, int32_t index, dpiNativeTypeNum nativeTypeNum, dpiData *value); // return the first index used in a collection DPI_EXPORT int dpiObject_getFirstIndex(dpiObject *obj, int32_t *index, int *exists); // return the last index used in a collection DPI_EXPORT int dpiObject_getLastIndex(dpiObject *obj, int32_t *index, int *exists); // return the next index used in a collection given an index DPI_EXPORT int dpiObject_getNextIndex(dpiObject *obj, int32_t index, int32_t *nextIndex, int *exists); // return the previous index used in a collection given an index DPI_EXPORT int dpiObject_getPrevIndex(dpiObject *obj, int32_t index, int32_t *prevIndex, int *exists); // return the number of elements in a collection DPI_EXPORT int dpiObject_getSize(dpiObject *obj, int32_t *size); // release a reference to the object DPI_EXPORT int dpiObject_release(dpiObject *obj); // set the value of the specified attribute DPI_EXPORT int dpiObject_setAttributeValue(dpiObject *obj, dpiObjectAttr *attr, dpiNativeTypeNum nativeTypeNum, dpiData *value); // set the value of the element in a collection at the specified index DPI_EXPORT int dpiObject_setElementValueByIndex(dpiObject *obj, int32_t index, dpiNativeTypeNum nativeTypeNum, dpiData *value); // trim a number of elements from the end of a collection DPI_EXPORT int dpiObject_trim(dpiObject *obj, uint32_t numToTrim); //----------------------------------------------------------------------------- // Object Type Attribute Methods (dpiObjectAttr) //----------------------------------------------------------------------------- // add a reference to the attribute DPI_EXPORT int dpiObjectAttr_addRef(dpiObjectAttr *attr); // return the name of the attribute DPI_EXPORT int dpiObjectAttr_getInfo(dpiObjectAttr *attr, dpiObjectAttrInfo *info); // release a reference to the attribute DPI_EXPORT int dpiObjectAttr_release(dpiObjectAttr *attr); //----------------------------------------------------------------------------- // Object Type Methods (dpiObjectType) //----------------------------------------------------------------------------- // add a reference to the object type DPI_EXPORT int dpiObjectType_addRef(dpiObjectType *objType); // create an object of the specified type and return it DPI_EXPORT int dpiObjectType_createObject(dpiObjectType *objType, dpiObject **obj); // return the attributes available on the object type DPI_EXPORT int dpiObjectType_getAttributes(dpiObjectType *objType, uint16_t numAttributes, dpiObjectAttr **attributes); // return information about the object type DPI_EXPORT int dpiObjectType_getInfo(dpiObjectType *objType, dpiObjectTypeInfo *info); // release a reference to the object type DPI_EXPORT int dpiObjectType_release(dpiObjectType *objType); //----------------------------------------------------------------------------- // Session Pools Methods (dpiPool) //----------------------------------------------------------------------------- // acquire a connection from the pool and return it DPI_EXPORT int dpiPool_acquireConnection(dpiPool *pool, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, dpiConnCreateParams *createParams, dpiConn **conn); // add a reference to a pool DPI_EXPORT int dpiPool_addRef(dpiPool *pool); // destroy the pool now, not when its reference count reaches zero DPI_EXPORT int dpiPool_close(dpiPool *pool, dpiPoolCloseMode closeMode); // create a session pool and return it DPI_EXPORT int dpiPool_create(const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiPoolCreateParams *createParams, dpiPool **pool); // get the pool's busy count DPI_EXPORT int dpiPool_getBusyCount(dpiPool *pool, uint32_t *value); // return the encoding information used by the session pool DPI_EXPORT int dpiPool_getEncodingInfo(dpiPool *pool, dpiEncodingInfo *info); // get the pool's "get" mode DPI_EXPORT int dpiPool_getGetMode(dpiPool *pool, dpiPoolGetMode *value); // get the pool's maximum lifetime session DPI_EXPORT int dpiPool_getMaxLifetimeSession(dpiPool *pool, uint32_t *value); // get the pool's maximum sessions per shard DPI_EXPORT int dpiPool_getMaxSessionsPerShard(dpiPool *pool, uint32_t *value); // get the pool's open count DPI_EXPORT int dpiPool_getOpenCount(dpiPool *pool, uint32_t *value); // return whether the SODA metadata cache is enabled or not DPI_EXPORT int dpiPool_getSodaMetadataCache(dpiPool *pool, int *enabled); // return the statement cache size DPI_EXPORT int dpiPool_getStmtCacheSize(dpiPool *pool, uint32_t *cacheSize); // get the pool's timeout value DPI_EXPORT int dpiPool_getTimeout(dpiPool *pool, uint32_t *value); // get the pool's wait timeout value DPI_EXPORT int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value); // get the pool-ping-interval DPI_EXPORT int dpiPool_getPingInterval(dpiPool *pool, int *value); // release a reference to the pool DPI_EXPORT int dpiPool_release(dpiPool *pool); // set token parameter for token based authentication DPI_EXPORT int dpiPool_setAccessToken(dpiPool *pool, dpiAccessToken *params); // set the pool's "get" mode DPI_EXPORT int dpiPool_setGetMode(dpiPool *pool, dpiPoolGetMode value); // set the pool's maximum lifetime session DPI_EXPORT int dpiPool_setMaxLifetimeSession(dpiPool *pool, uint32_t value); // set the pool's maximum sessions per shard DPI_EXPORT int dpiPool_setMaxSessionsPerShard(dpiPool *pool, uint32_t value); // set whether the SODA metadata cache is enabled or not DPI_EXPORT int dpiPool_setSodaMetadataCache(dpiPool *pool, int enabled); // set the statement cache size DPI_EXPORT int dpiPool_setStmtCacheSize(dpiPool *pool, uint32_t cacheSize); // set the pool's timeout value DPI_EXPORT int dpiPool_setTimeout(dpiPool *pool, uint32_t value); // set the pool's wait timeout value DPI_EXPORT int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value); // set the pool-ping-interval value DPI_EXPORT int dpiPool_setPingInterval(dpiPool *pool, int value); //----------------------------------------------------------------------------- // AQ Queue Methods (dpiQueue) //----------------------------------------------------------------------------- // add a reference to the queue DPI_EXPORT int dpiQueue_addRef(dpiQueue *queue); // dequeue multiple messages from the queue DPI_EXPORT int dpiQueue_deqMany(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props); // dequeue a single message from the queue DPI_EXPORT int dpiQueue_deqOne(dpiQueue *queue, dpiMsgProps **props); // enqueue multiple message to the queue DPI_EXPORT int dpiQueue_enqMany(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props); // enqueue a single message to the queue DPI_EXPORT int dpiQueue_enqOne(dpiQueue *queue, dpiMsgProps *props); // get a reference to the dequeue options associated with the queue DPI_EXPORT int dpiQueue_getDeqOptions(dpiQueue *queue, dpiDeqOptions **options); // get a reference to the enqueue options associated with the queue DPI_EXPORT int dpiQueue_getEnqOptions(dpiQueue *queue, dpiEnqOptions **options); // release a reference to the queue DPI_EXPORT int dpiQueue_release(dpiQueue *queue); // reconfigure the current pool DPI_EXPORT int dpiPool_reconfigure(dpiPool *pool, uint32_t minSessions, uint32_t maxSessions, uint32_t sessionIncrement); //----------------------------------------------------------------------------- // SODA Collection Methods (dpiSodaColl) //----------------------------------------------------------------------------- // add a reference to the SODA collection DPI_EXPORT int dpiSodaColl_addRef(dpiSodaColl *coll); // create an index on the collection DPI_EXPORT int dpiSodaColl_createIndex(dpiSodaColl *coll, const char *indexSpec, uint32_t indexSpecLength, uint32_t flags); // drop a SODA collection DPI_EXPORT int dpiSodaColl_drop(dpiSodaColl *coll, uint32_t flags, int *isDropped); // drop an index on the collection DPI_EXPORT int dpiSodaColl_dropIndex(dpiSodaColl *coll, const char *name, uint32_t nameLength, uint32_t flags, int *isDropped); // find documents in a SODA collection and return a cursor DPI_EXPORT int dpiSodaColl_find(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, dpiSodaDocCursor **cursor); // find a single document in a SODA collection DPI_EXPORT int dpiSodaColl_findOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **doc); // get the data guide for the collection DPI_EXPORT int dpiSodaColl_getDataGuide(dpiSodaColl *coll, uint32_t flags, dpiSodaDoc **doc); // get the count of documents that match the criteria DPI_EXPORT int dpiSodaColl_getDocCount(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count); // get the metadata of the collection DPI_EXPORT int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value, uint32_t *valueLength); // get the name of the collection DPI_EXPORT int dpiSodaColl_getName(dpiSodaColl *coll, const char **value, uint32_t *valueLength); // insert multiple documents into the SODA collection DPI_EXPORT int dpiSodaColl_insertMany(dpiSodaColl *coll, uint32_t numDocs, dpiSodaDoc **docs, uint32_t flags, dpiSodaDoc **insertedDocs); // insert multiple documents into the SODA collection (with options) DPI_EXPORT int dpiSodaColl_insertManyWithOptions(dpiSodaColl *coll, uint32_t numDocs, dpiSodaDoc **docs, dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **insertedDocs); // insert a document into the SODA collection DPI_EXPORT int dpiSodaColl_insertOne(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, dpiSodaDoc **insertedDoc); // insert a document into the SODA collection (with options) DPI_EXPORT int dpiSodaColl_insertOneWithOptions(dpiSodaColl *coll, dpiSodaDoc *doc, dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **insertedDoc); // get a list of indexes associated with the collection DPI_EXPORT int dpiSodaColl_listIndexes(dpiSodaColl *coll, uint32_t flags, dpiStringList *list); // release a reference to the SODA collection DPI_EXPORT int dpiSodaColl_release(dpiSodaColl *coll); // remove documents from a SODA collection (with operation options) DPI_EXPORT int dpiSodaColl_remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count); // replace a document in a SODA collection (with operation options) DPI_EXPORT int dpiSodaColl_replaceOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, int *replaced, dpiSodaDoc **replacedDoc); // save a document to a SODA collection DPI_EXPORT int dpiSodaColl_save(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, dpiSodaDoc **savedDoc); // save a document to a SODA collection (with options) DPI_EXPORT int dpiSodaColl_saveWithOptions(dpiSodaColl *coll, dpiSodaDoc *doc, dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **savedDoc); // remove all of the documents from a SODA collection DPI_EXPORT int dpiSodaColl_truncate(dpiSodaColl *coll); //----------------------------------------------------------------------------- // SODA Collection Cursor Methods (dpiSodaCollCursor) //----------------------------------------------------------------------------- // add a reference to the SODA collection cursor DPI_EXPORT int dpiSodaCollCursor_addRef(dpiSodaCollCursor *cursor); // close the SODA collection cursor DPI_EXPORT int dpiSodaCollCursor_close(dpiSodaCollCursor *cursor); // get the next collection from the cursor DPI_EXPORT int dpiSodaCollCursor_getNext(dpiSodaCollCursor *cursor, uint32_t flags, dpiSodaColl **coll); // release a reference to the SODA collection cursor DPI_EXPORT int dpiSodaCollCursor_release(dpiSodaCollCursor *cursor); //----------------------------------------------------------------------------- // SODA Database Methods (dpiSodaDb) //----------------------------------------------------------------------------- // add a reference to the SODA database DPI_EXPORT int dpiSodaDb_addRef(dpiSodaDb *db); // create a new SODA collection DPI_EXPORT int dpiSodaDb_createCollection(dpiSodaDb *db, const char *name, uint32_t nameLength, const char *metadata, uint32_t metadataLength, uint32_t flags, dpiSodaColl **coll); // create a new SODA document with binary or encoded text content DPI_EXPORT int dpiSodaDb_createDocument(dpiSodaDb *db, const char *key, uint32_t keyLength, const char *content, uint32_t contentLength, const char *mediaType, uint32_t mediaTypeLength, uint32_t flags, dpiSodaDoc **doc); // create a new SODA document with JSON content DPI_EXPORT int dpiSodaDb_createJsonDocument(dpiSodaDb *db, const char *key, uint32_t keyLength, const dpiJsonNode *content, uint32_t flags, dpiSodaDoc **doc); // free the memory allocated when getting an array of SODA collection names DPI_EXPORT int dpiSodaDb_freeCollectionNames(dpiSodaDb *db, dpiStringList *names); // return a cursor to iterate over SODA collections DPI_EXPORT int dpiSodaDb_getCollections(dpiSodaDb *db, const char *startName, uint32_t startNameLength, uint32_t flags, dpiSodaCollCursor **cursor); // return an array of SODA collection names DPI_EXPORT int dpiSodaDb_getCollectionNames(dpiSodaDb *db, const char *startName, uint32_t startNameLength, uint32_t limit, uint32_t flags, dpiStringList *names); // open an existing SODA collection DPI_EXPORT int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name, uint32_t nameLength, uint32_t flags, dpiSodaColl **coll); // release a reference to the SODA database DPI_EXPORT int dpiSodaDb_release(dpiSodaDb *db); //----------------------------------------------------------------------------- // SODA Document Methods (dpiSodaDoc) //----------------------------------------------------------------------------- // add a reference to the SODA document DPI_EXPORT int dpiSodaDoc_addRef(dpiSodaDoc *cursor); // get the binary or encoded text content of the document DPI_EXPORT int dpiSodaDoc_getContent(dpiSodaDoc *doc, const char **value, uint32_t *valueLength, const char **encoding); // get the created timestamp associated with the document DPI_EXPORT int dpiSodaDoc_getCreatedOn(dpiSodaDoc *doc, const char **value, uint32_t *valueLength); // get whether the document contains a JSON document or not DPI_EXPORT int dpiSodaDoc_getIsJson(dpiSodaDoc *doc, int *isJson); // get the JSON content of the document DPI_EXPORT int dpiSodaDoc_getJsonContent(dpiSodaDoc *doc, dpiJson **value); // get the key associated with the document DPI_EXPORT int dpiSodaDoc_getKey(dpiSodaDoc *doc, const char **value, uint32_t *valueLength); // get the last modified timestamp associated with the document DPI_EXPORT int dpiSodaDoc_getLastModified(dpiSodaDoc *doc, const char **value, uint32_t *valueLength); // get the media type of the document DPI_EXPORT int dpiSodaDoc_getMediaType(dpiSodaDoc *doc, const char **value, uint32_t *valueLength); // get the version of the document DPI_EXPORT int dpiSodaDoc_getVersion(dpiSodaDoc *doc, const char **value, uint32_t *valueLength); // release a reference to the SODA document DPI_EXPORT int dpiSodaDoc_release(dpiSodaDoc *doc); //----------------------------------------------------------------------------- // SODA Document Cursor Methods (dpiSodaDocCursor) //----------------------------------------------------------------------------- // add a reference to the SODA document cursor DPI_EXPORT int dpiSodaDocCursor_addRef(dpiSodaDocCursor *cursor); // close the SODA document cursor DPI_EXPORT int dpiSodaDocCursor_close(dpiSodaDocCursor *cursor); // get the next document from the cursor DPI_EXPORT int dpiSodaDocCursor_getNext(dpiSodaDocCursor *cursor, uint32_t flags, dpiSodaDoc **doc); // release a reference to the SODA document cursor DPI_EXPORT int dpiSodaDocCursor_release(dpiSodaDocCursor *cursor); //----------------------------------------------------------------------------- // Statement Methods (dpiStmt) //----------------------------------------------------------------------------- // add a reference to a statement DPI_EXPORT int dpiStmt_addRef(dpiStmt *stmt); // bind a variable to the statement using the given name DPI_EXPORT int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength, dpiVar *var); // bind a variable to the statement at the given position // positions are determined by the order in which names are introduced DPI_EXPORT int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var); // bind a value to the statement using the given name // this creates the variable by looking at the type and then binds it DPI_EXPORT int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name, uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data); // bind a value to the statement at the given position // this creates the variable by looking at the type and then binds it DPI_EXPORT int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos, dpiNativeTypeNum nativeTypeNum, dpiData *data); // close the statement now, not when its reference count reaches zero DPI_EXPORT int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength); // define a variable to accept the data for the specified column (1 based) DPI_EXPORT int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var); // define type of data to use for the specified column (1 based) DPI_EXPORT int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos, dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, uint32_t size, int sizeIsBytes, dpiObjectType *objType); // execute the statement and return the number of query columns // zero implies the statement is not a query DPI_EXPORT int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, uint32_t *numQueryColumns); // execute the statement multiple times (queries not supported) DPI_EXPORT int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters); // fetch a single row and return the index into the defined variables // this will internally perform any execute and array fetch as needed DPI_EXPORT int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex); // return the number of rows that are available in the defined variables // up to the maximum specified; this will internally perform execute/array // fetch only if no rows are available in the defined variables and there are // more rows available to fetch DPI_EXPORT int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows, uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows); // get the number of batch errors that took place in the previous execution DPI_EXPORT int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count); // get the batch errors that took place in the previous execution DPI_EXPORT int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors, dpiErrorInfo *errors); // get the number of bind variables that are in the prepared statement DPI_EXPORT int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count); // get the names of the bind variables that are in the prepared statement DPI_EXPORT int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames, const char **bindNames, uint32_t *bindNameLengths); // get the number of rows to (internally) fetch at one time DPI_EXPORT int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize); // get next implicit result from previous execution; NULL if no more exist DPI_EXPORT int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult); // return information about the statement DPI_EXPORT int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info); // get the rowid of the last row affected by a DML statement DPI_EXPORT int dpiStmt_getLastRowid(dpiStmt *stmt, dpiRowid **rowid); // get the number of query columns (zero implies the statement is not a query) DPI_EXPORT int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns); // generic method for getting an OCI statement attribute // WARNING: use only as directed by Oracle DPI_EXPORT int dpiStmt_getOciAttr(dpiStmt *stmt, uint32_t attribute, dpiDataBuffer *value, uint32_t *valueLength); // return the number of rows that are prefetched by the Oracle Client library DPI_EXPORT int dpiStmt_getPrefetchRows(dpiStmt *stmt, uint32_t *numRows); // return metadata about the column at the specified position (1 based) DPI_EXPORT int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info); // get the value for the specified column of the current row fetched DPI_EXPORT int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos, dpiNativeTypeNum *nativeTypeNum, dpiData **data); // get the row count for the statement // for queries, this is the number of rows that have been fetched so far // for non-queries, this is the number of rows affected by the last execution DPI_EXPORT int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count); // get the number of rows affected for each DML operation just executed // using the mode DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS DPI_EXPORT int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts, uint64_t **rowCounts); // get subscription query id for continuous query notification DPI_EXPORT int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId); // release a reference to the statement DPI_EXPORT int dpiStmt_release(dpiStmt *stmt); // scroll the statement to the desired row // this is only valid for scrollable statements DPI_EXPORT int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset, int32_t rowCountOffset); // set the number of rows to (internally) fetch at one time DPI_EXPORT int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize); // generic method for setting an OCI statement attribute // WARNING: use only as directed by Oracle DPI_EXPORT int dpiStmt_setOciAttr(dpiStmt *stmt, uint32_t attribute, void *value, uint32_t valueLength); // set the number of rows that are prefetched by the Oracle Client library DPI_EXPORT int dpiStmt_setPrefetchRows(dpiStmt *stmt, uint32_t numRows); // set the flag to exclude the current SQL statement from the statement // cache DPI_EXPORT int dpiStmt_deleteFromCache(dpiStmt *stmt); //----------------------------------------------------------------------------- // Rowid Methods (dpiRowid) //----------------------------------------------------------------------------- // add a reference to the rowid DPI_EXPORT int dpiRowid_addRef(dpiRowid *rowid); // get string representation from rowid DPI_EXPORT int dpiRowid_getStringValue(dpiRowid *rowid, const char **value, uint32_t *valueLength); // release a reference to the rowid DPI_EXPORT int dpiRowid_release(dpiRowid *subscr); //----------------------------------------------------------------------------- // Subscription Methods (dpiSubscr) //----------------------------------------------------------------------------- // add a reference to the subscription DPI_EXPORT int dpiSubscr_addRef(dpiSubscr *subscr); // prepare statement for registration with subscription DPI_EXPORT int dpiSubscr_prepareStmt(dpiSubscr *subscr, const char *sql, uint32_t sqlLength, dpiStmt **stmt); // release a reference to the subscription DPI_EXPORT int dpiSubscr_release(dpiSubscr *subscr); //----------------------------------------------------------------------------- // Variable Methods (dpiVar) //----------------------------------------------------------------------------- // add a reference to the variable DPI_EXPORT int dpiVar_addRef(dpiVar *var); // copy the data from one variable to another variable DPI_EXPORT int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar, uint32_t sourcePos); // return the number of elements in a PL/SQL index-by table DPI_EXPORT int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements); // return pointer to array of dpiData structures for transferring data // this is needed for DML returning where the number of elements is modified DPI_EXPORT int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements, dpiData **data); // return the size in bytes of the buffer used for fetching/binding DPI_EXPORT int dpiVar_getSizeInBytes(dpiVar *var, uint32_t *sizeInBytes); // release a reference to the variable DPI_EXPORT int dpiVar_release(dpiVar *var); // set the value of the variable from a byte string DPI_EXPORT int dpiVar_setFromBytes(dpiVar *var, uint32_t pos, const char *value, uint32_t valueLength); // set the value of the variable from a JSON handle DPI_EXPORT int dpiVar_setFromJson(dpiVar *var, uint32_t pos, dpiJson *json); // set the value of the variable from a LOB DPI_EXPORT int dpiVar_setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob); // set the value of the variable from an object DPI_EXPORT int dpiVar_setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj); // set the value of the variable from a rowid DPI_EXPORT int dpiVar_setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid); // set the value of the variable from a statement DPI_EXPORT int dpiVar_setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt); // set the value of the variable from a vector DPI_EXPORT int dpiVar_setFromVector(dpiVar *var, uint32_t pos, dpiVector *vector); // set the number of elements in a PL/SQL index-by table DPI_EXPORT int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements); //----------------------------------------------------------------------------- // Vector Methods (dpiVector) //----------------------------------------------------------------------------- // add a reference to the vector DPI_EXPORT int dpiVector_addRef(dpiVector *vector); // get information about the vector DPI_EXPORT int dpiVector_getValue(dpiVector *vector, dpiVectorInfo *info); // release a reference to the vector DPI_EXPORT int dpiVector_release(dpiVector *vector); // set the contents of the vector DPI_EXPORT int dpiVector_setValue(dpiVector *vector, dpiVectorInfo *info); #ifdef __cplusplus } #endif #endif odpi-5.6.4/samples/000077500000000000000000000000001510466437300141365ustar00rootroot00000000000000odpi-5.6.4/samples/DemoAppContext.c000066400000000000000000000124101510466437300171720ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoAppContext.c // Demos the use of application context. //----------------------------------------------------------------------------- #include "SampleLib.h" #define APP_CTX_NAMESPACE "CLIENTCONTEXT" #define APP_CTX_NUM_KEYS 3 #define SQL_TEXT_GET_CTX "select sys_context(:1, :2) from dual" static const char *gc_ContextKeys[APP_CTX_NUM_KEYS] = { "ATTR1", "ATTR2", "ATTR3" }; static const char *gc_ContextValues[APP_CTX_NUM_KEYS] = { "VALUE1", "VALUE2", "VALUE3" }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *namespaceData, *keyData, *valueData; uint32_t numQueryColumns, i, bufferRowIndex; dpiAppContext appContext[APP_CTX_NUM_KEYS]; dpiVar *namespaceVar, *keyVar, *valueVar; dpiConnCreateParams createParams; dpiSampleParams *params; dpiStmt *stmt; dpiConn *conn; int found; // get parameters params = dpiSamples_getParams(); // populate app context for (i = 0; i < APP_CTX_NUM_KEYS; i++) { appContext[i].namespaceName = APP_CTX_NAMESPACE; appContext[i].namespaceNameLength = strlen(APP_CTX_NAMESPACE); appContext[i].name = gc_ContextKeys[i]; appContext[i].nameLength = strlen(gc_ContextKeys[i]); appContext[i].value = gc_ContextValues[i]; appContext[i].valueLength = strlen(gc_ContextValues[i]); } // connect to the database if (dpiContext_initConnCreateParams(params->context, &createParams) < 0) return dpiSamples_showError(); createParams.appContext = appContext; createParams.numAppContext = APP_CTX_NUM_KEYS; if (dpiConn_create(params->context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &conn) < 0) return dpiSamples_showError(); // prepare statement for multiple execution if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_GET_CTX, strlen(SQL_TEXT_GET_CTX), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 30, 1, 0, NULL, &namespaceVar, &namespaceData) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 30, 1, 0, NULL, &keyVar, &keyData) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 30, 1, 0, NULL, &valueVar, &valueData) < 0) return dpiSamples_showError(); // get the values for each key for (i = 0; i < APP_CTX_NUM_KEYS; i++) { if (dpiVar_setFromBytes(namespaceVar, 0, APP_CTX_NAMESPACE, strlen(APP_CTX_NAMESPACE)) < 0) return dpiSamples_showError(); if (dpiVar_setFromBytes(keyVar, 0, gc_ContextKeys[i], strlen(gc_ContextKeys[i])) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, namespaceVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, keyVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, valueVar) < 0) return dpiSamples_showError(); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); printf("Value of context key %s is %.*s\n", gc_ContextKeys[i], valueData->value.asBytes.length, valueData->value.asBytes.ptr); } // clean up dpiVar_release(namespaceVar); dpiVar_release(keyVar); dpiVar_release(valueVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoBFILE.c000066400000000000000000000171071510466437300157360ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBFILE.c // Demos whether BFILEs are handled properly using ODPI-C. // // NOTE: the program assumes that you have write access to the // directory path pointed to by the directory object, i.e. that the // program is being run on the same machine as the database. // // DIR_NAME is specified in the Makefile // //----------------------------------------------------------------------------- #ifdef _WIN32 #include #else #include #endif #include "SampleLib.h" #define SQL_TEXT_QUERY_DIR "select directory_path " \ "from all_directories " \ "where directory_name = :1" #define SQL_TEXT_DELETE "delete from DemoBFILEs" #define SQL_TEXT_INSERT "insert into DemoBFILEs " \ "values (:IntValue, :BFILEValue)" #define SQL_TEXT_QUERY "select IntCol, BFILECol " \ "from DemoBFILEs" #define FILE_NAME "demo_contents.txt" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *intColValue, *bfileColValue, *pathValue, *bfileValue, intValue; uint32_t numQueryColumns, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiSampleParams *params; dpiQueryInfo queryInfo; uint64_t blobSize; dpiData bindValue; dpiVar *bfileVar; dpiStmt *stmt; dpiConn *conn; char *path; int found; FILE *fp; // connect to database params = dpiSamples_getParams(); conn = dpiSamples_getConn(0, NULL); printf("Note: this demo must be run on the same machine as the database\n"); // find the directory path location by querying from the database if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_QUERY_DIR, strlen(SQL_TEXT_QUERY_DIR), NULL, 0, &stmt) < 0) return dpiSamples_showError(); dpiData_setBytes(&bindValue, (char*) params->dirName, params->dirNameLength); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_BYTES, &bindValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &pathValue) < 0) return dpiSamples_showError(); path = malloc(pathValue->value.asBytes.length + 1); if (!path) { printf("ERROR: unable to duplicate path string!?\n"); return -1; } memcpy(path, pathValue->value.asBytes.ptr, pathValue->value.asBytes.length); path[pathValue->value.asBytes.length] = '\0'; dpiStmt_release(stmt); printf("%.*s path is '%s'\n", params->dirNameLength, params->dirName, path); // write a temporary file at that location if (chdir(path) < 0) { printf("ERROR: unable to change directory to %.*s location\n", params->dirNameLength, params->dirName); return -1; } free(path); printf("Writing file named '%s'\n", FILE_NAME); fp = fopen(FILE_NAME, "w"); if (!fp) { printf("ERROR: unable to open demo file for writing\n"); return -1; } fprintf(fp, "These are some demo comments.\nFile can be deleted.\n"); fclose(fp); // delete existing rows in table printf("Delete existing rows in table...\n"); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_DELETE, strlen(SQL_TEXT_DELETE), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // inserting row into table printf("Inserting row into table...\n"); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_BFILE, DPI_NATIVE_TYPE_LOB, 1, 0, 0, 0, NULL, &bfileVar, &bfileValue) < 0) return dpiSamples_showError(); bfileValue->isNull = 0; if (dpiLob_setDirectoryAndFileName(bfileValue->value.asLOB, params->dirName, params->dirNameLength, FILE_NAME, strlen(FILE_NAME)) < 0) return dpiSamples_showError(); intValue.isNull = 0; intValue.value.asInt64 = 1; if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_INSERT, strlen(SQL_TEXT_INSERT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &intValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, bfileVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiConn_commit(conn) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); dpiVar_release(bfileVar); // querying row from table printf("Querying row from table...\n"); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_QUERY, strlen(SQL_TEXT_QUERY), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intColValue) < 0 || dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &bfileColValue) < 0) return dpiSamples_showError(); if (dpiLob_getSize(bfileColValue->value.asLOB, &blobSize) < 0) return dpiSamples_showError(); printf("Row: IntCol = %g, BfileCol = BFILE(%" PRIu64 ")\n", intColValue->value.asDouble, blobSize); } // display description of each variable for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%.*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoBLOB.c000066400000000000000000000134501510466437300156300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBLOB.c // Populates a table containing BLOBs and then fetches them using LOB // locators. For smaller sized LOBs (up to a few megabytes in size, depending // on platform and configuration) this can be substantially slower because // there are more round trips to the database that are required. // // See DemoBLOBsAsBytes.c for a similar example that fetches the BLOBs as // strings instead. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "truncate table DemoBLOBs" #define SQL_TEXT_2 "insert into DemoBLOBs values (:1, :2)" #define SQL_TEXT_3 "select IntCol, BlobCol from DemoBLOBs" #define NUM_ROWS 10 #define LOB_SIZE_INCREMENT 25000 #define MAX_LOB_SIZE NUM_ROWS * LOB_SIZE_INCREMENT //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiData *intColValue, *blobColValue; dpiVar *intColVar, *blobColVar; dpiNativeTypeNum nativeTypeNum; char buffer[MAX_LOB_SIZE]; dpiQueryInfo queryInfo; uint64_t blobSize; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // truncate table if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); // populate with a number of rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_RAW, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &blobColVar, &blobColValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, blobColVar) < 0) return dpiSamples_showError(); for (i = 0; i < NUM_ROWS; i++) { dpiData_setInt64(intColValue, i + 1); memset(buffer, i + 'A', LOB_SIZE_INCREMENT * (i + 1)); if (dpiVar_setFromBytes(blobColVar, 0, buffer, LOB_SIZE_INCREMENT * (i + 1)) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); } if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); if (dpiVar_release(intColVar) < 0) return dpiSamples_showError(); if (dpiVar_release(blobColVar) < 0) return dpiSamples_showError(); // fetch rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_3, strlen(SQL_TEXT_3), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intColValue) < 0 || dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &blobColValue) < 0) return dpiSamples_showError(); if (dpiLob_getSize(blobColValue->value.asLOB, &blobSize) < 0) return dpiSamples_showError(); printf("Row: IntCol = %" PRId64 ", BlobCol = BLOB(%" PRIu64 ")\n", intColValue->value.asInt64, blobSize); } // display description of each variable for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoBLOBsAsBytes.c000066400000000000000000000135271510466437300173130ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBLOBsAsBytes.c // Populates a table containing BLOBs and then fetches them without using // LOB locators, but directly as bytes. For smaller sized LOBs (up to a few // megabytes in size, depending on platform and configuration) this can // significantly improve performance as there are fewer round trips to the // database that are required. // // See DemoBLOB.c for a similar example but which fetches the BLOBs as // LOB locators instead. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "truncate table DemoBLOBs" #define SQL_TEXT_2 "insert into DemoBLOBs values (:1, :2)" #define SQL_TEXT_3 "select IntCol, BlobCol from DemoBLOBs" #define NUM_ROWS 10 #define LOB_SIZE_INCREMENT 25000 #define MAX_LOB_SIZE NUM_ROWS * LOB_SIZE_INCREMENT //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiData *intColValue, *blobColValue; dpiVar *intColVar, *blobColVar; char buffer[MAX_LOB_SIZE]; dpiQueryInfo queryInfo; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // truncate table if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); // populate with a number of rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, NUM_ROWS, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_RAW, DPI_NATIVE_TYPE_BYTES, NUM_ROWS, 0, 0, 0, NULL, &blobColVar, &blobColValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, blobColVar) < 0) return dpiSamples_showError(); for (i = 0; i < NUM_ROWS; i++) { dpiData_setInt64(intColValue, i + 1); intColValue->value.asInt64 = i + 1; memset(buffer, i + 'A', LOB_SIZE_INCREMENT * (i + 1)); if (dpiVar_setFromBytes(blobColVar, 0, buffer, LOB_SIZE_INCREMENT * (i + 1)) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); } if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); // fetch rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_3, strlen(SQL_TEXT_3), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, NUM_ROWS) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 2, blobColVar) < 0) return dpiSamples_showError(); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; printf("Row: IntCol = %" PRId64 ", BlobCol = BLOB(%" PRIu32 ")\n", intColValue[bufferRowIndex].value.asInt64, blobColValue[bufferRowIndex].value.asBytes.length); } if (dpiVar_release(intColVar) < 0) return dpiSamples_showError(); if (dpiVar_release(blobColVar) < 0) return dpiSamples_showError(); // display description of each variable for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoBindArrays.c000066400000000000000000000220021510466437300171410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBindArrays.c // Demos calling stored procedures binding PL/SQL arrays in various ways. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_IN "begin :1 := pkg_DemoStringArrays.DemoInArrays(:2, :3); end;" #define SQL_INOUT "begin pkg_DemoStringArrays.DemoInOutArrays(:1, :2); end;" #define SQL_OUT "begin pkg_DemoStringArrays.DemoOutArrays(:1, :2); end;" #define SQL_ASSOC "begin pkg_DemoStringArrays.DemoIndexBy(:1); end;" #define TYPE_NAME "PKG_DEMOSTRINGARRAYS.UDT_STRINGLIST" static const char *gc_Strings[5] = { "Demo String 1 (I)", "Demo String 2 (II)", "Demo String 3 (III)", "Demo String 4 (IV)", "Demo String 5 (V)" }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *returnValue, *numberValue, *arrayValue, *objectValue; dpiVar *returnVar, *numberVar, *arrayVar, *objectVar; uint32_t numQueryColumns, i, numElementsInArray; int32_t elementIndex, nextElementIndex; dpiObjectType *objType; dpiData elementValue; dpiStmt *stmt; dpiConn *conn; int exists; // connect to database conn = dpiSamples_getConn(0, NULL); // create variable for return value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiSamples_showError(); // create variable for numeric value passed to procedures if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numberVar, &numberValue) < 0) return dpiSamples_showError(); // create variable for string array passed to procedures // a maximum of 8 elements, each of 60 characters is permitted if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 8, 60, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiSamples_showError(); // ************** IN ARRAYS ***************** // prepare statement for demoing in arrays if (dpiConn_prepareStmt(conn, 0, SQL_IN, strlen(SQL_IN), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // bind return value if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiSamples_showError(); // bind in numeric value numberValue->isNull = 0; numberValue->value.asInt64 = 12; if (dpiStmt_bindByPos(stmt, 2, numberVar) < 0) return dpiSamples_showError(); // bind in string array for (i = 0; i < 5; i++) { if (dpiVar_setFromBytes(arrayVar, i, gc_Strings[i], strlen(gc_Strings[i])) < 0) return dpiSamples_showError(); } if (dpiVar_setNumElementsInArray(arrayVar, 5) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 3, arrayVar) < 0) return dpiSamples_showError(); // perform execution (in arrays with 5 elements) if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); printf("IN array (5 elements): return value is %" PRId64 "\n\n", returnValue->value.asInt64); // perform execution (in arrays with 0 elements) if (dpiVar_setNumElementsInArray(arrayVar, 0) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); printf("IN array (0 elements): return value is %" PRId64 "\n\n", returnValue->value.asInt64); // ************** IN/OUT ARRAYS ***************** // prepare statement for demoing in/out arrays if (dpiConn_prepareStmt(conn, 0, SQL_INOUT, strlen(SQL_INOUT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // bind in numeric value numberValue->value.asInt64 = 5; if (dpiStmt_bindByPos(stmt, 1, numberVar) < 0) return dpiSamples_showError(); // bind in array value (use same values as demo for in arrays) if (dpiVar_setNumElementsInArray(arrayVar, 5) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiSamples_showError(); // perform execution (in/out arrays) if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // display value of array after procedure call if (dpiVar_getNumElementsInArray(arrayVar, &numElementsInArray) < 0) return dpiSamples_showError(); printf("IN/OUT array contents:\n"); for (i = 0; i < numElementsInArray; i++) printf(" [%d] %.*s\n", i + 1, arrayValue[i].value.asBytes.length, arrayValue[i].value.asBytes.ptr); printf("\n"); // ************** OUT ARRAYS ***************** // prepare statement for demoing out arrays if (dpiConn_prepareStmt(conn, 0, SQL_OUT, strlen(SQL_OUT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // bind in numeric value numberValue->value.asInt64 = 7; if (dpiStmt_bindByPos(stmt, 1, numberVar) < 0) return dpiSamples_showError(); // bind in array value (value will be overwritten) if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiSamples_showError(); // perform execution (out arrays) if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // display value of array after procedure call if (dpiVar_getNumElementsInArray(arrayVar, &numElementsInArray) < 0) return dpiSamples_showError(); printf("OUT array contents:\n"); for (i = 0; i < numElementsInArray; i++) printf(" [%d] %.*s\n", i + 1, arrayValue[i].value.asBytes.length, arrayValue[i].value.asBytes.ptr); printf("\n"); // ************** INDEX-BY ASSOCIATIVE ARRAYS ***************** // look up object type by name if (dpiConn_getObjectType(conn, TYPE_NAME, strlen(TYPE_NAME), &objType) < 0) return dpiSamples_showError(); // create new object variable if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiSamples_showError(); // prepare statement for demoing associative arrays if (dpiConn_prepareStmt(conn, 0, SQL_ASSOC, strlen(SQL_ASSOC), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // bind array if (dpiStmt_bindByPos(stmt, 1, objectVar) < 0) return dpiSamples_showError(); // perform execution (associative arrays) if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // display contents of array after procedure call if (dpiObject_getFirstIndex(objectValue->value.asObject, &elementIndex, &exists) < 0) return dpiSamples_showError(); printf("ASSOCIATIVE array contents:\n"); while (1) { if (dpiObject_getElementValueByIndex(objectValue->value.asObject, elementIndex, DPI_NATIVE_TYPE_BYTES, &elementValue) < 0) return dpiSamples_showError(); printf(" [%d] %.*s\n", elementIndex, elementValue.value.asBytes.length, elementValue.value.asBytes.ptr); if (dpiObject_getNextIndex(objectValue->value.asObject, elementIndex, &nextElementIndex, &exists) < 0) return dpiSamples_showError(); if (!exists) break; elementIndex = nextElementIndex; } printf("\n"); // clean up dpiVar_release(returnVar); dpiVar_release(numberVar); dpiVar_release(arrayVar); dpiVar_release(objectVar); dpiObjectType_release(objType); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoBindJSON.c000066400000000000000000000226161510466437300164640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2020, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBindJSON.c // Demos binding JSON values into the database. This requires Oracle Client // and Oracle Database to both be 20 or higher. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL "select :1 from dual" //----------------------------------------------------------------------------- // displayJson() //----------------------------------------------------------------------------- void displayJson(dpiJsonNode *node, uint32_t indentLevel, int printIndent) { dpiTimestamp *timestamp; dpiJsonArray *array; dpiJsonObject *obj; uint32_t i, j; if (printIndent) { printf("\n"); for (i = 0; i < indentLevel; i++) printf(" "); } switch (node->nativeTypeNum) { case DPI_NATIVE_TYPE_INT64: printf("%" PRId64 "d", node->value->asInt64); break; case DPI_NATIVE_TYPE_DOUBLE: printf("%g", node->value->asDouble); break; case DPI_NATIVE_TYPE_BYTES: printf("'%.*s'", node->value->asBytes.length, node->value->asBytes.ptr); break; case DPI_NATIVE_TYPE_TIMESTAMP: timestamp = &node->value->asTimestamp; printf("%.4d-%.2d-%.2d %.2d:%.2d:%.2d", timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second); break; case DPI_NATIVE_TYPE_JSON_ARRAY: array = &node->value->asJsonArray; printf("["); for (i = 0; i < array->numElements; i++) { if (i > 0) printf(","); displayJson(&array->elements[i], indentLevel + 1, 1); } printf("\n"); for (i = 0; i < indentLevel; i++) printf(" "); printf("]"); break; case DPI_NATIVE_TYPE_JSON_OBJECT: obj = &node->value->asJsonObject; printf("{"); for (i = 0; i < obj->numFields; i++) { if (i > 0) printf(","); printf("\n"); for (j = 0; j < indentLevel + 1; j++) printf(" "); printf("'%.*s': ", obj->fieldNameLengths[i], obj->fieldNames[i]); displayJson(&obj->fields[i], indentLevel + 1, 0); } printf("\n"); for (i = 0; i < indentLevel; i++) printf(" "); printf("}"); break; default: printf("Unhandled native type %u", node->nativeTypeNum); } } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t bufferRowIndex, fieldNameLengths[2]; dpiJsonNode inNodes[12], *topNode; dpiNativeTypeNum nativeTypeNum; dpiData *inVarData, *outValue; dpiDataBuffer inNodeData[12]; char *fieldNames[2]; dpiVar *inVar; dpiConn *conn; dpiStmt *stmt; int found, i; // connect to database conn = dpiSamples_getConn(0, NULL); // build up JSON node tree; this can be done by allocating nodes or by // using fixed size arrays as demonstrated here; start with lowest levels // in tree; the data here is the same data used in the DemoFetchJSON // sample // zero all memory so only non-zero values need to be set memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); // set value for each of the nodes for (i = 0; i < 12; i++) inNodes[i].value = &inNodeData[i]; // scalar values stored in the object inNodes[0].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[0].nativeTypeNum = DPI_NATIVE_TYPE_INT64; inNodeData[0].asInt64 = 5; inNodes[1].oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; inNodes[1].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[1].asBytes.ptr = "A String"; inNodeData[1].asBytes.length = strlen(inNodeData[1].asBytes.ptr); // JSON object fieldNames[0] = "Fred"; fieldNameLengths[0] = strlen(fieldNames[0]); fieldNames[1] = "George"; fieldNameLengths[1] = strlen(fieldNames[1]); inNodes[9].oracleTypeNum = DPI_ORACLE_TYPE_JSON_OBJECT; inNodes[9].nativeTypeNum = DPI_NATIVE_TYPE_JSON_OBJECT; inNodeData[9].asJsonObject.numFields = 2; inNodeData[9].asJsonObject.fieldNames = fieldNames; inNodeData[9].asJsonObject.fieldNameLengths = fieldNameLengths; inNodeData[9].asJsonObject.fields = &inNodes[0]; inNodeData[9].asJsonObject.fieldValues = &inNodeData[0]; // scalar values stored in the lowest level array inNodes[2].oracleTypeNum = DPI_ORACLE_TYPE_RAW; inNodes[2].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[2].asBytes.ptr = "A Raw"; inNodeData[2].asBytes.length = strlen(inNodeData[2].asBytes.ptr); inNodes[3].oracleTypeNum = DPI_ORACLE_TYPE_DATE; inNodes[3].nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; inNodeData[3].asTimestamp.year = 2020; inNodeData[3].asTimestamp.month = 10; inNodeData[3].asTimestamp.day = 15; inNodeData[3].asTimestamp.hour = 13; inNodeData[3].asTimestamp.minute = 54; inNodeData[3].asTimestamp.second = 12; inNodes[4].oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP; inNodes[4].nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; inNodeData[4].asTimestamp.year = 2020; inNodeData[4].asTimestamp.month = 10; inNodeData[4].asTimestamp.day = 15; inNodeData[4].asTimestamp.hour = 13; inNodeData[4].asTimestamp.minute = 58; inNodeData[4].asTimestamp.second = 59; inNodes[5].oracleTypeNum = DPI_ORACLE_TYPE_NATIVE_DOUBLE; inNodes[5].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData[5].asDouble = 25.25; inNodes[6].oracleTypeNum = DPI_ORACLE_TYPE_NATIVE_FLOAT; inNodes[6].nativeTypeNum = DPI_NATIVE_TYPE_FLOAT; inNodeData[6].asFloat = 50.125; // lowest level JSON array inNodes[10].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[10].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[10].asJsonArray.numElements = 5; inNodeData[10].asJsonArray.elements = &inNodes[2]; inNodeData[10].asJsonArray.elementValues = &inNodeData[2]; // values stored in the top level array inNodes[7].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[7].nativeTypeNum = DPI_NATIVE_TYPE_INT64; inNodeData[7].asInt64 = 1; inNodes[8].oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; inNodes[8].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[8].asBytes.ptr = "String Value"; inNodeData[8].asBytes.length = strlen(inNodeData[8].asBytes.ptr); // top level JSON array inNodes[11].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[11].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[11].asJsonArray.numElements = 4; inNodeData[11].asJsonArray.elements = &inNodes[7]; inNodeData[11].asJsonArray.elementValues = &inNodeData[7]; // create a JSON bind variable and populate it if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &inVarData) < 0) return dpiSamples_showError(); inVarData->isNull = 0; if (dpiJson_setValue(inVarData->value.asJson, &inNodes[11]) < 0) return dpiSamples_showError(); // perform query if (dpiConn_prepareStmt(conn, 0, SQL, strlen(SQL), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiSamples_showError(); // fetch row if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiSamples_showError(); if (dpiJson_getValue(outValue->value.asJson, DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiSamples_showError(); // display results printf("Bound JSON value:\n"); displayJson(topNode, 0, 0); printf("\n"); return 0; } odpi-5.6.4/samples/DemoBindObjects.c000066400000000000000000000100531510466437300172740ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBindObjects.c // Demos simple binding of objects. //----------------------------------------------------------------------------- #include "SampleLib.h" #define OBJECT_TYPE_NAME "UDT_OBJECT" #define SQL_TEXT "begin :1 := " \ "pkg_DemoBindObject.GetStringRep(:2); end;" #define NUM_ATTRS 7 //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData attrValue, objValue, *stringRepValue; dpiObjectAttr *attrs[NUM_ATTRS]; uint32_t numQueryColumns, i; dpiObjectType *objType; dpiVar *stringRepVar; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; // connect to database conn = dpiSamples_getConn(0, NULL); // get object type and attributes if (dpiConn_getObjectType(conn, OBJECT_TYPE_NAME, strlen(OBJECT_TYPE_NAME), &objType) < 0) return dpiSamples_showError(); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiSamples_showError(); // create object and populate attributes if (dpiObjectType_createObject(objType, &obj) < 0) return dpiSamples_showError(); attrValue.isNull = 0; attrValue.value.asDouble = 13; if (dpiObject_setAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiSamples_showError(); attrValue.value.asBytes.ptr = "Demo String"; attrValue.value.asBytes.length = strlen(attrValue.value.asBytes.ptr); if (dpiObject_setAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiSamples_showError(); // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 0, 0, NULL, &stringRepVar, &stringRepValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, stringRepVar) < 0) return dpiSamples_showError(); objValue.isNull = 0; objValue.value.asObject = obj; if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_OBJECT, &objValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiObject_release(obj); dpiObjectType_release(objType); for (i = 0; i < NUM_ATTRS; i++) dpiObjectAttr_release(attrs[i]); // display result printf("String rep: '%.*s'\n", stringRepValue->value.asBytes.length, stringRepValue->value.asBytes.ptr); dpiVar_release(stringRepVar); // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoBulkAQ.c000066400000000000000000000104411510466437300162260ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoBulkAQ.c // Demos bulk enqueuing and dequeuing RAW data using advanced queuing. //----------------------------------------------------------------------------- #include "SampleLib.h" #define QUEUE_NAME "DEMO_RAW_QUEUE" #define NUM_MESSAGES 12 #define NUM_BATCH_ENQ 6 #define NUM_BATCH_DEQ 8 const char *payloads[NUM_MESSAGES] = { "The first message", "The second message", "The third message", "The fourth message", "The fifth message", "The sixth message", "The seventh message", "The eighth message", "The ninth message", "The tenth message", "The eleventh message", "The twelfth and final message" }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiMsgProps *msgPropsEnq[NUM_BATCH_ENQ], *msgPropsDeq[NUM_BATCH_DEQ]; uint32_t i, pos, numMessages; dpiDeqOptions *deqOptions; uint32_t payloadLength; const char *payload; dpiQueue *queue; dpiConn *conn; // connect to database conn = dpiSamples_getConn(0, NULL); // create queue and message properties if (dpiConn_newQueue(conn, QUEUE_NAME, strlen(QUEUE_NAME), NULL, &queue) < 0) return dpiSamples_showError(); for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiConn_newMsgProps(conn, &msgPropsEnq[i]) < 0) return dpiSamples_showError(); } dpiConn_release(conn); // enqueue messages printf("Enqueuing messages...\n"); for (i = 0, pos = 0; i < NUM_MESSAGES; i++) { printf("%s\n", payloads[i]); if (dpiMsgProps_setPayloadBytes(msgPropsEnq[pos], payloads[i], strlen(payloads[i])) < 0) return dpiSamples_showError(); if (++pos == NUM_BATCH_ENQ) { if (dpiQueue_enqMany(queue, NUM_BATCH_ENQ, msgPropsEnq) < 0) return dpiSamples_showError(); pos = 0; } } for (i = 0; i < NUM_BATCH_ENQ; i++) dpiMsgProps_release(msgPropsEnq[i]); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiSamples_showError(); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiSamples_showError(); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiSamples_showError(); // dequeue messages printf("\nDequeuing messages...\n"); while (1) { numMessages = NUM_BATCH_DEQ; if (dpiQueue_deqMany(queue, &numMessages, msgPropsDeq) < 0) return dpiSamples_showError(); if (numMessages == 0) break; for (i = 0; i < numMessages; i++) { if (dpiMsgProps_getPayload(msgPropsDeq[i], NULL, &payload, &payloadLength) < 0) return dpiSamples_showError(); printf("%.*s\n", payloadLength, payload); dpiMsgProps_release(msgPropsDeq[i]); } } printf("\nDone.\n"); return 0; } odpi-5.6.4/samples/DemoCLOB.c000066400000000000000000000135461510466437300156370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoCLOB.c // Populates a table containing CLOBs and then fetches them using LOB // locators. For smaller sized LOBs (up to a few megabytes in size, depending // on platform and configuration) this can be substantially slower because // there are more round trips to the database that are required. // // See DemoCLOBsAsStrings.c for a similar example that fetches the CLOBs as // strings instead. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "truncate table DemoCLOBs" #define SQL_TEXT_2 "insert into DemoCLOBs values (:1, :2)" #define SQL_TEXT_3 "select IntCol, ClobCol from DemoCLOBs" #define NUM_ROWS 10 #define LOB_SIZE_INCREMENT 25000 #define MAX_LOB_SIZE NUM_ROWS * LOB_SIZE_INCREMENT //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiData *intColValue, *clobColValue; dpiVar *intColVar, *clobColVar; dpiNativeTypeNum nativeTypeNum; char buffer[MAX_LOB_SIZE]; dpiQueryInfo queryInfo; uint64_t clobSize; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // truncate table if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); // populate with a number of rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &clobColVar, &clobColValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, clobColVar) < 0) return dpiSamples_showError(); for (i = 0; i < NUM_ROWS; i++) { dpiData_setInt64(intColValue, i + 1); intColValue->value.asInt64 = i + 1; memset(buffer, i + 'A', LOB_SIZE_INCREMENT * (i + 1)); if (dpiVar_setFromBytes(clobColVar, 0, buffer, LOB_SIZE_INCREMENT * (i + 1)) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); } if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); if (dpiVar_release(intColVar) < 0) return dpiSamples_showError(); if (dpiVar_release(clobColVar) < 0) return dpiSamples_showError(); // fetch rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_3, strlen(SQL_TEXT_3), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intColValue) < 0 || dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &clobColValue) < 0) return dpiSamples_showError(); if (dpiLob_getSize(clobColValue->value.asLOB, &clobSize) < 0) return dpiSamples_showError(); printf("Row: IntCol = %" PRId64 ", ClobCol = CLOB(%" PRIu64 ")\n", intColValue->value.asInt64, clobSize); } // display description of each variable for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoCLOBsAsStrings.c000066400000000000000000000134771510466437300176630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoCLOBsAsStrings.c // Populates a table containing CLOBs and then fetches them without using // LOB locators, but directly as strings. For smaller sized LOBs (up to a few // megabytes in size, depending on platform and configuration) this can // significantly improve performance as there are fewer round trips to the // database that are required. // // See DemoCLOB.c for a similar example but which fetches the CLOBs as // LOB locators instead. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "truncate table DemoCLOBs" #define SQL_TEXT_2 "insert into DemoCLOBs values (:1, :2)" #define SQL_TEXT_3 "select IntCol, ClobCol from DemoCLOBs" #define NUM_ROWS 10 #define LOB_SIZE_INCREMENT 25000 #define MAX_LOB_SIZE NUM_ROWS * LOB_SIZE_INCREMENT //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiData *intColValue, *clobColValue; dpiVar *intColVar, *clobColVar; char buffer[MAX_LOB_SIZE]; dpiQueryInfo queryInfo; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // truncate table if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); // populate with a number of rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, NUM_ROWS, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, NUM_ROWS, 0, 0, 0, NULL, &clobColVar, &clobColValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, clobColVar) < 0) return dpiSamples_showError(); for (i = 0; i < NUM_ROWS; i++) { dpiData_setInt64(intColValue, i + 1); memset(buffer, i + 'A', LOB_SIZE_INCREMENT * (i + 1)); if (dpiVar_setFromBytes(clobColVar, 0, buffer, LOB_SIZE_INCREMENT * (i + 1)) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); } if (dpiStmt_release(stmt) < 0) return dpiSamples_showError(); // fetch rows if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_3, strlen(SQL_TEXT_3), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, NUM_ROWS) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 2, clobColVar) < 0) return dpiSamples_showError(); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; printf("Row: IntCol = %" PRId64 ", ClobCol = CLOB(%" PRIu32 ")\n", intColValue[bufferRowIndex].value.asInt64, clobColValue[bufferRowIndex].value.asBytes.length); } if (dpiVar_release(intColVar) < 0) return dpiSamples_showError(); if (dpiVar_release(clobColVar) < 0) return dpiSamples_showError(); // display description of each variable for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoCQN.c000066400000000000000000000126011510466437300155300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoCQN.c // Demos continuous query notification. //----------------------------------------------------------------------------- #ifdef _WIN32 #include #define sleep(seconds) Sleep(seconds * 1000) #else #include #endif #include "SampleLib.h" #define SQL_TEXT "select * from DemoTempTable" //----------------------------------------------------------------------------- // DemoCallback() // Demo callback for continuous query notification. //----------------------------------------------------------------------------- void DemoCallback(void *context, dpiSubscrMessage *message) { dpiSubscrMessageQuery *query; dpiSubscrMessageTable *table; dpiSubscrMessageRow *row; uint32_t i, j, k; // check for error if (message->errorInfo) { fprintf(stderr, "ERROR: %.*s (%s: %s)\n", message->errorInfo->messageLength, message->errorInfo->message, message->errorInfo->fnName, message->errorInfo->action); return; } // display contents of message printf("===========================================================\n"); printf("NOTIFICATION RECEIVED from database %.*s (EVENT TYPE %d)\n", message->dbNameLength, message->dbName, message->eventType); printf("===========================================================\n"); for (i = 0; i < message->numQueries; i++) { query = &message->queries[i]; printf("--> Query ID: %" PRIu64 "\n", query->id); for (j = 0; j < query->numTables; j++) { table = &query->tables[j]; printf("--> --> Table Name: %.*s\n", table->nameLength, table->name); printf("--> --> Table Operation: %d\n", table->operation); if (table->numRows > 0) { printf("--> --> Table Rows:\n"); for (k = 0; k < table->numRows; k++) { row = &table->rows[k]; printf("--> --> --> ROWID: %.*s\n", row->rowidLength, row->rowid); printf("--> --> --> Operation: %d\n", row->operation); } } } } } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiCommonCreateParams commonParams; dpiSubscrCreateParams createParams; uint32_t numQueryColumns, i; dpiSampleParams *params; dpiSubscr *subscr; uint64_t queryId; dpiStmt *stmt; dpiConn *conn; // connect to database // NOTE: events mode must be configured params = dpiSamples_getParams(); if (dpiContext_initCommonCreateParams(params->context, &commonParams) < 0) return dpiSamples_showError(); commonParams.createMode = DPI_MODE_CREATE_EVENTS; conn = dpiSamples_getConn(0, &commonParams); // create subscription if (dpiContext_initSubscrCreateParams(params->context, &createParams) < 0) return dpiSamples_showError(); createParams.qos = DPI_SUBSCR_QOS_QUERY | DPI_SUBSCR_QOS_ROWIDS; createParams.callback = DemoCallback; if (dpiConn_subscribe(conn, &createParams, &subscr) < 0) return dpiSamples_showError(); printf("Created subscription with registration id %" PRIu64 "\n", createParams.outRegId); // register query if (dpiSubscr_prepareStmt(subscr, SQL_TEXT, strlen(SQL_TEXT), &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_getSubscrQueryId(stmt, &queryId) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); printf("Registered query with id %" PRIu64 "\n\n", queryId); // wait for events to come through printf("In another session, modify the results of the query\n\n%s\n\n", SQL_TEXT); printf("Use Ctrl-C to terminate or wait for 100 seconds\n"); for (i = 0; i < 20; i++) { printf("Waiting for notifications...\n"); sleep(5); } // clean up dpiSubscr_release(subscr); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoCallProc.c000066400000000000000000000067141510466437300166160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoCallProc.c // Demos simple call of stored procedure with in, in/out and out variables. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "begin proc_Demo(:1, :2, :3); end;" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *inOutValue, *outValue, inValue; dpiVar *inOutVar, *outVar; uint32_t numQueryColumns; dpiStmt *stmt; dpiConn *conn; // connect to database and create statement conn = dpiSamples_getConn(0, NULL); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // bind IN value inValue.isNull = 0; inValue.value.asBytes.ptr = "In value for demoing"; inValue.value.asBytes.length = strlen("In value for demoing"); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_BYTES, &inValue) < 0) return dpiSamples_showError(); // bind IN/OUT variable if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &inOutVar, &inOutValue) < 0) return dpiSamples_showError(); inOutValue->isNull = 0; inOutValue->value.asInt64 = 347; if (dpiStmt_bindByPos(stmt, 2, inOutVar) < 0) return dpiSamples_showError(); // bind OUT variable if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &outVar, &outValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 3, outVar) < 0) return dpiSamples_showError(); // perform execution if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // display value of IN/OUT variable printf("IN/OUT value (after call) is %" PRId64 "\n", inOutValue->value.asInt64); dpiVar_release(inOutVar); // display value of OUT variable printf("OUT value (after call) is %" PRId64 "\n", outValue->value.asInt64); dpiVar_release(outVar); // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoConvertNumbers.c000066400000000000000000000104501510466437300200630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoConvertNumbers.c // Demos conversion of numbers to strings and strings to numbers. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "select :1 from dual" static const char *numbersToConvert[] = { "0", "1", "-1", "10", "-10", "100", "-100", "0.1", "-0.1", "0.01", "-0.01", "0.001", "-0.001", ".100004", "-.100004", "1234567890123456789012345678901234567891", "-1234567890123456789012345678901234567891", "1.2345E20", "-1.2345E+20", "9e125", "-9e125", "9e-130", "-9e-130", "9.99999999999999999999999999999999999999E-130", "-9.99999999999999999999999999999999999999E-130", NULL }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, ix; dpiData *inputValue, *outputValue; dpiVar *inputVar, *outputVar; const char *inputStringValue; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(1, NULL); // create variables for the input and output values if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &inputVar, &inputValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &outputVar, &outputValue) < 0) return dpiSamples_showError(); // prepare and execute statement for each of the numbers to convert if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, inputVar) < 0) return dpiSamples_showError(); // perform query for each string in the array ix = 0; while (1) { inputStringValue = numbersToConvert[ix++]; if (!inputStringValue) break; printf(" INPUT: |%s|\n", inputStringValue); if (dpiVar_setFromBytes(inputVar, 0, inputStringValue, strlen(inputStringValue)) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, outputVar) < 0) return dpiSamples_showError(); // fetch rows while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; printf("OUTPUT: |%.*s|\n", outputValue->value.asBytes.length, outputValue->value.asBytes.ptr); } } // clean up dpiVar_release(inputVar); dpiVar_release(outputVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoCreateSodaColl.c000066400000000000000000000052721510466437300177410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoCreateSodaColl.c // Demos creating a SODA collection with the specified name. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t tempLength; const char *temp; dpiSodaColl *coll; dpiSodaDb *db; char *name; // determine name of collection to create if (argc != 2) { fprintf(stderr, "Usage: DemoCreateSodaColl \n"); return 1; } name = argv[1]; printf("Creating SODA collection named %s\n", name); // connect to database db = dpiSamples_getSodaDb(); // create new SODA collection if (dpiSodaDb_createCollection(db, name, strlen(name), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); // get the name of the collection if (dpiSodaColl_getName(coll, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Name of created collection: %.*s\n", tempLength, temp); // get the metadata of the collection if (dpiSodaColl_getMetadata(coll, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Metadata of created collection: %.*s\n", tempLength, temp); // clean up dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoDMLReturning.c000066400000000000000000000122021510466437300174160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoDMLReturning.c // Demos DML returning clause which returns multiple rows. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "truncate table DemoTempTable" #define SQL_TEXT_2 "begin " \ " for i in 1..10 loop " \ " insert into DemoTempTable values (i, " \ " 'Demo String ' || i); " \ " end loop; " \ "end;" #define SQL_TEXT_3 "delete from DemoTempTable " \ "where IntCol <= :inIntCol " \ "returning IntCol, StringCol " \ "into :outIntCol, :outStrCol" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *inIntColData, *outIntColData, *outStrColData; dpiVar *inIntColVar, *outIntColVar, *outStrColVar; uint32_t numQueryColumns, numRows, i; dpiStmt *stmt; dpiConn *conn; // connect to database conn = dpiSamples_getConn(1, NULL); // truncate table printf("Truncating table...\n"); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // populate table printf("Populating table...\n"); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &inIntColVar, &inIntColData) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &outIntColVar, &outIntColData) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 0, 0, NULL, &outStrColVar, &outStrColData) < 0) return dpiSamples_showError(); // prepare and execute delete statement with DML returning clause printf("Deleting rows with DML returning...\n"); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_3, strlen(SQL_TEXT_3), NULL, 0, &stmt) < 0) return dpiSamples_showError(); inIntColData->isNull = 0; inIntColData->value.asInt64 = 4; if (dpiStmt_bindByPos(stmt, 1, inIntColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, outIntColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 3, outStrColVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // get the data and number of rows returned if (dpiVar_getReturnedData(outIntColVar, 0, &numRows, &outIntColData) < 0) return dpiSamples_showError(); if (dpiVar_getReturnedData(outStrColVar, 0, &numRows, &outStrColData) < 0) return dpiSamples_showError(); printf("%d rows returned.\n", numRows); // display the output from the rows for (i = 0; i < numRows; i++) printf("IntCol = %" PRId64 ", StrCol = %.*s\n", outIntColData[i].value.asInt64, outStrColData[i].value.asBytes.length, outStrColData[i].value.asBytes.ptr); // clean up dpiVar_release(inIntColVar); dpiVar_release(outIntColVar); dpiVar_release(outStrColVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoDistribTrans.c000066400000000000000000000100151510466437300175140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoDistribTrans.c // Demos simple handling of distributed transactions. //----------------------------------------------------------------------------- #include "SampleLib.h" #define DELETE_TEXT "delete from DemoTempTable" #define INSERT_TEXT "insert into DemoTempTable values (:1, :2)" #define FORMAT_ID 100 #define TRANSACTION_ID "123" #define BRANCH_ID "456" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData intColValue, stringColValue; uint32_t numQueryColumns; uint64_t rowCount; int commitNeeded; dpiStmt *stmt; dpiConn *conn; dpiXid xid; // connect to database conn = dpiSamples_getConn(0, NULL); // start distributed transaction xid.formatId = FORMAT_ID; xid.globalTransactionId = TRANSACTION_ID; xid.globalTransactionIdLength = strlen(TRANSACTION_ID); xid.branchQualifier = BRANCH_ID; xid.branchQualifierLength = strlen(BRANCH_ID); if (dpiConn_tpcBegin(conn, &xid, 0, DPI_TPC_BEGIN_NEW) < 0) return dpiSamples_showError(); // perform delete if (dpiConn_prepareStmt(conn, 0, DELETE_TEXT, strlen(DELETE_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); printf("%" PRIu64 " rows deleted.\n", rowCount); dpiStmt_release(stmt); // perform insert if (dpiConn_prepareStmt(conn, 0, INSERT_TEXT, strlen(INSERT_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); intColValue.isNull = 0; stringColValue.isNull = 0; intColValue.value.asInt64 = 1; if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &intColValue) < 0) return dpiSamples_showError(); stringColValue.value.asBytes.ptr = "DEMO 1"; stringColValue.value.asBytes.length = strlen("DEMO 1"); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &stringColValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); printf("%" PRIu64 " rows inserted.\n", rowCount); // prepare transaction for commit if (dpiConn_tpcPrepare(conn, NULL, &commitNeeded) < 0) return dpiSamples_showError(); // commit changes if (commitNeeded && dpiConn_commit(conn) < 0) return dpiSamples_showError(); // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoDropSodaColl.c000066400000000000000000000046641510466437300174460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoDropSodaColl.c // Demos dropping a SODA collection with the specified name. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiSodaColl *coll; dpiSodaDb *db; char *name; // determine name of collection to drop if (argc != 2) { fprintf(stderr, "Usage: DemoDropSodaColl \n"); return 1; } name = argv[1]; // connect to database db = dpiSamples_getSodaDb(); // open the SODA collection first if (dpiSodaDb_openCollection(db, name, strlen(name), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", name); return 1; } // drop collection printf("Dropping SODA collection named %s\n", name); if (dpiSodaColl_drop(coll, DPI_SODA_FLAGS_DEFAULT, NULL) < 0) return dpiSamples_showError(); // clean up dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoFetch.c000066400000000000000000000143101510466437300161370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoFetch.c // Demos simple fetch of numbers and strings. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "select IntCol, StringCol, RawCol, rowid " \ "from DemoStrings " \ "where IntCol > :intCol" #define SQL_TEXT_2 "select IntCol " \ "from DemoStrings " \ "where rowid = :1" #define BIND_NAME "intCol" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *intColValue, *stringColValue, *rawColValue, *rowidValue; uint32_t numQueryColumns, bufferRowIndex, i, rowidAsStringLength; dpiData bindValue, *bindRowidValue; dpiNativeTypeNum nativeTypeNum; const char *rowidAsString; dpiQueryInfo queryInfo; dpiVar *rowidVar; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(1, NULL); // create variable for storing the rowid of one of the rows if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_ROWID, DPI_NATIVE_TYPE_ROWID, 1, 0, 0, 0, NULL, &rowidVar, &bindRowidValue) < 0) return dpiSamples_showError(); // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); bindValue.value.asInt64 = 7; bindValue.isNull = 0; if (dpiStmt_bindValueByName(stmt, BIND_NAME, strlen(BIND_NAME), DPI_NATIVE_TYPE_INT64, &bindValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 0, 0, NULL) < 0) return dpiSamples_showError(); // fetch rows printf("Fetch rows with IntCol > %" PRId64 "\n", bindValue.value.asInt64); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intColValue) < 0 || dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &stringColValue) < 0 || dpiStmt_getQueryValue(stmt, 3, &nativeTypeNum, &rawColValue) < 0 || dpiStmt_getQueryValue(stmt, 4, &nativeTypeNum, &rowidValue) < 0) return dpiSamples_showError(); if (dpiRowid_getStringValue(rowidValue->value.asRowid, &rowidAsString, &rowidAsStringLength) < 0) return dpiSamples_showError(); printf("Row: Int = %.*s, String = '%.*s', Raw = '%.*s', " "Rowid = '%.*s'\n", intColValue->value.asBytes.length, intColValue->value.asBytes.ptr, stringColValue->value.asBytes.length, stringColValue->value.asBytes.ptr, rawColValue->value.asBytes.length, rawColValue->value.asBytes.ptr, rowidAsStringLength, rowidAsString); if (dpiVar_setFromRowid(rowidVar, 0, rowidValue->value.asRowid) < 0) return dpiSamples_showError(); } printf("\n"); // display description of each variable printf("Display column metadata\n"); for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } printf("\n"); printf("Fetch rows with rowid = %.*s\n", rowidAsStringLength, rowidAsString); dpiStmt_release(stmt); // prepare and execute statement to fetch by rowid if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, rowidVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // fetch rows while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intColValue) < 0) return dpiSamples_showError(); printf("Row: Int = %" PRId64 "\n", intColValue->value.asInt64); } // clean up dpiVar_release(rowidVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoFetchDates.c000066400000000000000000000107161510466437300171260ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoFetchDates.c // Demos simple fetch of dates. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "select * from DemoTimestamps" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiData *intColValue, *timestampColValue; dpiNativeTypeNum nativeTypeNum; dpiTimestamp *timestamp; dpiQueryInfo queryInfo; dpiStmt *stmt; dpiConn *conn; char sign; int found; // connect to database conn = dpiSamples_getConn(1, NULL); // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // fetch rows while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intColValue) < 0) return dpiSamples_showError(); printf("Row: IntCol = %" PRId64 "\n", intColValue->value.asInt64); for (i = 1; i < numQueryColumns; i++) { if (dpiStmt_getQueryValue(stmt, i + 1, &nativeTypeNum, ×tampColValue) < 0) return dpiSamples_showError(); if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf(" %-18.*s = ", queryInfo.nameLength, queryInfo.name); if (timestampColValue->isNull) printf("null\n"); else { timestamp = ×tampColValue->value.asTimestamp; printf("%4d-%.2d-%.2d %.2d:%.2d:%.2d.%.6d", timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second, timestamp->fsecond); if (queryInfo.typeInfo.oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_TZ) { sign = (timestamp->tzHourOffset < 0 || timestamp->tzMinuteOffset < 0) ? '-' : '+'; printf(" %c%.2d:%.2d", sign, abs(timestamp->tzHourOffset), abs(timestamp->tzMinuteOffset)); } printf("\n"); } } } // display description of each variable for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoFetchJSON.c000066400000000000000000000131121510466437300166300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2020, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoFetchJSON.c // Demos fetching JSON values from the database. This requires Oracle Client // and Oracle Database to both be 20 or higher. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL "select" \ " json_array(" \ " json_scalar(1)," \ " json_scalar('String value')," \ " json_object(" \ " key 'Fred' value json_scalar(5)," \ " key 'George' value json_scalar('A string')" \ " returning json)," \ " json_array(" \ " json_scalar(utl_raw.cast_to_raw('A raw'))," \ " json_scalar(sysdate - 1)," \ " json_scalar(systimestamp + 1)" \ " returning json)" \ " returning json) " \ "from dual" //----------------------------------------------------------------------------- // displayJson() //----------------------------------------------------------------------------- void displayJson(dpiJsonNode *node, uint32_t indentLevel, int printIndent) { dpiTimestamp *timestamp; dpiJsonArray *array; dpiJsonObject *obj; uint32_t i, j; if (printIndent) { printf("\n"); for (i = 0; i < indentLevel; i++) printf(" "); } switch (node->nativeTypeNum) { case DPI_NATIVE_TYPE_DOUBLE: printf("%g", node->value->asDouble); break; case DPI_NATIVE_TYPE_BYTES: printf("'%.*s'", node->value->asBytes.length, node->value->asBytes.ptr); break; case DPI_NATIVE_TYPE_TIMESTAMP: timestamp = &node->value->asTimestamp; printf("%.4d-%.2d-%.2d %.2d:%.2d:%.2d", timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second); break; case DPI_NATIVE_TYPE_JSON_ARRAY: array = &node->value->asJsonArray; printf("["); for (i = 0; i < array->numElements; i++) { if (i > 0) printf(","); displayJson(&array->elements[i], indentLevel + 1, 1); } printf("\n"); for (i = 0; i < indentLevel; i++) printf(" "); printf("]"); break; case DPI_NATIVE_TYPE_JSON_OBJECT: obj = &node->value->asJsonObject; printf("{"); for (i = 0; i < obj->numFields; i++) { if (i > 0) printf(","); printf("\n"); for (j = 0; j < indentLevel + 1; j++) printf(" "); printf("'%.*s': ", obj->fieldNameLengths[i], obj->fieldNames[i]); displayJson(&obj->fields[i], indentLevel + 1, 0); } printf("\n"); for (i = 0; i < indentLevel; i++) printf(" "); printf("}"); break; default: printf("Unhandled native type %u", node->nativeTypeNum); } } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiData *jsonColValue; dpiJsonNode *topNode; dpiConn *conn; dpiStmt *stmt; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // perform query if (dpiConn_prepareStmt(conn, 0, SQL, strlen(SQL), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiSamples_showError(); // fetch row if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &jsonColValue) < 0) return dpiSamples_showError(); if (dpiJson_getValue(jsonColValue->value.asJson, DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiSamples_showError(); // display results printf("JSON value:\n"); displayJson(topNode, 0, 0); printf("\n"); return 0; } odpi-5.6.4/samples/DemoFetchObjects.c000066400000000000000000000122631510466437300174560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoFetchObjects.c // Demos simple fetch of objects. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "select ObjectCol " \ "from DemoObjects " \ "order by IntCol" #define NUM_ATTRS 7 #define NUM_DISPLAY_ATTRS 5 //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiObjectAttr *attrs[NUM_ATTRS]; dpiData *objColValue, attrValue; dpiNativeTypeNum nativeTypeNum; dpiObjectTypeInfo typeInfo; dpiObjectAttrInfo attrInfo; dpiTimestamp *timestamp; dpiQueryInfo queryInfo; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(1, NULL); // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // get object type and attributes if (dpiStmt_getQueryInfo(stmt, 1, &queryInfo) < 0) return dpiSamples_showError(); if (dpiObjectType_getAttributes(queryInfo.typeInfo.objectType, NUM_ATTRS, attrs) < 0) return dpiSamples_showError(); if (dpiObjectType_getInfo(queryInfo.typeInfo.objectType, &typeInfo) < 0) return dpiSamples_showError(); printf("Fetching objects of type %.*s.%.*s\n", typeInfo.schemaLength, typeInfo.schema, typeInfo.nameLength, typeInfo.name); // fetch rows while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &objColValue) < 0) return dpiSamples_showError(); if (objColValue->isNull) printf("Row: ObjCol = null\n"); else { printf("Row: objCol =\n"); for (i = 0; i < NUM_DISPLAY_ATTRS; i++) { if (dpiObjectAttr_getInfo(attrs[i], &attrInfo) < 0) return dpiSamples_showError(); printf(" %.*s => ", attrInfo.nameLength, attrInfo.name); if (dpiObject_getAttributeValue(objColValue->value.asObject, attrs[i], attrInfo.typeInfo.defaultNativeTypeNum, &attrValue) < 0) return dpiSamples_showError(); if (attrValue.isNull) printf("null\n"); else { switch (attrInfo.typeInfo.defaultNativeTypeNum) { case DPI_NATIVE_TYPE_BYTES: printf("'%.*s'\n", attrValue.value.asBytes.length, attrValue.value.asBytes.ptr); break; case DPI_NATIVE_TYPE_DOUBLE: printf("%.g\n", attrValue.value.asDouble); break; case DPI_NATIVE_TYPE_TIMESTAMP: timestamp = &attrValue.value.asTimestamp; printf("%.2d/%.2d/%.2d %.2d:%.2d:%.2d\n", timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second); break; default: printf("???\n"); break; } } } } } // clean up for (i = 0; i < NUM_ATTRS; i++) dpiObjectAttr_release(attrs[i]); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoGetAllSodaDocs.c000066400000000000000000000100621510466437300176760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoGetAllSodaDocs.c // Demos getting all documents from a SODA collection. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { const char *collectionName, *temp, *encoding; dpiSodaDocCursor *cursor; uint32_t tempLength; dpiSodaColl *coll; dpiSodaDoc *doc; dpiSodaDb *db; // determine name of collection and key of document to retrieve if (argc != 2) { fprintf(stderr, "Usage: DemoGetSodaDoc \n"); return 1; } collectionName = argv[1]; // connect to database db = dpiSamples_getSodaDb(); // open existing SODA collection if (dpiSodaDb_openCollection(db, collectionName, strlen(collectionName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", collectionName); return 1; } // find all documents in the collection if (dpiSodaColl_find(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiSamples_showError(); // iterate over the cursor until no more documents are found while (1) { // get next document from the cursor if (dpiSodaDocCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiSamples_showError(); if (!doc) break; // print details about the document printf("Document Details:\n"); if (dpiSodaDoc_getKey(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Key -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getContent(doc, &temp, &tempLength, &encoding) < 0) return dpiSamples_showError(); printf("Content -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getMediaType(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Media Type -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getVersion(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Version -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getCreatedOn(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Created -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getLastModified(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Last Modified -> %.*s\n\n", tempLength, temp); // free document if (dpiSodaDoc_release(doc) < 0) return dpiSamples_showError(); } // clean up dpiSodaDocCursor_release(cursor); dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoGetSodaCollNames.c000066400000000000000000000052661510466437300202440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoGetSodaCollNames.c // Demos getting the names of all SODA collections using the method // dpiSodaDb_getCollectionNames(). //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t startingNameLength, i; dpiSodaCollNames collNames; const char *startingName; dpiSodaDb *db; // determine starting name to use; no parameters means all collections if (argc < 2) { startingName = NULL; startingNameLength = 0; printf("Getting all SODA collection names\n"); } else { startingName = argv[1]; startingNameLength = strlen(startingName); printf("Getting all SODA collection names starting with %s\n", startingName); } // connect to database db = dpiSamples_getSodaDb(); // get all collection names if (dpiSodaDb_getCollectionNames(db, startingName, startingNameLength, 0, DPI_SODA_FLAGS_DEFAULT, &collNames) < 0) return dpiSamples_showError(); for (i = 0; i < collNames.numNames; i++) printf("Collection: %.*s\n", collNames.nameLengths[i], collNames.names[i]); // clean up dpiSodaDb_freeCollectionNames(db, &collNames); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoGetSodaDoc.c000066400000000000000000000077361510466437300171000ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoGetSodaDoc.c // Demos getting a document from a SODA collection with the specified key. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { const char *collectionName, *key, *temp, *encoding; dpiSodaOperOptions options; dpiSampleParams *params; uint32_t tempLength; dpiSodaColl *coll; dpiSodaDoc *doc; dpiSodaDb *db; // determine name of collection and key of document to retrieve if (argc != 3) { fprintf(stderr, "Usage: DemoGetSodaDoc \n"); return 1; } collectionName = argv[1]; key = argv[2]; // connect to database db = dpiSamples_getSodaDb(); // open existing SODA collection if (dpiSodaDb_openCollection(db, collectionName, strlen(collectionName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", collectionName); return 1; } // build options params = dpiSamples_getParams(); if (dpiContext_initSodaOperOptions(params->context, &options) < 0) return dpiSamples_showError(); options.key = key; options.keyLength = strlen(key); // get document from the collection if (dpiSodaColl_findOne(coll, &options, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiSamples_showError(); if (!doc) { printf("No document with key %s\n", key); return 1; } // print some details about the retrieved document printf("Document Details:\n"); if (dpiSodaDoc_getKey(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Key -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getContent(doc, &temp, &tempLength, &encoding) < 0) return dpiSamples_showError(); printf("Content -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getMediaType(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Media Type -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getVersion(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Version -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getCreatedOn(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Created -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getLastModified(doc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Last Modified -> %.*s\n", tempLength, temp); // clean up dpiSodaDoc_release(doc); dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoImplicitResults.c000066400000000000000000000076121510466437300202510ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoImplicitResults.c // Demos fetch of implicit results. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "declare " \ " c1 sys_refcursor; " \ " c2 sys_refcursor; " \ "begin " \ " " \ " open c1 for " \ " select NumberCol " \ " from DemoNumbers " \ " where IntCol between 3 and 5; " \ " " \ " dbms_sql.return_result(c1); " \ " " \ " open c2 for " \ " select NumberCol " \ " from DemoNumbers " \ " where IntCol between 7 and 10; " \ " " \ " dbms_sql.return_result(c2); " \ "end;" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex; dpiNativeTypeNum nativeTypeNum; dpiStmt *stmt, *resultStmt; dpiData *doubleValue; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(1, NULL); // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // retrieve from implicit results while (1) { // get implicit result if (dpiStmt_getImplicitResult(stmt, &resultStmt) < 0) return dpiSamples_showError(); if (!resultStmt) break; // fetch from cursor printf("----------------------------------------------------------\n"); while (1) { if (dpiStmt_fetch(resultStmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(resultStmt, 1, &nativeTypeNum, &doubleValue) < 0) return dpiSamples_showError(); printf("Row: NumberValue = %g\n", doubleValue->value.asDouble); } dpiStmt_release(resultStmt); } // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoInOutTempLobs.c000066400000000000000000000176311510466437300176230ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoInOutTempLobs.c // Demos whether temporary LOBs passed to a PL/SQL procedure are processed // correctly without leaks. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_1 "begin pkg_DemoLOBs." \ "DemoInOutTempClob(:1, :2); end;" #define SQL_TEXT_2 "select sid from v$session " \ "where audsid = userenv('sessionid')" #define SQL_TEXT_3 "select cache_lobs, nocache_lobs, " \ "abstract_lobs " \ "from v$temporary_lobs " \ "where sid = :sid" #define LOB_TEXT "This is but a demo!" //----------------------------------------------------------------------------- // GetNumTempLobs() // Calculate and print the number of temporary LOBs for the current session. //----------------------------------------------------------------------------- int GetNumTempLobs(dpiConn *conn, int64_t sid) { dpiData *cacheLobsData, *nocacheLobsData, *abstractLobsData, *sidData; dpiVar *cacheLobsVar, *nocacheLobsVar, *abstractLobsVar, *sidVar; uint32_t numQueryColumns, bufferRowIndex; dpiStmt *stmt; int found; // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_3, strlen(SQL_TEXT_3), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &sidVar, &sidData) < 0) return dpiSamples_showError(); sidData->value.asInt64 = sid; sidData->isNull = 0; if (dpiStmt_bindByPos(stmt, 1, sidVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); dpiVar_release(sidVar); // fetch row from database if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &cacheLobsVar, &cacheLobsData) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &nocacheLobsVar, &nocacheLobsData) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &abstractLobsVar, &abstractLobsData) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, cacheLobsVar) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 2, nocacheLobsVar) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 3, abstractLobsVar) < 0) return dpiSamples_showError(); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) { fprintf(stderr, "No row found for sid %" PRId64 "!\n", sid); return -1; } // display result and clean up printf("Temporary LOBS: cache: %" PRId64 ", nocache: %" PRId64 ", abstract: %" PRId64 "\n", cacheLobsData->value.asInt64, nocacheLobsData->value.asInt64, abstractLobsData->value.asInt64); dpiVar_release(cacheLobsVar); dpiVar_release(nocacheLobsVar); dpiVar_release(abstractLobsVar); dpiStmt_release(stmt); return 0; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex; dpiData *sidValue, *lobValue, *intValue; dpiVar *sidVar, *lobVar, *intVar; dpiStmt *stmt; dpiConn *conn; uint64_t sid; dpiLob *lob; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // fetch SID if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_2, strlen(SQL_TEXT_2), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &sidVar, &sidValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, sidVar) < 0) return dpiSamples_showError(); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) { fprintf(stderr, "No row found for current session!?\n"); return -1; } sid = sidValue->value.asInt64; dpiVar_release(sidVar); dpiStmt_release(stmt); printf("SID of current session is %" PRId64 "\n", sid); // display the number of temporary LOBs at this point (should be 0) if (GetNumTempLobs(conn, sid) < 0) return -1; // create new temporary LOB and populate it if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiSamples_showError(); if (dpiLob_setFromBytes(lob, LOB_TEXT, strlen(LOB_TEXT)) < 0) return dpiSamples_showError(); // display the number of temporary LOBs at this point (should be 1) if (GetNumTempLobs(conn, sid) < 0) return -1; // prepare bind variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &intVar, &intValue) < 0) return dpiSamples_showError(); intValue->isNull = 0; intValue->value.asInt64 = 1; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_CLOB, DPI_NATIVE_TYPE_LOB, 1, 0, 0, 0, NULL, &lobVar, &lobValue) < 0) return dpiSamples_showError(); if (dpiVar_setFromLob(lobVar, 0, lob) < 0) return dpiSamples_showError(); // call stored procedure if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_1, strlen(SQL_TEXT_1), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, lobVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiConn_commit(conn) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); dpiVar_release(intVar); dpiVar_release(lobVar); dpiLob_release(lob); // display the number of temporary LOBs at this point (should be 0) if (GetNumTempLobs(conn, sid) < 0) return -1; // clean up dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoInsert.c000066400000000000000000000111171510466437300163540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoInsert.c // Demos simple insert of numbers and strings. //----------------------------------------------------------------------------- #include "SampleLib.h" #define DELETE_TEXT "delete from DemoTempTable" #define INSERT_TEXT "insert into DemoTempTable values (:1, :2)" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData intColValue, stringColValue; uint32_t rowidStrLength; const char *rowidStr; uint64_t rowCount; dpiRowid *rowid; dpiStmt *stmt; dpiConn *conn; // connect to database and create statement conn = dpiSamples_getConn(0, NULL); if (dpiConn_prepareStmt(conn, 0, DELETE_TEXT, strlen(DELETE_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // perform delete if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); printf("%" PRIu64 " rows deleted.\n", rowCount); dpiStmt_release(stmt); // prepare insert statement for execution if (dpiConn_prepareStmt(conn, 0, INSERT_TEXT, strlen(INSERT_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); intColValue.isNull = 0; stringColValue.isNull = 0; // create first row intColValue.value.asInt64 = 1; if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &intColValue) < 0) return dpiSamples_showError(); stringColValue.value.asBytes.ptr = "DEMO 1"; stringColValue.value.asBytes.length = strlen("DEMO 1"); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &stringColValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiSamples_showError(); if (dpiRowid_getStringValue(rowid, &rowidStr, &rowidStrLength)) return dpiSamples_showError(); printf("%" PRIu64 " row inserted (rowid %.*s).\n", rowCount, rowidStrLength, rowidStr); // create second row intColValue.value.asInt64 = 2; if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &intColValue) < 0) return dpiSamples_showError(); stringColValue.value.asBytes.ptr = "DEMO #2"; stringColValue.value.asBytes.length = strlen("DEMO #2"); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &stringColValue) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiSamples_showError(); if (dpiRowid_getStringValue(rowid, &rowidStr, &rowidStrLength)) return dpiSamples_showError(); printf("%" PRIu64 " row inserted (rowid %.*s).\n", rowCount, rowidStrLength, rowidStr); // commit changes if (dpiConn_commit(conn) < 0) return dpiSamples_showError(); // clean up dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoInsertAsArray.c000066400000000000000000000102411510466437300176340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoInsertAsArray.c // Demos simple insert of numbers and strings using array bind. //----------------------------------------------------------------------------- #include "SampleLib.h" #define DELETE_TEXT "delete from DemoTempTable" #define INSERT_TEXT "insert into DemoTempTable values (:1, :2)" #define NUM_ROWS 5 static int gc_IntColValues[NUM_ROWS] = { 3, 5, 7, 9, 11 }; static const char *gc_StringColValues[NUM_ROWS] = { "DEMO 1", "DEMO ROW 2", "DEMO #3", "DEMO ROW 4", "DEMO ROW #5" }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiData *intColValue, *stringColValue; dpiVar *intColVar, *stringColVar; uint32_t numQueryColumns, i; uint64_t rowCount; dpiStmt *stmt; dpiConn *conn; // connect to database and create statement conn = dpiSamples_getConn(0, NULL); if (dpiConn_prepareStmt(conn, 0, DELETE_TEXT, strlen(DELETE_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // perform delete if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); printf("%" PRIu64 " rows deleted.\n", rowCount); dpiStmt_release(stmt); // prepare insert statement for execution if (dpiConn_prepareStmt(conn, 0, INSERT_TEXT, strlen(INSERT_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, NUM_ROWS, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, NUM_ROWS, 20, 0, 0, NULL, &stringColVar, &stringColValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, stringColVar) < 0) return dpiSamples_showError(); // populate data for (i = 0; i < NUM_ROWS; i++) { intColValue[i].isNull = 0; intColValue[i].value.asInt64 = gc_IntColValues[i]; if (dpiVar_setFromBytes(stringColVar, i, gc_StringColValues[i], strlen(gc_StringColValues[i])) < 0) return dpiSamples_showError(); } if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, NUM_ROWS) < 0) return dpiSamples_showError(); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiSamples_showError(); printf("%" PRIu64 " rows inserted.\n", rowCount); // commit changes if (dpiConn_commit(conn) < 0) return dpiSamples_showError(); // clean up dpiVar_release(intColVar); dpiVar_release(stringColVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoInsertManySodaColl.c000066400000000000000000000112271510466437300206240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoInsertManySodaColl.c // Demos inserting many documents into a SODA collection with the specified // contents. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { const char *collectionName, *temp, *encoding; dpiSodaDoc **docs, **insertedDocs; uint32_t numDocs, i, tempLength; dpiSodaColl *coll; dpiSodaDb *db; // determine name of collection to insert into and number of documents if (argc < 3) { fprintf(stderr, "Usage: DemoInsertManySodaColl ...\n"); return 1; } collectionName = argv[1]; numDocs = (uint32_t) argc - 2; // connect to database db = dpiSamples_getSodaDb(); // allocate memory for the document arrays docs = malloc(numDocs * sizeof(dpiSodaDoc*)); insertedDocs = malloc(numDocs * sizeof(dpiSodaDoc*)); if (!docs || !insertedDocs) { printf("Out of memory!\n"); return 1; } // create documents for each of the contents provided for (i = 0; i < numDocs; i++) { if (dpiSodaDb_createDocument(db, NULL, 0, argv[i + 2], strlen(argv[i + 2]), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &docs[i]) < 0) return dpiSamples_showError(); } // open existing SODA collection if (dpiSodaDb_openCollection(db, collectionName, strlen(collectionName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", collectionName); return 1; } // insert documents into collection and return them printf("Inserting %u documents into collection %s\n\n", numDocs, collectionName); if (dpiSodaColl_insertMany(coll, numDocs, docs, DPI_SODA_FLAGS_DEFAULT, insertedDocs) < 0) return dpiSamples_showError(); // display information about the documents that were just inserted for (i = 0; i < numDocs; i++) { dpiSodaDoc_release(docs[i]); printf("Document Details:\n"); if (dpiSodaDoc_getKey(insertedDocs[i], &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Key -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getContent(insertedDocs[i], &temp, &tempLength, &encoding) < 0) return dpiSamples_showError(); printf("Content -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getMediaType(insertedDocs[i], &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Media Type -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getVersion(insertedDocs[i], &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Version -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getCreatedOn(insertedDocs[i], &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Created -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getLastModified(insertedDocs[i], &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Last Modified -> %.*s\n\n", tempLength, temp); dpiSodaDoc_release(insertedDocs[i]); } // clean up dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoInsertSodaColl.c000066400000000000000000000101011510466437300177650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoInsertSodaColl.c // Demos inserting a document into a SODA collection with the specified name // and content. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { const char *collectionName, *content, *temp, *encoding; dpiSodaDoc *doc, *insertedDoc; uint32_t tempLength; dpiSodaColl *coll; dpiSodaDb *db; // determine name of collection to insert into and content of document if (argc != 3) { fprintf(stderr, "Usage: DemoInsertSodaColl \n"); return 1; } collectionName = argv[1]; content = argv[2]; // connect to database db = dpiSamples_getSodaDb(); // open existing SODA collection if (dpiSodaDb_openCollection(db, collectionName, strlen(collectionName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", collectionName); return 1; } // create SODA document using the provided content if (dpiSodaDb_createDocument(db, NULL, 0, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiSamples_showError(); // insert document into collection and return inserted document if (dpiSodaColl_insertOne(coll, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, &insertedDoc) , 0) return dpiSamples_showError(); if (dpiSodaDoc_release(doc) < 0) return dpiSamples_showError(); // display information about the document that was just inserted printf("Document Details:\n"); if (dpiSodaDoc_getKey(insertedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Key -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getContent(insertedDoc, &temp, &tempLength, &encoding) < 0) return dpiSamples_showError(); printf("Content -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getMediaType(insertedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Media Type -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getVersion(insertedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Version -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getCreatedOn(insertedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Created -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getLastModified(insertedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Last Modified -> %.*s\n", tempLength, temp); // clean up dpiSodaDoc_release(insertedDoc); dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoIterSodaColls.c000066400000000000000000000062621510466437300176240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoIterSodaColls.c // Demos iterating over the SODA collections that are available and displays // their names. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t startingNameLength, collectionNameLength; const char *startingName, *collectionName; dpiSodaCollCursor *cursor; dpiSodaColl *coll; dpiSodaDb *db; // determine starting name to use; no parameters means all collections if (argc < 2) { startingName = NULL; startingNameLength = 0; printf("Iterating all SODA collections\n"); } else { startingName = argv[1]; startingNameLength = strlen(startingName); printf("Iterating SODA collections starting with %s\n", startingName); } // connect to database db = dpiSamples_getSodaDb(); // get cursor to iterate over SODA collections if (dpiSodaDb_getCollections(db, startingName, startingNameLength, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiSamples_showError(); // iterate over collections until no more are found while (1) { // get next collection if (dpiSodaCollCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) break; // get the name of the collection if (dpiSodaColl_getName(coll, &collectionName, &collectionNameLength) < 0) return dpiSamples_showError(); printf("Collection: %.*s\n", collectionNameLength, collectionName); if (dpiSodaColl_release(coll) < 0) return dpiSamples_showError(); } // clean up dpiSodaCollCursor_release(cursor); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoLongRaws.c000066400000000000000000000125571510466437300166550ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoLongRaws.c // Demos inserting and fetching long raw columns. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_TRUNC "truncate table DemoLongRaws" #define SQL_TEXT_INSERT "insert into DemoLongRaws values (:1, :2)" #define SQL_TEXT_QUERY "select * from DemoLongRaws order by IntCol" #define ARRAY_SIZE 4 #define NUM_ROWS 13 #define SIZE_INCREMENT 75000 //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t i, longValueLength, numQueryColumns, bufferRowIndex; dpiData *intColValue, *longColValue; dpiVar *intColVar, *longColVar; char *longValue; dpiConn *conn; dpiStmt *stmt; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // truncate the table so that the demo can be repeated if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_TRUNC, strlen(SQL_TEXT_TRUNC), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // create variables for insertion if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, ARRAY_SIZE, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_RAW, DPI_NATIVE_TYPE_BYTES, ARRAY_SIZE, 0, 0, 0, NULL, &longColVar, &longColValue) < 0) return dpiSamples_showError(); // prepare insert statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_INSERT, strlen(SQL_TEXT_INSERT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // insert the requested number of rows for (i = 1; i <= NUM_ROWS; i++) { // perform binds if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, longColVar) < 0) return dpiSamples_showError(); // create long string of specified size longValueLength = i * SIZE_INCREMENT; printf("Inserting row %d with long column of length %d\n", i, longValueLength); longValue = malloc(longValueLength); if (!longValue) { fprintf(stderr, "Out of memory!\n"); return -1; } memset(longValue, 13, longValueLength); // insert value intColValue->isNull = 0; intColValue->value.asInt64 = i; if (dpiVar_setFromBytes(longColVar, 0, longValue, longValueLength) < 0) return dpiSamples_showError(); free(longValue); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); } dpiStmt_release(stmt); printf("\n"); // perform commit if (dpiConn_commit(conn) < 0) return dpiSamples_showError(); // prepare statement for query if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_QUERY, strlen(SQL_TEXT_QUERY), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, ARRAY_SIZE) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 2, longColVar) < 0) return dpiSamples_showError(); // fetch rows while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; printf("Fetched row %" PRId64 " with long column of length %d\n", intColValue[bufferRowIndex].value.asInt64, longColValue[bufferRowIndex].value.asBytes.length); } // clean up dpiVar_release(intColVar); dpiVar_release(longColVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoLongs.c000066400000000000000000000125601510466437300161750ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoLongs.c // Demos inserting and fetching long columns. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT_TRUNC "truncate table DemoLongs" #define SQL_TEXT_INSERT "insert into DemoLongs values (:1, :2)" #define SQL_TEXT_QUERY "select * from DemoLongs order by IntCol" #define ARRAY_SIZE 3 #define NUM_ROWS 10 #define SIZE_INCREMENT 50000 //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t i, longValueLength, numQueryColumns, bufferRowIndex; dpiData *intColValue, *longColValue; dpiVar *intColVar, *longColVar; char *longValue; dpiConn *conn; dpiStmt *stmt; int found; // connect to database conn = dpiSamples_getConn(0, NULL); // truncate the table so that the demo can be repeated if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_TRUNC, strlen(SQL_TEXT_TRUNC), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); dpiStmt_release(stmt); // create variables for insertion if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, ARRAY_SIZE, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, ARRAY_SIZE, 0, 0, 0, NULL, &longColVar, &longColValue) < 0) return dpiSamples_showError(); // prepare insert statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_INSERT, strlen(SQL_TEXT_INSERT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); // insert the requested number of rows for (i = 1; i <= NUM_ROWS; i++) { // perform binds if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 2, longColVar) < 0) return dpiSamples_showError(); // create long string of specified size longValueLength = i * SIZE_INCREMENT; printf("Inserting row %d with long column of length %d\n", i, longValueLength); longValue = malloc(longValueLength); if (!longValue) { fprintf(stderr, "Out of memory!\n"); return -1; } memset(longValue, 'A', longValueLength); // insert value intColValue->isNull = 0; intColValue->value.asInt64 = i; if (dpiVar_setFromBytes(longColVar, 0, longValue, longValueLength) < 0) return dpiSamples_showError(); free(longValue); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); } dpiStmt_release(stmt); printf("\n"); // perform commit if (dpiConn_commit(conn) < 0) return dpiSamples_showError(); // prepare statement for query if (dpiConn_prepareStmt(conn, 0, SQL_TEXT_QUERY, strlen(SQL_TEXT_QUERY), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_setFetchArraySize(stmt, ARRAY_SIZE) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 1, intColVar) < 0) return dpiSamples_showError(); if (dpiStmt_define(stmt, 2, longColVar) < 0) return dpiSamples_showError(); // fetch rows while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; printf("Fetched row %" PRId64 " with long column of length %d\n", intColValue[bufferRowIndex].value.asInt64, longColValue[bufferRowIndex].value.asBytes.length); } // clean up dpiVar_release(intColVar); dpiVar_release(longColVar); dpiStmt_release(stmt); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoObjectAQ.c000066400000000000000000000123431510466437300165420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoObjectAQ.c // Demos simple enqueuing and dequeuing objects using advanced queuing. //----------------------------------------------------------------------------- #include "SampleLib.h" #define QUEUE_NAME "DEMO_BOOK_QUEUE" #define QUEUE_OBJECT_TYPE "UDT_BOOK" #define NUM_BOOKS 2 #define NUM_ATTRS 3 struct bookType { char *title; char *authors; double price; }; struct bookType books[NUM_BOOKS] = { { "Oracle Call Interface Programmers Guide", "Oracle", 0 }, { "Selecting Employees", "Scott Tiger", 7.99 } }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiObjectAttr *attrs[NUM_ATTRS]; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiMsgProps *msgProps; dpiData attrValue; dpiQueue *queue; dpiObject *book; dpiConn *conn; uint32_t i; // connect to database conn = dpiSamples_getConn(0, NULL); // look up object type if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiSamples_showError(); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiSamples_showError(); // create queue if (dpiConn_newQueue(conn, QUEUE_NAME, strlen(QUEUE_NAME), objType, &queue) < 0) return dpiSamples_showError(); dpiConn_release(conn); // create message properties and set payload if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiSamples_showError(); if (dpiObjectType_createObject(objType, &book) < 0) return dpiSamples_showError(); if (dpiMsgProps_setPayloadObject(msgProps, book) < 0) return dpiSamples_showError(); // enqueue books printf("Enqueuing messages...\n"); for (i = 0; i < NUM_BOOKS; i++) { printf("%s\n", books[i].title); // set title dpiData_setBytes(&attrValue, books[i].title, strlen(books[i].title)); if (dpiObject_setAttributeValue(book, attrs[0], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiSamples_showError(); // set authors dpiData_setBytes(&attrValue, books[i].authors, strlen(books[i].authors)); if (dpiObject_setAttributeValue(book, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiSamples_showError(); // set price dpiData_setDouble(&attrValue, books[i].price); if (dpiObject_setAttributeValue(book, attrs[2], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiSamples_showError(); // enqueue book if (dpiQueue_enqOne(queue, msgProps) < 0) return dpiSamples_showError(); } dpiObjectType_release(objType); dpiMsgProps_release(msgProps); dpiObject_release(book); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiSamples_showError(); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiSamples_showError(); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiSamples_showError(); // dequeue books printf("\nDequeuing messages...\n"); while (1) { if (dpiQueue_deqOne(queue, &msgProps) < 0) return dpiSamples_showError(); if (!msgProps) break; if (dpiMsgProps_getPayload(msgProps, &book, NULL, NULL) < 0) return dpiSamples_showError(); if (dpiObject_getAttributeValue(book, attrs[0], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiSamples_showError(); printf("%.*s\n", attrValue.value.asBytes.length, attrValue.value.asBytes.ptr); dpiMsgProps_release(msgProps); } for (i = 0; i < NUM_ATTRS; i++) dpiObjectAttr_release(attrs[i]); printf("\nDone.\n"); return 0; } odpi-5.6.4/samples/DemoRawAQ.c000066400000000000000000000071401510466437300160640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoRawAQ.c // Demos simple enqueuing and dequeuing RAW data using advanced queuing. //----------------------------------------------------------------------------- #include "SampleLib.h" #define QUEUE_NAME "DEMO_RAW_QUEUE" #define NUM_MESSAGES 4 const char *payloads[NUM_MESSAGES] = { "The first message", "The second message", "The third message", "The fourth and final message" }; //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiDeqOptions *deqOptions; uint32_t payloadLength; dpiMsgProps *msgProps; const char *payload; dpiQueue *queue; dpiConn *conn; uint32_t i; // connect to database conn = dpiSamples_getConn(0, NULL); // create queue and message properties if (dpiConn_newQueue(conn, QUEUE_NAME, strlen(QUEUE_NAME), NULL, &queue) < 0) return dpiSamples_showError(); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiSamples_showError(); dpiConn_release(conn); // enqueue messages printf("Enqueuing messages...\n"); for (i = 0; i < NUM_MESSAGES; i++) { printf("%s\n", payloads[i]); if (dpiMsgProps_setPayloadBytes(msgProps, payloads[i], strlen(payloads[i])) < 0) return dpiSamples_showError(); if (dpiQueue_enqOne(queue, msgProps) < 0) return dpiSamples_showError(); } dpiMsgProps_release(msgProps); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiSamples_showError(); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiSamples_showError(); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiSamples_showError(); // dequeue messages printf("\nDequeuing messages...\n"); while (1) { if (dpiQueue_deqOne(queue, &msgProps) < 0) return dpiSamples_showError(); if (!msgProps) break; if (dpiMsgProps_getPayload(msgProps, NULL, &payload, &payloadLength) < 0) return dpiSamples_showError(); printf("%.*s\n", payloadLength, payload); dpiMsgProps_release(msgProps); } printf("\nDone.\n"); return 0; } odpi-5.6.4/samples/DemoRefCursors.c000066400000000000000000000074641510466437300172170ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoRefCursors.c // Demos simple fetch of REF cursors. //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "begin " \ " open :1 for select 'X' StrVal from dual; " \ "end;" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { uint32_t numQueryColumns, bufferRowIndex, i; dpiData *refCursorValue, *strValue; dpiNativeTypeNum nativeTypeNum; dpiQueryInfo queryInfo; dpiVar *refCursorVar; dpiStmt *stmt; dpiConn *conn; int found; // connect to database conn = dpiSamples_getConn(1, NULL); // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_STMT, DPI_NATIVE_TYPE_STMT, 1, 0, 0, 0, NULL, &refCursorVar, &refCursorValue) < 0) return dpiSamples_showError(); if (dpiStmt_bindByPos(stmt, 1, refCursorVar) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiSamples_showError(); // get ref cursor dpiStmt_release(stmt); stmt = refCursorValue->value.asStmt; // fetch data from ref cursor while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &strValue) < 0) return dpiSamples_showError(); printf("Row: StrVal = '%.*s'\n", strValue->value.asBytes.length, strValue->value.asBytes.ptr); } // display description of each fetched column if (dpiStmt_getNumQueryColumns(stmt, &numQueryColumns) < 0) return dpiSamples_showError(); for (i = 0; i < numQueryColumns; i++) { if (dpiStmt_getQueryInfo(stmt, i + 1, &queryInfo) < 0) return dpiSamples_showError(); printf("('%*s', %d, %d, %d, %d, %d, %d)\n", queryInfo.nameLength, queryInfo.name, queryInfo.typeInfo.oracleTypeNum, queryInfo.typeInfo.sizeInChars, queryInfo.typeInfo.clientSizeInBytes, queryInfo.typeInfo.precision, queryInfo.typeInfo.scale, queryInfo.nullOk); } // clean up dpiVar_release(refCursorVar); dpiConn_release(conn); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoRemoveSodaDoc.c000066400000000000000000000056361510466437300176130ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoRemoveSodaDoc.c // Demos removing a document from a SODA collection with the specified key. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { const char *collectionName, *key; dpiSodaOperOptions options; dpiSampleParams *params; dpiSodaColl *coll; uint64_t numDocs; dpiSodaDb *db; // determine name of collection and key of document to retrieve if (argc != 3) { fprintf(stderr, "Usage: DemoGetSodaDoc \n"); return 1; } collectionName = argv[1]; key = argv[2]; // connect to database db = dpiSamples_getSodaDb(); // open existing SODA collection if (dpiSodaDb_openCollection(db, collectionName, strlen(collectionName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", collectionName); return 1; } // build options params = dpiSamples_getParams(); if (dpiContext_initSodaOperOptions(params->context, &options) < 0) return dpiSamples_showError(); options.key = key; options.keyLength = strlen(key); // remove document from the collection if (dpiSodaColl_remove(coll, &options, DPI_SODA_FLAGS_ATOMIC_COMMIT, &numDocs) < 0) return dpiSamples_showError(); printf("%" PRIu64 " documents removed.\n", numDocs); // clean up dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoReplaceSodaDoc.c000066400000000000000000000107501510466437300177220ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoReplaceSodaDoc.c // Demos replacing a document in a SODA collection with the specified key. //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { const char *collectionName, *key, *content, *temp, *encoding; dpiSodaDoc *doc, *replacedDoc; dpiSodaOperOptions options; dpiSampleParams *params; uint32_t tempLength; dpiSodaColl *coll; dpiSodaDb *db; int replaced; // determine name of collection to insert into and content of document if (argc != 4) { fprintf(stderr, "Usage: DemoReplaceSodaColl \n"); return 1; } collectionName = argv[1]; key = argv[2]; content = argv[3]; // connect to database db = dpiSamples_getSodaDb(); // open existing SODA collection if (dpiSodaDb_openCollection(db, collectionName, strlen(collectionName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiSamples_showError(); if (!coll) { printf("No collection named %s\n", collectionName); return 1; } // build options params = dpiSamples_getParams(); if (dpiContext_initSodaOperOptions(params->context, &options) < 0) return dpiSamples_showError(); options.key = key; options.keyLength = strlen(key); // create SODA document using the provided content if (dpiSodaDb_createDocument(db, NULL, 0, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiSamples_showError(); // replace document in collection and return it if (dpiSodaColl_replaceOne(coll, &options, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, &replaced, &replacedDoc) < 0) return dpiSamples_showError(); if (dpiSodaDoc_release(doc) < 0) return dpiSamples_showError(); if (!replaced) { printf("No document with key %s\n", key); return 1; } // display information about the document that was just inserted printf("Document Details:\n"); if (dpiSodaDoc_getKey(replacedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Key -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getContent(replacedDoc, &temp, &tempLength, &encoding) < 0) return dpiSamples_showError(); printf("Content -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getMediaType(replacedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Media Type -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getVersion(replacedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Version -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getCreatedOn(replacedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Created -> %.*s\n", tempLength, temp); if (dpiSodaDoc_getLastModified(replacedDoc, &temp, &tempLength) < 0) return dpiSamples_showError(); printf("Last Modified -> %.*s\n", tempLength, temp); // clean up dpiSodaDoc_release(replacedDoc); dpiSodaColl_release(coll); dpiSodaDb_release(db); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoShardingNumberKey.c000066400000000000000000000077551510466437300205060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2020, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // DemoShardingNumberKey.c // Demos simple use of sharding with a numeric key. The sample schema // provided does not include suppoort for running this demo. A sharded database // must first be created. Information on how to create a sharded database can // be found in the documentation: // https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=SHARD //----------------------------------------------------------------------------- #include "SampleLib.h" #define SQL_TEXT "select cust_id, cust_name from ShardedTable" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiShardingKeyColumn shardingKeyColumn; dpiConnCreateParams createParams; dpiNativeTypeNum nativeTypeNum; dpiData *intData, *strData; dpiSampleParams *params; uint32_t bufferRowIndex; long shardingKeyValue; dpiStmt *stmt; dpiConn *conn; int found; // verify parameters if (argc != 2) { fprintf(stderr, "Specify sharding key to use.\n"); return 1; } shardingKeyValue = atol(argv[1]); printf("Using sharding key value %ld\n", shardingKeyValue); // connect to database params = dpiSamples_getParams(); if (dpiContext_initConnCreateParams(params->context, &createParams) < 0) return dpiSamples_showError(); createParams.shardingKeyColumns = &shardingKeyColumn; createParams.numShardingKeyColumns = 1; shardingKeyColumn.oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; shardingKeyColumn.nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; shardingKeyColumn.value.asDouble = shardingKeyValue; if (dpiConn_create(params->context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &conn) < 0) return dpiSamples_showError(); // perform query if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiSamples_showError(); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiSamples_showError(); while (1) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiSamples_showError(); if (!found) break; if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &intData) < 0) return dpiSamples_showError(); if (dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &strData) < 0) return dpiSamples_showError(); printf("Row: ID = %g, Name = %.*s\n", intData->value.asDouble, strData->value.asBytes.length, strData->value.asBytes.ptr); } printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoTokenPoolWithCallback.c000066400000000000000000000123261510466437300212760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // NAME // DemoTokenPoolWithCallback.c // // DESCRIPTION // This demo file shows connection pooling with token based authentication to // Oracle Autonomous Database from Oracle Compute Infrastructure. It shows // how to create a connection pool and update expired tokens. // // PREREQUISITES // - Oracle Client libraries 19.14 (or later), or 21.5 (or later). // // - The Oracle Cloud Infrastructure command line interface (OCI-CLI). The // command line interface (CLI) is a tool that enables you to work with // Oracle Cloud Infrastructure objects and services at a command line, see // https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm // // - Set these environment variables (see the code explanation): // ODPIC_SAMPLES_ACCESS_TOKEN_LOC // ODPIC_SAMPLES_CONNECT_STRING // ODPIC_SAMPLES_EXPIRED_ACCESS_TOKEN_LOC //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // tokenCallback() //----------------------------------------------------------------------------- int tokenCallback(void *context, dpiAccessToken *tokenRefresh) { printf("Token callback is called.\n"); // used for extracting the token and private key from files generated // through the OCI-CLI. dpiAccessToken *accessToken; accessToken = dpiSamples_getAccessToken(); tokenRefresh->token = accessToken->token; tokenRefresh->tokenLength = accessToken->tokenLength; tokenRefresh->privateKey = accessToken->privateKey; tokenRefresh->privateKeyLength = accessToken->privateKeyLength; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiConn *conn1, *conn2; dpiPool *pool; dpiSampleParams *params; dpiAccessToken *accessToken; accessToken = dpiSamples_getAccessToken(); params = dpiSamples_getParams(); dpiPoolCreateParams poolCreateParams; if (dpiContext_initPoolCreateParams(params->context, &poolCreateParams) < 0) return dpiSamples_showError(); // params for token based authentication: // accessTokenCallback: A callback function to provide a refreshed token // externalAuth: Must be set to true for token based authentication // homogeneous: Must be set to true for token based authentication poolCreateParams.minSessions = 1; poolCreateParams.maxSessions = 10; poolCreateParams.sessionIncrement = 1; poolCreateParams.externalAuth = 1; poolCreateParams.homogeneous = 1; poolCreateParams.accessTokenCallback = tokenCallback; dpiCommonCreateParams commonCreateParams; if (dpiContext_initCommonCreateParams(params->context, &commonCreateParams) < 0) return dpiSamples_showError(); commonCreateParams.accessToken = accessToken; if (dpiPool_create(params->context, NULL, 0, NULL, 0, params->connectString, params->connectStringLength, &commonCreateParams, &poolCreateParams, &pool) < 0) return dpiSamples_showError(); printf("Connection pool is created.\n"); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn1) < 0) return dpiSamples_showError(); printf("Session is acquired from connection pool.\n"); // set expired token and private key in connection pool dpiAccessToken expiredAccessToken; dpiSamples_populateAccessToken(&expiredAccessToken, "ODPIC_SAMPLES_EXPIRED_ACCESS_TOKEN_LOC"); if (dpiPool_setAccessToken(pool, &expiredAccessToken) < 0) return dpiSamples_showError(); // accessTokenCallback will get invoked to get refreshed tokens if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn2) < 0) return dpiSamples_showError(); printf("Session is acquired from connection pool.\n"); printf("Done.\n"); return 0; } odpi-5.6.4/samples/DemoTokenStandalone.c000066400000000000000000000064111510466437300202020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // NAME // DemoTokenStandalone.c // // DESCRIPTION // This Demo file shows standalone connection using token based authentication // to Oracle Autonomous Database from Oracle Compute Infrastructure. // // PREQUISITES // - Oracle Client libraries 19.14 (or later), or 21.5 (or later). // // - The Oracle Cloud Infrastructure command line interface (OCI-CLI). The // command line interface (CLI) is a tool that enables you to work with // Oracle Cloud Infrastructure objects and services at a command line, see // https://docs.oracle.com/en-us/iaas/Content/API/Concepts/cliconcepts.htm // // - Set these environment variables (see the code explanation): // ODPIC_SAMPLES_ACCESS_TOKEN_LOC // ODPIC_SAMPLES_CONNECT_STRING //----------------------------------------------------------------------------- #include "SampleLib.h" //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiConn *conn; dpiSampleParams *params; dpiAccessToken *accessToken; accessToken = dpiSamples_getAccessToken(); params = dpiSamples_getParams(); dpiConnCreateParams connCreateParams; if (dpiContext_initConnCreateParams(params->context, &connCreateParams) < 0) return dpiSamples_showError(); // params for token based authentication: // externalAuth: Must be set to true for token based authentication connCreateParams.externalAuth = 1; dpiCommonCreateParams commonCreateParams; if (dpiContext_initCommonCreateParams(params->context, &commonCreateParams) < 0) return dpiSamples_showError(); commonCreateParams.accessToken = accessToken; if (dpiConn_create(params->context, NULL, 0, NULL, 0, params->connectString, params->connectStringLength, &commonCreateParams, &connCreateParams, &conn) < 0) return dpiSamples_showError(); printf("Standalone connection is created\n"); printf("Done.\n"); return 0; } odpi-5.6.4/samples/Makefile000066400000000000000000000050571510466437300156050ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2016, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #------------------------------------------------------------------------------ # # Sample Makefile if you wish to build the ODPI-C sample executables. # # Look at README.md for information on how to build and run the samples. #------------------------------------------------------------------------------ BUILD_DIR = build INCLUDE_DIR = ../include LIB_DIR = ../lib CC=gcc LD=gcc CFLAGS=-I$(INCLUDE_DIR) -O2 -g -Wall LIBS=-L$(LIB_DIR) -lodpic COMMON_OBJS = $(BUILD_DIR)/SampleLib.o SOURCES = DemoBLOB.c DemoCLOB.c DemoFetch.c DemoInsert.c DemoInsertAsArray.c \ DemoCallProc.c DemoRefCursors.c DemoImplicitResults.c \ DemoFetchObjects.c DemoBindObjects.c DemoFetchDates.c \ DemoBindArrays.c DemoBFILE.c DemoAppContext.c DemoDistribTrans.c \ DemoObjectAQ.c DemoRawAQ.c DemoBulkAQ.c DemoCQN.c DemoLongs.c \ DemoLongRaws.c DemoDMLReturning.c DemoInOutTempLobs.c \ DemoConvertNumbers.c DemoCreateSodaColl.c DemoIterSodaColls.c \ DemoDropSodaColl.c DemoInsertSodaColl.c DemoGetSodaDoc.c \ DemoRemoveSodaDoc.c DemoReplaceSodaDoc.c DemoGetAllSodaDocs.c \ DemoGetSodaCollNames.c DemoCLOBsAsStrings.c DemoBLOBsAsBytes.c \ DemoInsertManySodaColl.c DemoShardingNumberKey.c DemoFetchJSON.c \ DemoBindJSON.c DemoTokenStandalone.c DemoTokenPoolWithCallback.c BINARIES = $(SOURCES:%.c=$(BUILD_DIR)/%) all: $(BUILD_DIR) $(BINARIES) clean: rm -rf $(BUILD_DIR) $(BUILD_DIR): mkdir -p $@ $(BUILD_DIR)/%.o: %.c SampleLib.h $(CC) -c $(CFLAGS) -o $@ $< $(BUILD_DIR)/%: $(BUILD_DIR)/%.o $(COMMON_OBJS) $(LD) $(LDFLAGS) $< -o $@ $(COMMON_OBJS) $(LIBS) odpi-5.6.4/samples/Makefile.win32000066400000000000000000000066751510466437300165550ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2017, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #------------------------------------------------------------------------------ # # Sample nmake Makefile for building the ODPI-C samples on Windows. # # This file is expected to be processed by nmake as in the following: # nmake /f Makefile.win32 # # Look at README.md for information on how to build and run the samples. # #------------------------------------------------------------------------------ BUILD_DIR = build INCLUDE_DIR = ..\include LIB_DIR = ..\lib LIBS = $(LIB_DIR)\odpic.lib COMMON_OBJS = $(BUILD_DIR)\SampleLib.obj EXES = $(BUILD_DIR)\DemoBLOB.exe \ $(BUILD_DIR)\DemoCLOB.exe \ $(BUILD_DIR)\DemoFetch.exe \ $(BUILD_DIR)\DemoInsert.exe \ $(BUILD_DIR)\DemoInsertAsArray.exe \ $(BUILD_DIR)\DemoCallProc.exe \ $(BUILD_DIR)\DemoRefCursors.exe \ $(BUILD_DIR)\DemoImplicitResults.exe \ $(BUILD_DIR)\DemoFetchObjects.exe \ $(BUILD_DIR)\DemoBindObjects.exe \ $(BUILD_DIR)\DemoFetchDates.exe \ $(BUILD_DIR)\DemoBindArrays.exe \ $(BUILD_DIR)\DemoBFILE.exe \ $(BUILD_DIR)\DemoAppContext.exe \ $(BUILD_DIR)\DemoDistribTrans.exe \ $(BUILD_DIR)\DemoObjectAQ.exe \ $(BUILD_DIR)\DemoRawAQ.exe \ $(BUILD_DIR)\DemoBulkAQ.exe \ $(BUILD_DIR)\DemoCQN.exe \ $(BUILD_DIR)\DemoLongs.exe \ $(BUILD_DIR)\DemoLongRaws.exe \ $(BUILD_DIR)\DemoDMLReturning.exe \ $(BUILD_DIR)\DemoInOutTempLobs.exe \ $(BUILD_DIR)\DemoConvertNumbers.exe \ $(BUILD_DIR)\DemoCreateSodaColl.exe \ $(BUILD_DIR)\DemoIterSodaColls.exe \ $(BUILD_DIR)\DemoDropSodaColl.exe \ $(BUILD_DIR)\DemoInsertSodaColl.exe \ $(BUILD_DIR)\DemoGetSodaDoc.exe \ $(BUILD_DIR)\DemoRemoveSodaDoc.exe \ $(BUILD_DIR)\DemoReplaceSodaDoc.exe \ $(BUILD_DIR)\DemoGetAllSodaDocs.exe \ $(BUILD_DIR)\DemoGetSodaCollNames.exe \ $(BUILD_DIR)\DemoInsertManySodaColl.exe $(BUILD_DIR)\DemoInsertManySodaColl.exe \ $(BUILD_DIR)\DemoShardingNumberKey.exe \ $(BUILD_DIR)\DemoFetchJSON.exe \ $(BUILD_DIR)\DemoBindJSON.exe all: $(EXES) $(BUILD_DIR) $(EXES): $(BUILD_DIR) $(COMMON_OBJS) $*.obj clean: @if exist $(BUILD_DIR) rmdir /S /Q $(BUILD_DIR) $(BUILD_DIR): @if not exist $(BUILD_DIR) mkdir $(BUILD_DIR) {.}.c{$(BUILD_DIR)}.obj :: cl /nologo /c /Fo$(BUILD_DIR)\ /I$(INCLUDE_DIR) $< {$(BUILD_DIR)}.obj{$(BUILD_DIR)}.exe: link /nologo /out:$@ $< $(COMMON_OBJS) $(LIBS) odpi-5.6.4/samples/README.md000066400000000000000000000040141510466437300154140ustar00rootroot00000000000000This directory contains samples for ODPI-C. All of the executables can be built using the supplied Makefile (Makefile.win32 for use with nmake on Windows). The executables will be placed in the subdirectory "build" and can be run from there. See the top level [README](../README.md) for the platforms and compilers that have been tested and are known to work. Some samples require the latest Database features. TestBFILE needs to write to the physical directory that the database can read from, so it will generally fail unless it is run on the same machine as the database. To run the samples: - Ensure that installation of the ODPI-C library has been completed as explained [here](https://oracle.github.io/odpi/doc/installation.html). - Optionally edit the file sql/SampleEnv.sql and edit the parameters defined there. If you don't change any of the parameters, make the sure the schemas odpicdemo and odpicdemo_proxy can be dropped. If you do edit the parameters defined there, also set the corresponding environment variables indicated on the right of the defined variable. - Optionally set the environment variable ODPIC_SAMPLES_CONNECT_STRING to point to the database in which you plan to run the tests. If this environment variable is not set, the connect string will be assumed to be the EZ connect string "localhost/orclpdb". - Run 'make clean' and 'make' to build the samples - Run SQL\*Plus as SYSDBA and create the sample SQL objects with sql/SetupSamples.sql. The syntax is: sqlplus sys/syspassword@hostname/servicename as sysdba @SetupSamples - Change to the 'build' directory and run each sample individually. On Linux you will need to set LD_LIBRARY_PATH to point to the location of the library, for example: LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../lib ./TestAppContext - After running the samples, drop the SQL objects by running the script sql/DropSamples.sql. The syntax is: sqlplus sys/syspassword@hostname/servicename as sysdba @DropSamples odpi-5.6.4/samples/SampleLib.c000066400000000000000000000264431510466437300161630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // SampleLib.c // Common code used in all samples. //----------------------------------------------------------------------------- #include "SampleLib.h" static dpiContext *gContext = NULL; static dpiSampleParams gParams; static dpiAccessToken *gAccessToken = NULL; //----------------------------------------------------------------------------- // dpiSamples__fatalError() [INTERNAL] // Called when a fatal error is encountered from which recovery is not // possible. This simply prints a message to stderr and exits the program with // a non-zero exit code to indicate an error. //----------------------------------------------------------------------------- static void dpiSamples__fatalError(const char *message) { fprintf(stderr, "FATAL: %s\n", message); exit(1); } //----------------------------------------------------------------------------- // dpiSamples__finalize() [INTERNAL] // Destroy context upon process exit. //----------------------------------------------------------------------------- static void dpiSamples__finalize(void) { dpiContext_destroy(gContext); if (gAccessToken) { if (gAccessToken->token) free((char*) gAccessToken->token); if (gAccessToken->privateKey) free((char*) gAccessToken->privateKey); free(gAccessToken); } } //----------------------------------------------------------------------------- // dpiSamples__getEnvValue() // Get parameter value from the environment or use supplied default value if // the value is not set in the environment. Memory is allocated to accommodate // the value. //----------------------------------------------------------------------------- static void dpiSamples__getEnvValue(const char *envName, const char *defaultValue, const char **value, uint32_t *valueLength, int convertToUpper) { const char *source; uint32_t i; char *ptr; source = getenv(envName); if (!source) source = defaultValue; *valueLength = strlen(source); *value = malloc(*valueLength); if (!*value) dpiSamples__fatalError("Out of memory!"); memcpy((void*) *value, source, *valueLength); if (convertToUpper) { ptr = (char*) *value; for (i = 0; i < *valueLength; i++) ptr[i] = toupper(ptr[i]); } } //----------------------------------------------------------------------------- // dpiSamples_getConn() // Connect to the database using the supplied parameters. The DPI library // will also be initialized, if needed. //----------------------------------------------------------------------------- dpiConn *dpiSamples_getConn(int withPool, dpiCommonCreateParams *commonParams) { dpiConn *conn; dpiPool *pool; // perform initialization dpiSamples_getParams(); // create a pool and acquire a connection if (withPool) { if (dpiPool_create(gContext, gParams.mainUserName, gParams.mainUserNameLength, gParams.mainPassword, gParams.mainPasswordLength, gParams.connectString, gParams.connectStringLength, commonParams, NULL, &pool) < 0) { dpiSamples_showError(); dpiSamples__fatalError("Unable to create pool."); } if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn) < 0) { dpiSamples_showError(); dpiSamples__fatalError("Unable to acquire connection from pool."); } dpiPool_release(pool); // or create a standalone connection } else if (dpiConn_create(gContext, gParams.mainUserName, gParams.mainUserNameLength, gParams.mainPassword, gParams.mainPasswordLength, gParams.connectString, gParams.connectStringLength, commonParams, NULL, &conn) < 0) { dpiSamples_showError(); dpiSamples__fatalError("Unable to create connection."); } return conn; } //----------------------------------------------------------------------------- // dpiSamples_getParams() // Get parameters set in the environment. The DPI library will also be // initialized if needed. //----------------------------------------------------------------------------- dpiSampleParams *dpiSamples_getParams(void) { dpiErrorInfo errorInfo; if (!gContext) { if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, &gContext, &errorInfo) < 0) { fprintf(stderr, "ERROR: %.*s (%s : %s)\n", errorInfo.messageLength, errorInfo.message, errorInfo.fnName, errorInfo.action); dpiSamples__fatalError("Cannot create DPI context."); } atexit(dpiSamples__finalize); } dpiSamples__getEnvValue("ODPIC_SAMPLES_MAIN_USER", "odpicdemo", &gParams.mainUserName, &gParams.mainUserNameLength, 1); dpiSamples__getEnvValue("ODPIC_SAMPLES_MAIN_PASSWORD", "welcome", &gParams.mainPassword, &gParams.mainPasswordLength, 0); dpiSamples__getEnvValue("ODPIC_SAMPLES_PROXY_USER", "odpicdemo_proxy", &gParams.proxyUserName, &gParams.proxyUserNameLength, 1); dpiSamples__getEnvValue("ODPIC_SAMPLES_PROXY_PASSWORD", "welcome", &gParams.proxyPassword, &gParams.proxyPasswordLength, 0); dpiSamples__getEnvValue("ODPIC_SAMPLES_CONNECT_STRING", "localhost/orclpdb", &gParams.connectString, &gParams.connectStringLength, 0); dpiSamples__getEnvValue("ODPIC_SAMPLES_DIR_NAME", "odpicdemo_dir", &gParams.dirName, &gParams.dirNameLength, 1); gParams.context = gContext; return &gParams; } //----------------------------------------------------------------------------- // dpiSamples_getSodaDb() // Connect to the database and then acquire the SODA database object. //----------------------------------------------------------------------------- dpiSodaDb *dpiSamples_getSodaDb(void) { dpiSodaDb *db; dpiConn *conn; conn = dpiSamples_getConn(0, NULL); if (dpiConn_getSodaDb(conn, &db) < 0) { dpiSamples_showError(); dpiSamples__fatalError("Unable to acquire SODA database."); } dpiConn_release(conn); return db; } //----------------------------------------------------------------------------- // dpiSamples__strRemove() [INTERNAL] // Removes substring from buffer //----------------------------------------------------------------------------- void dpiSamples__strRemove(char *str, const char *sub, size_t dataLen) { char *r; size_t len = 0; r = strstr(str, sub); if (r) { len = strlen(sub); memmove(r, r + len + 1, dataLen - (r - str + len)); } } //----------------------------------------------------------------------------- // dpiSamples__getTokenData() [INTERNAL] // Read files from location specified //----------------------------------------------------------------------------- void dpiSamples__getTokenData(const char *dirName, const char *fileName, char **value, uint32_t *valueLength, int type) { FILE *fp = NULL; char *fullFileName = NULL; size_t len = 0; fullFileName = malloc(strlen(dirName) + strlen(fileName) + 2); if (!fullFileName) dpiSamples__fatalError("Out of memory!"); sprintf(fullFileName, "%s/%s", dirName, fileName); fp = fopen(fullFileName, "r"); free(fullFileName); fullFileName = NULL; if (!fp) { *value = NULL; *valueLength = 0; return; } *value = malloc(TOKENBUFLEN); if (!*value) dpiSamples__fatalError("Out of memory!"); len = fread(*value, sizeof(char), TOKENBUFLEN - 1, fp); (*value)[len] = '\0'; *valueLength = strlen(*value); if (ferror(fp)) dpiSamples__fatalError("Error in reading from file."); if (type) { dpiSamples__strRemove(*value, "-----BEGIN PRIVATE KEY-----", len); dpiSamples__strRemove(*value, "-----END PRIVATE KEY-----", len); } fclose(fp); } //----------------------------------------------------------------------------- // dpiSamples_populateAccessToken() // Populates structure with token and private key // ---------------------------------------------------------------------------- void dpiSamples_populateAccessToken(dpiAccessToken* accessToken, const char* envName) { const char *privateKeyFileName = "oci_db_key.pem"; const char *tokenFileName = "token"; char *dbLocation = NULL; dbLocation = getenv(envName); if (!dbLocation) { const char *format = "Set environment variable %s to the directory " "where the database token and private key files are found."; char *errorMessage = malloc(strlen(format) + strlen(envName) + 1); if (!errorMessage) dpiSamples__fatalError("Out of memory!"); sprintf(errorMessage, format, envName); dpiSamples__fatalError(errorMessage); } dpiSamples__getTokenData(dbLocation, tokenFileName, (char **)(&accessToken->token), &accessToken->tokenLength, 0); dpiSamples__getTokenData(dbLocation, privateKeyFileName, (char **)(&accessToken->privateKey), &accessToken->privateKeyLength, 1); } //----------------------------------------------------------------------------- // dpiSamples_getAccessToken() // Read the authentication token and key from files // ---------------------------------------------------------------------------- dpiAccessToken *dpiSamples_getAccessToken(void) { if (!gAccessToken) { gAccessToken = malloc(sizeof(dpiAccessToken)); if (!gAccessToken) dpiSamples__fatalError("Out of memory!"); dpiSamples_populateAccessToken(gAccessToken, "ODPIC_SAMPLES_ACCESS_TOKEN_LOC"); } return gAccessToken; } //----------------------------------------------------------------------------- // dpiSamples_showError() // Display the error to stderr. //----------------------------------------------------------------------------- int dpiSamples_showError(void) { dpiErrorInfo info; dpiContext_getError(gContext, &info); fprintf(stderr, "ERROR: %.*s (%s: %s), offset: %u\n", info.messageLength, info.message, info.fnName, info.action, info.offset); return -1; } odpi-5.6.4/samples/SampleLib.h000066400000000000000000000051271510466437300161640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // SampleLib.h // Header file for common code used in all samples. //----------------------------------------------------------------------------- #include #include #include #include #include #ifdef _MSC_VER #if _MSC_VER < 1900 #define PRId64 "I64d" #define PRIu64 "I64u" #endif #endif #ifndef PRIu64 #include #endif // buffer length for token and private key #define TOKENBUFLEN 8000 typedef struct { const char *mainUserName; uint32_t mainUserNameLength; const char *mainPassword; uint32_t mainPasswordLength; const char *proxyUserName; uint32_t proxyUserNameLength; const char *proxyPassword; uint32_t proxyPasswordLength; const char *connectString; uint32_t connectStringLength; const char *dirName; uint32_t dirNameLength; dpiContext *context; } dpiSampleParams; // connect to the database dpiConn *dpiSamples_getConn(int withPool, dpiCommonCreateParams *commonParams); // acquire parameters dpiSampleParams *dpiSamples_getParams(void); // acquire SODA database dpiSodaDb *dpiSamples_getSodaDb(void); // show error to stderr int dpiSamples_showError(void); // get token and private key dpiAccessToken *dpiSamples_getAccessToken(void); // populate access token void dpiSamples_populateAccessToken(dpiAccessToken* accessToken, const char* envName); odpi-5.6.4/samples/sql/000077500000000000000000000000001510466437300147355ustar00rootroot00000000000000odpi-5.6.4/samples/sql/DropSamples.sql000066400000000000000000000042131510466437300177070ustar00rootroot00000000000000/*----------------------------------------------------------------------------- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License * 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose * either license.* * * If you elect to accept the software under the Apache License, Version 2.0, * the following applies: * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * DropSamples.sql * Drops database objects used for samples. * * Run this like: * sqlplus / as sysdba @DropSamples * * Note that the script SampleEnv.sql should be modified if you would like to * use something other than the default configuration. *---------------------------------------------------------------------------*/ whenever sqlerror exit failure -- setup environment @@SampleEnv.sql -- drop schemas begin for r in ( select username from dba_users where username in (upper('&main_user'), upper('&proxy_user')) ) loop execute immediate 'drop user ' || r.username || ' cascade'; end loop; end; / -- drop directory begin for r in ( select directory_name from dba_directories where directory_name = upper('&dir_name') ) loop execute immediate 'drop directory ' || r.directory_name; end loop; end; / odpi-5.6.4/samples/sql/SampleEnv.sql000066400000000000000000000047261510466437300173610ustar00rootroot00000000000000/*----------------------------------------------------------------------------- * Copyright (c) 2017, 2022, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License * 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose * either license.* * * If you elect to accept the software under the Apache License, Version 2.0, * the following applies: * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * SampleEnv.sql * Sets up configuration for the SetupSamples.sql and DropSamples.sql * scripts. Change the values below if you would like to use something other * than the default values. Note that the environment variables noted below * will also need to be set, if non-default values are used. * The directory path must be one that both the server and the client can * read simultaneously. *---------------------------------------------------------------------------*/ set echo off termout on feedback off verify off define main_user = "odpicdemo" -- $ODPIC_SAMPLES_MAIN_USER define main_password = "welcome" -- $ODPIC_SAMPLES_MAIN_PASSWORD define proxy_user = "odpicdemo_proxy" -- $ODPIC_SAMPLES_PROXY_USER define proxy_password = "welcome" -- $ODPIC_SAMPLES_PROXY_PASSWORD define dir_name = "odpicdemo_dir" -- $ODPIC_SAMPLES_DIR_NAME define dir_path = "/tmp" prompt ************************************************************************ prompt CONFIGURATION prompt ************************************************************************ prompt Main Schema: &main_user prompt Proxy Schema: &proxy_user prompt Directory Name: &dir_name prompt Directory Path: &dir_path prompt set echo on verify on feedback on odpi-5.6.4/samples/sql/SetupSamples.sql000066400000000000000000000740371510466437300201160ustar00rootroot00000000000000/*----------------------------------------------------------------------------- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License * 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose * either license.* * * If you elect to accept the software under the Apache License, Version 2.0, * the following applies: * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * SetupSamples.sql * Creates schemas and populates them with the tables and packages necessary * for running the various included samples. * * Run this like: * sqlplus / as sysdba @SetupSamples * * Note that the script SampleEnv.sql should be modified if you would like to * use something other than the default configuration. *---------------------------------------------------------------------------*/ whenever sqlerror exit failure -- drop existing users, if present @@DropSamples.sql -- create directory CREATE DIRECTORY &dir_name AS '&dir_path'; alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'; alter session set nls_numeric_characters='.,'; create user &main_user identified by "&main_password" quota unlimited on users default tablespace users; create user &proxy_user identified by "&proxy_password"; alter user &proxy_user grant connect through &main_user; grant create session to &proxy_user; grant create session, create table, create procedure, create type, change notification to &main_user; grant read on directory &dir_name to &main_user; grant select on v_$session to &main_user; begin for r in ( select role from dba_roles where role in ('SODA_APP') ) loop execute immediate 'grant ' || r.role || ' to &main_user'; end loop; end; / -- create types create type &main_user..udt_SubObject as object ( SubNumberValue number, SubStringValue varchar2(60) ); / create type &main_user..udt_ObjectArray as varray(10) of &main_user..udt_SubObject; / create type &main_user..udt_Object as object ( NumberValue number, StringValue varchar2(60), FixedCharValue char(10), DateValue date, TimestampValue timestamp, SubObjectValue &main_user..udt_SubObject, SubObjectArray &main_user..udt_ObjectArray ); / create type &main_user..udt_Array as varray(10) of number; / create type &main_user..udt_ObjectDataTypes as object ( StringCol varchar2(60), UnicodeCol nvarchar2(60), FixedCharCol char(30), FixedUnicodeCol nchar(30), IntCol number, NumberCol number(9,2), DateCol date, TimestampCol timestamp, TimestampTZCol timestamp with time zone, TimestampLTZCol timestamp with local time zone, BinaryFltCol binary_float, BinaryDoubleCol binary_double ); / create type &main_user..udt_ObjectDataTypesArray as varray(10) of &main_user..udt_ObjectDataTypes; / create type &main_user..udt_NestedArray is table of &main_user..udt_SubObject; / -- create tables create table &main_user..DemoNumbers ( IntCol number(9) not null, NumberCol number(9, 2) not null, FloatCol float not null, UnconstrainedCol number not null, NullableCol number(38) ); create table &main_user..DemoStrings ( IntCol number(9) not null, StringCol varchar2(20) not null, RawCol raw(30) not null, FixedCharCol char(40) not null, NullableCol varchar2(50) ); create table &main_user..DemoUnicodes ( IntCol number(9) not null, UnicodeCol nvarchar2(20) not null, FixedUnicodeCol nchar(40) not null, NullableCol nvarchar2(50) ); create table &main_user..DemoDates ( IntCol number(9) not null, DateCol date not null, NullableCol date ); create table &main_user..DemoCLOBs ( IntCol number(9) not null, CLOBCol clob not null ); create table &main_user..DemoNCLOBs ( IntCol number(9) not null, NCLOBCol nclob not null ); create table &main_user..DemoBLOBs ( IntCol number(9) not null, BLOBCol blob not null ); create table &main_user..DemoBFILEs ( IntCol number(9) not null, BFILECol bfile not null ); create table &main_user..DemoLongs ( IntCol number(9) not null, LongCol long not null ); create table &main_user..DemoLongsAlter ( IntCol number(9), LongCol long ); create table &main_user..DemoLongRaws ( IntCol number(9) not null, LongRawCol long raw not null ); create table &main_user..DemoTempTable ( IntCol number(9) not null, StringCol varchar2(100), constraint DemoTempTable_pk primary key (IntCol) ); create table &main_user..DemoArrayDML ( IntCol number(9) not null, StringCol varchar2(100), IntCol2 number(3), constraint DemoArrayDML_pk primary key (IntCol) ); create table &main_user..DemoObjects ( IntCol number(9) not null, ObjectCol &main_user..udt_Object, ArrayCol &main_user..udt_Array ); create table &main_user..DemoTimestamps ( IntCol number(9) not null, TimestampCol timestamp not null, TimestampTZCol timestamp with time zone not null, TimestampLTZCol timestamp with local time zone not null, NullableCol timestamp ); create table &main_user..DemoIntervals ( IntCol number(9) not null, IntervalCol interval day to second not null, NullableCol interval day to second ); create table &main_user..DemoObjectDataTypes ( ObjectCol &main_user..udt_ObjectDataTypes ); create table &main_user..DemoObjectDataTypesVarray ( ObjectCol &main_user..udt_ObjectDataTypesArray ); -- populate tables begin for i in 1..10 loop insert into &main_user..DemoNumbers values (i, i + i * 0.25, i + i * .75, i * i * i + i *.5, decode(mod(i, 2), 0, null, power(143, i))); end loop; end; / declare t_RawValue raw(30); function ConvertHexDigit(a_Value number) return varchar2 is begin if a_Value between 0 and 9 then return to_char(a_Value); end if; return chr(ascii('A') + a_Value - 10); end; function ConvertToHex(a_Value varchar2) return varchar2 is t_HexValue varchar2(60); t_Digit number; begin for i in 1..length(a_Value) loop t_Digit := ascii(substr(a_Value, i, 1)); t_HexValue := t_HexValue || ConvertHexDigit(trunc(t_Digit / 16)) || ConvertHexDigit(mod(t_Digit, 16)); end loop; return t_HexValue; end; begin for i in 1..10 loop t_RawValue := hextoraw(ConvertToHex('Raw ' || to_char(i))); insert into &main_user..DemoStrings values (i, 'String ' || to_char(i), t_RawValue, 'Fixed Char ' || to_char(i), decode(mod(i, 2), 0, null, 'Nullable ' || to_char(i))); end loop; end; / begin for i in 1..10 loop insert into &main_user..DemoUnicodes values (i, 'Unicode ' || unistr('\3042') || ' ' || to_char(i), 'Fixed Unicode ' || to_char(i), decode(mod(i, 2), 0, null, unistr('Nullable ') || to_char(i))); end loop; end; / begin for i in 1..10 loop insert into &main_user..DemoDates values (i, to_date(20021209, 'YYYYMMDD') + i + i * .1, decode(mod(i, 2), 0, null, to_date(20021209, 'YYYYMMDD') + i + i + i * .15)); end loop; end; / begin for i in 1..10 loop insert into &main_user..DemoTimestamps values (i, to_timestamp('20021209', 'YYYYMMDD') + to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 2) || '.' || to_char(i * 50)), to_timestamp_tz('20021210 00:00:00 ' || decode(mod(i, 2), 0, '-', '+') || ltrim(to_char(abs(i - 6), '00')) || ':' || decode(mod(i, 2), 0, '30', '00'), 'YYYYMMDD HH24:MI:SS TZH:TZM') + to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 3) || '.' || to_char(i * 75)), to_timestamp_tz('20021211 00:00:00 ' || to_char(i - 8, 'S00') || ':00', 'YYYYMMDD HH24:MI:SS TZH:TZM') + to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 4) || '.' || to_char(i * 100)), decode(mod(i, 2), 0, to_timestamp(null, 'YYYYMMDD'), to_timestamp('20021209', 'YYYYMMDD') + to_dsinterval(to_char(i + 1) || ' 00:00:' || to_char(i * 3) || '.' || to_char(i * 125)))); end loop; end; / begin for i in 1..10 loop insert into &main_user..DemoIntervals values (i, to_dsinterval(to_char(i) || ' ' || to_char(i) || ':' || to_char(i * 2) || ':' || to_char(i * 3)), decode(mod(i, 2), 0, to_dsinterval(null), to_dsinterval(to_char(i + 5) || ' ' || to_char(i + 2) || ':' || to_char(i * 2 + 5) || ':' || to_char(i * 3 + 5)))); end loop; end; / insert into &main_user..DemoObjects values (1, &main_user..udt_Object(1, 'First row', 'First', to_date(20070306, 'YYYYMMDD'), to_timestamp('20080912 16:40:00', 'YYYYMMDD HH24:MI:SS'), &main_user..udt_SubObject(11, 'Sub object 1'), &main_user..udt_ObjectArray( &main_user..udt_SubObject(5, 'first element'), &main_user..udt_SubObject(6, 'second element'))), &main_user..udt_Array(5, 10, null, 20)); insert into &main_user..DemoObjects values (2, null, &main_user..udt_Array(3, null, 9, 12, 15)); insert into &main_user..DemoObjects values (3, &main_user..udt_Object(3, 'Third row', 'Third', to_date(20070621, 'YYYYMMDD'), to_timestamp('20071213 07:30:45', 'YYYYMMDD HH24:MI:SS'), &main_user..udt_SubObject(13, 'Sub object 3'), &main_user..udt_ObjectArray( &main_user..udt_SubObject(10, 'element #1'), &main_user..udt_SubObject(20, 'element #2'), &main_user..udt_SubObject(30, 'element #3'), &main_user..udt_SubObject(40, 'element #4'))), null); commit; -- create procedures for demoing callproc() create procedure &main_user..proc_Demo ( a_InValue varchar2, a_InOutValue in out number, a_OutValue out number ) as begin a_InOutValue := a_InOutValue * length(a_InValue); a_OutValue := length(a_InValue); end; / create procedure &main_user..proc_DemoNoArgs as begin null; end; / -- create functions for demoing callfunc() create function &main_user..func_Demo ( a_String varchar2, a_ExtraAmount number ) return number as begin return length(a_String) + a_ExtraAmount; end; / create function &main_user..func_DemoNoArgs return number as begin return 712; end; / -- create packages create or replace package &main_user..pkg_DemoStringArrays as type udt_StringList is table of varchar2(100) index by binary_integer; function DemoInArrays ( a_StartingLength number, a_Array udt_StringList ) return number; procedure DemoInOutArrays ( a_NumElems number, a_Array in out nocopy udt_StringList ); procedure DemoOutArrays ( a_NumElems number, a_Array out nocopy udt_StringList ); procedure DemoIndexBy ( a_Array out nocopy udt_StringList ); end; / create or replace package body &main_user..pkg_DemoStringArrays as function DemoInArrays ( a_StartingLength number, a_Array udt_StringList ) return number is t_Length number; begin t_Length := a_StartingLength; for i in 1..a_Array.count loop t_Length := t_Length + length(a_Array(i)); end loop; return t_Length; end; procedure DemoInOutArrays ( a_NumElems number, a_Array in out udt_StringList ) is begin for i in 1..a_NumElems loop a_Array(i) := 'Converted element # ' || to_char(i) || ' originally had length ' || to_char(length(a_Array(i))); end loop; end; procedure DemoOutArrays ( a_NumElems number, a_Array out udt_StringList ) is begin for i in 1..a_NumElems loop a_Array(i) := 'Demo out element # ' || to_char(i); end loop; end; procedure DemoIndexBy ( a_Array out nocopy udt_StringList ) is begin a_Array(-1048576) := 'First element'; a_Array(-576) := 'Second element'; a_Array(284) := 'Third element'; a_Array(8388608) := 'Fourth element'; end; end; / create or replace package &main_user..pkg_DemoUnicodeArrays as type udt_UnicodeList is table of nvarchar2(100) index by binary_integer; function DemoInArrays ( a_StartingLength number, a_Array udt_UnicodeList ) return number; procedure DemoInOutArrays ( a_NumElems number, a_Array in out nocopy udt_UnicodeList ); procedure DemoOutArrays ( a_NumElems number, a_Array out nocopy udt_UnicodeList ); end; / create or replace package body &main_user..pkg_DemoUnicodeArrays as function DemoInArrays ( a_StartingLength number, a_Array udt_UnicodeList ) return number is t_Length number; begin t_Length := a_StartingLength; for i in 1..a_Array.count loop t_Length := t_Length + length(a_Array(i)); end loop; return t_Length; end; procedure DemoInOutArrays ( a_NumElems number, a_Array in out udt_UnicodeList ) is begin for i in 1..a_NumElems loop a_Array(i) := unistr('Converted element ' || unistr('\3042') || ' # ') || to_char(i) || ' originally had length ' || to_char(length(a_Array(i))); end loop; end; procedure DemoOutArrays ( a_NumElems number, a_Array out udt_UnicodeList ) is begin for i in 1..a_NumElems loop a_Array(i) := unistr('Demo out element ') || unistr('\3042') || ' # ' || to_char(i); end loop; end; end; / create or replace package &main_user..pkg_DemoNumberArrays as type udt_NumberList is table of number index by binary_integer; function DemoInArrays ( a_StartingValue number, a_Array udt_NumberList ) return number; procedure DemoInOutArrays ( a_NumElems number, a_Array in out nocopy udt_NumberList ); procedure DemoOutArrays ( a_NumElems number, a_Array out nocopy udt_NumberList ); end; / create or replace package body &main_user..pkg_DemoNumberArrays as function DemoInArrays ( a_StartingValue number, a_Array udt_NumberList ) return number is t_Value number; begin t_Value := a_StartingValue; for i in 1..a_Array.count loop t_Value := t_Value + a_Array(i); end loop; return t_Value; end; procedure DemoInOutArrays ( a_NumElems number, a_Array in out udt_NumberList ) is begin for i in 1..a_NumElems loop a_Array(i) := a_Array(i) * 10; end loop; end; procedure DemoOutArrays ( a_NumElems number, a_Array out udt_NumberList ) is begin for i in 1..a_NumElems loop a_Array(i) := i * 100; end loop; end; end; / create or replace package &main_user..pkg_DemoDateArrays as type udt_DateList is table of date index by binary_integer; function DemoInArrays ( a_StartingValue number, a_BaseDate date, a_Array udt_DateList ) return number; procedure DemoInOutArrays ( a_NumElems number, a_Array in out nocopy udt_DateList ); procedure DemoOutArrays ( a_NumElems number, a_Array out nocopy udt_DateList ); end; / create or replace package body &main_user..pkg_DemoDateArrays as function DemoInArrays ( a_StartingValue number, a_BaseDate date, a_Array udt_DateList ) return number is t_Value number; begin t_Value := a_StartingValue; for i in 1..a_Array.count loop t_Value := t_Value + a_Array(i) - a_BaseDate; end loop; return t_Value; end; procedure DemoInOutArrays ( a_NumElems number, a_Array in out udt_DateList ) is begin for i in 1..a_NumElems loop a_Array(i) := a_Array(i) + 7; end loop; end; procedure DemoOutArrays ( a_NumElems number, a_Array out udt_DateList ) is begin for i in 1..a_NumElems loop a_Array(i) := to_date(20021212, 'YYYYMMDD') + i * 1.2; end loop; end; end; / create or replace package &main_user..pkg_DemoOutCursors as type udt_RefCursor is ref cursor; procedure DemoOutCursor ( a_MaxIntValue number, a_Cursor out udt_RefCursor ); end; / create or replace package body &main_user..pkg_DemoOutCursors as procedure DemoOutCursor ( a_MaxIntValue number, a_Cursor out udt_RefCursor ) is begin open a_Cursor for select IntCol, StringCol from DemoStrings where IntCol <= a_MaxIntValue order by IntCol; end; end; / create or replace package &main_user..pkg_DemoBooleans as type udt_BooleanList is table of boolean index by binary_integer; function GetStringRep ( a_Value boolean ) return varchar2; function IsLessThan10 ( a_Value number ) return boolean; function DemoInArrays ( a_Value udt_BooleanList ) return number; procedure DemoOutArrays ( a_NumElements number, a_Value out nocopy udt_BooleanList ); end; / create or replace package body &main_user..pkg_DemoBooleans as function GetStringRep ( a_Value boolean ) return varchar2 is begin if a_Value is null then return 'NULL'; elsif a_Value then return 'TRUE'; end if; return 'FALSE'; end; function IsLessThan10 ( a_Value number ) return boolean is begin return a_Value < 10; end; function DemoInArrays ( a_Value udt_BooleanList ) return number is t_Result pls_integer; begin t_Result := 0; for i in 1..a_Value.count loop if a_Value(i) then t_Result := t_Result + 1; end if; end loop; return t_Result; end; procedure DemoOutArrays ( a_NumElements number, a_Value out nocopy udt_BooleanList ) is begin for i in 1..a_NumElements loop a_Value(i) := (mod(i, 2) = 1); end loop; end; end; / create or replace package &main_user..pkg_DemoBindObject as function GetStringRep ( a_Object udt_Object ) return varchar2; end; / create or replace package body &main_user..pkg_DemoBindObject as function GetStringRep ( a_Object udt_SubObject ) return varchar2 is begin if a_Object is null then return 'null'; end if; return 'udt_SubObject(' || nvl(to_char(a_Object.SubNumberValue), 'null') || ', ' || case when a_Object.SubStringValue is null then 'null' else '''' || a_Object.SubStringValue || '''' end || ')'; end; function GetStringRep ( a_Array udt_ObjectArray ) return varchar2 is t_StringRep varchar2(4000); begin if a_Array is null then return 'null'; end if; t_StringRep := 'udt_ObjectArray('; for i in 1..a_Array.count loop if i > 1 then t_StringRep := t_StringRep || ', '; end if; t_StringRep := t_StringRep || GetStringRep(a_Array(i)); end loop; return t_StringRep || ')'; end; function GetStringRep ( a_Object udt_Object ) return varchar2 is begin if a_Object is null then return 'null'; end if; return 'udt_Object(' || nvl(to_char(a_Object.NumberValue), 'null') || ', ' || case when a_Object.StringValue is null then 'null' else '''' || a_Object.StringValue || '''' end || ', ' || case when a_Object.FixedCharValue is null then 'null' else '''' || a_Object.FixedCharValue || '''' end || ', ' || case when a_Object.DateValue is null then 'null' else 'to_date(''' || to_char(a_Object.DateValue, 'YYYY-MM-DD') || ''', ''YYYY-MM-DD'')' end || ', ' || case when a_Object.TimestampValue is null then 'null' else 'to_timestamp(''' || to_char(a_Object.TimestampValue, 'YYYY-MM-DD HH24:MI:SS') || ''', ''YYYY-MM-DD HH24:MI:SS'')' end || ', ' || GetStringRep(a_Object.SubObjectValue) || ', ' || GetStringRep(a_Object.SubObjectArray) || ')'; end; end; / create or replace package &main_user..pkg_DemoRecords as type udt_Record is record ( NumberValue number, StringValue varchar2(30), DateValue date, TimestampValue timestamp, BooleanValue boolean ); function GetStringRep ( a_Value udt_Record ) return varchar2; procedure DemoOut ( a_Value out nocopy udt_Record ); end; / create or replace package body &main_user..pkg_DemoRecords as function GetStringRep ( a_Value udt_Record ) return varchar2 is begin return 'udt_Record(' || nvl(to_char(a_Value.NumberValue), 'null') || ', ' || case when a_Value.StringValue is null then 'null' else '''' || a_Value.StringValue || '''' end || ', ' || case when a_Value.DateValue is null then 'null' else 'to_date(''' || to_char(a_Value.DateValue, 'YYYY-MM-DD') || ''', ''YYYY-MM-DD'')' end || ', ' || case when a_Value.TimestampValue is null then 'null' else 'to_timestamp(''' || to_char(a_Value.TimestampValue, 'YYYY-MM-DD HH24:MI:SS') || ''', ''YYYY-MM-DD HH24:MI:SS'')' end || ', ' || case when a_Value.BooleanValue is null then 'null' when a_Value.BooleanValue then 'true' else 'false' end || ')'; end; procedure DemoOut ( a_Value out nocopy udt_Record ) is begin a_Value.NumberValue := 25; a_Value.StringValue := 'String in record'; a_Value.DateValue := to_date(20160216, 'YYYYMMDD'); a_Value.TimestampValue := to_timestamp('20160216 18:23:55', 'YYYYMMDD HH24:MI:SS'); a_Value.BooleanValue := true; end; end; / create or replace package &main_user..pkg_DemoLOBs as procedure DemoInOutTempClob ( a_IntValue number, a_CLOB in out clob ); end; / create or replace package body &main_user..pkg_DemoLOBs as procedure DemoInOutTempClob ( a_IntValue number, a_CLOB in out clob ) is begin delete from DemoClobs where IntCol = a_IntValue; insert into DemoClobs ( IntCol, ClobCol ) values ( a_IntValue, a_CLOB ); select ClobCol into a_CLOB from DemoClobs where IntCol = a_IntValue; end; end; / create or replace procedure &main_user..proc_DemoInOut ( a_StringCol in out varchar2, a_UnicodeCol in out nvarchar2, a_FloatCol in out float, a_DoublePrecCol in out double precision, a_NumberCol in out number, a_DateCol in out date, a_TimestampCol in out timestamp, a_TimestampTZCol in out timestamp with time zone, a_IntervalDSCol in out interval day to second, a_IntervalYMCol in out interval year to month, a_BinaryFltCol in out binary_float, a_BinaryDoubleCol in out binary_double ) as begin a_StringCol := 'demostring'; a_UnicodeCol := 'demounicode'; a_FloatCol := a_FloatCol + a_FloatCol; a_DoublePrecCol := a_DoublePrecCol + a_DoublePrecCol; a_NumberCol := a_NumberCol + a_NumberCol; a_DateCol := a_DateCol + interval '1' year; a_TimestampCol := a_TimestampCol + interval '30' minute; a_TimestampTZCol := a_TimestampTZCol + interval '30' minute; a_IntervalDSCol := a_IntervalDSCol + a_IntervalDSCol; a_IntervalYMCol := a_IntervalYMCol + a_IntervalYMCol; a_BinaryFltCol := a_BinaryFltCol + a_BinaryFltCol; a_BinaryDoubleCol := a_BinaryDoubleCol + a_BinaryDoubleCol; end; / -- create type and table for demoing advanced queuing with objects create or replace type &main_user..udt_Book as object ( Title varchar2(100), Authors varchar2(100), Price number(5,2) ); / -- create queues for demoing advanced queuing with objects and RAW begin dbms_aqadm.create_queue_table('&main_user..BOOK_QUEUE_TAB', '&main_user..UDT_BOOK'); dbms_aqadm.create_queue('&main_user..DEMO_BOOK_QUEUE', '&main_user..BOOK_QUEUE_TAB'); dbms_aqadm.start_queue('&main_user..DEMO_BOOK_QUEUE'); dbms_aqadm.create_queue_table('&main_user..RAW_QUEUE_TAB', 'RAW'); dbms_aqadm.create_queue('&main_user..DEMO_RAW_QUEUE', '&main_user..RAW_QUEUE_TAB'); dbms_aqadm.start_queue('&main_user..DEMO_RAW_QUEUE'); end; / odpi-5.6.4/src/000077500000000000000000000000001510466437300132615ustar00rootroot00000000000000odpi-5.6.4/src/dpiConn.c000066400000000000000000003724311510466437300150310ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiConn.c // Implementation of connection. //----------------------------------------------------------------------------- #include "dpiImpl.h" #include // forward declarations of internal functions only used in this file static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle, dpiError *error); static int dpiConn__createStandalone(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, const dpiConnCreateParams *createParams, dpiError *error); static int dpiConn__get(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error); static int dpiConn__getHandles(dpiConn *conn, dpiError *error); static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error); static int dpiConn__getSession(dpiConn *conn, uint32_t mode, const char *connectString, uint32_t connectStringLength, dpiConnCreateParams *params, void *authInfo, dpiError *error); static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle, uint32_t handleType, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const dpiCommonCreateParams *commonParams, const dpiConnCreateParams *params, int *used, dpiError *error); static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey, void *handle, uint32_t handleType, uint32_t attribute, const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns, dpiError *error); static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey, dpiShardingKeyColumn *column, dpiError *error); //----------------------------------------------------------------------------- // dpiConn__attachExternal() [INTERNAL] // Attach to the server and session of an existing service context handle. //----------------------------------------------------------------------------- static int dpiConn__attachExternal(dpiConn *conn, void *externalHandle, dpiError *error) { // mark connection as using an external handle so that no attempts are // made to close it conn->externalHandle = 1; // acquire handles from existing service context handle conn->handle = externalHandle; if (dpiConn__getHandles(conn, error) < 0) { conn->handle = NULL; return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__check() [INTERNAL] // Validate the connection handle and that it is still connected to the // database. //----------------------------------------------------------------------------- static int dpiConn__check(dpiConn *conn, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(conn, DPI_HTYPE_CONN, fnName, error) < 0) return DPI_FAILURE; return dpiConn__checkConnected(conn, error); } //----------------------------------------------------------------------------- // dpiConn__checkConnected() [INTERNAL] // Check to see if the connection is still open and raise an exception if it // is not. // Maintainers: keep these checks in sync with dpiConn_getIsHealthy() //----------------------------------------------------------------------------- int dpiConn__checkConnected(dpiConn *conn, dpiError *error) { if (!conn->handle || conn->closing || conn->deadSession || (conn->pool && !conn->pool->handle)) return dpiError__set(error, "check connected", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__clearTransaction() [INTERNAL] // Clears the service context of any associated transaction. //----------------------------------------------------------------------------- int dpiConn__clearTransaction(dpiConn *conn, dpiError *error) { return dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, NULL, 0, DPI_OCI_ATTR_TRANS, "clear transaction", error); } //----------------------------------------------------------------------------- // dpiConn__close() [INTERNAL] // Internal method used for closing the connection. Any transaction is rolled // back and any handles allocated are freed. For connections acquired from a // pool and that aren't marked as needed to be dropped, the last time used is // updated. This is called from dpiConn_close() where errors are expected to be // propagated and from dpiConn__free() where errors are ignored. //----------------------------------------------------------------------------- static int dpiConn__close(dpiConn *conn, uint32_t mode, const char *tag, uint32_t tagLength, int propagateErrors, dpiError *error) { int status, txnInProgress; uint32_t serverStatus, i; time_t *lastTimeUsed; dpiObject *obj; dpiStmt *stmt; dpiLob *lob; // rollback any outstanding transaction, if one is in progress; drop the // session if any errors take place txnInProgress = 0; if (!conn->deadSession && !conn->externalHandle && conn->sessionHandle) { txnInProgress = 1; if (conn->env->versionInfo->versionNum >= 12) dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, &txnInProgress, NULL, DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS, NULL, error); } if (txnInProgress && dpiOci__transRollback(conn, propagateErrors, error) < 0) conn->deadSession = 1; // Unset the tranasaction handle if one exists currently // (Required for tpc and sessionless transactions when the active // transaction is released to a pool without suspending) dpiConn__clearTransaction(conn, error); // close all objects; note that no references are retained by the // handle list (otherwise all objects would be left until an explicit // close of the connection was made) so a reference needs to be acquired // first, as otherwise the object may be freed while the close is being // performed! if (conn->objects && !conn->externalHandle) { for (i = 0; i < conn->objects->numSlots; i++) { obj = (dpiObject*) conn->objects->handles[i]; if (!obj) continue; if (conn->env->threaded) { dpiMutex__acquire(conn->env->mutex); status = dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, NULL, NULL); if (status == DPI_SUCCESS) obj->refCount += 1; dpiMutex__release(conn->env->mutex); if (status < 0) continue; } status = dpiObject__close(obj, propagateErrors, error); if (conn->env->threaded) dpiGen__setRefCount(obj, error, -1); if (status < 0) return DPI_FAILURE; } } // close all open statements; note that no references are retained by the // handle list (otherwise all statements would be left open until an // explicit close was made of either the statement or the connection) so // a reference needs to be acquired first, as otherwise the statement may // be freed while the close is being performed! if (conn->openStmts && !conn->externalHandle) { for (i = 0; i < conn->openStmts->numSlots; i++) { stmt = (dpiStmt*) conn->openStmts->handles[i]; if (!stmt) continue; if (conn->env->threaded) { dpiMutex__acquire(conn->env->mutex); status = dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, NULL, NULL); if (status == DPI_SUCCESS) stmt->refCount += 1; dpiMutex__release(conn->env->mutex); if (status < 0) continue; } status = dpiStmt__close(stmt, NULL, 0, propagateErrors, error); if (conn->env->threaded) dpiGen__setRefCount(stmt, error, -1); if (status < 0) return DPI_FAILURE; } } // close all open LOBs; the same comments apply as for statements // NOTE: Oracle Client 20 automatically closes all open LOBs which makes // this code redundant; as such, it can be removed once the minimum version // supported by ODPI-C is 20 if (conn->openLobs && !conn->externalHandle) { for (i = 0; i < conn->openLobs->numSlots; i++) { lob = (dpiLob*) conn->openLobs->handles[i]; if (!lob) continue; if (conn->env->threaded) { dpiMutex__acquire(conn->env->mutex); status = dpiGen__checkHandle(lob, DPI_HTYPE_LOB, NULL, NULL); if (status == DPI_SUCCESS) lob->refCount += 1; dpiMutex__release(conn->env->mutex); if (status < 0) continue; } status = dpiLob__close(lob, propagateErrors, error); if (conn->env->threaded) dpiGen__setRefCount(lob, error, -1); if (status < 0) return DPI_FAILURE; } } // handle connections created with an external handle if (conn->externalHandle) { conn->sessionHandle = NULL; // handle standalone connections } else if (conn->standalone) { // end session and free session handle if (dpiOci__sessionEnd(conn, propagateErrors, error) < 0) return DPI_FAILURE; dpiOci__handleFree(conn->sessionHandle, DPI_OCI_HTYPE_SESSION); conn->sessionHandle = NULL; // detach from server and free server handle if (dpiOci__serverDetach(conn, propagateErrors, error) < 0) return DPI_FAILURE; dpiOci__handleFree(conn->serverHandle, DPI_OCI_HTYPE_SERVER); // free service context handle dpiOci__handleFree(conn->handle, DPI_OCI_HTYPE_SVCCTX); // handle pooled connections } else { // if session is to be dropped, mark it as a dead session if (mode & DPI_OCI_SESSRLS_DROPSESS) { conn->deadSession = 1; // otherwise, check server status; if not connected, ensure session is // dropped } else if (conn->serverHandle) { if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &serverStatus, NULL, DPI_OCI_ATTR_SERVER_STATUS, "get server status", error) < 0 || serverStatus != DPI_OCI_SERVER_NORMAL) conn->deadSession = 1; } // update last time used (if the session isn't going to be dropped) // clear last time used (if the session is going to be dropped) // do nothing, however, if not using a pool or the pool is being closed if (conn->sessionHandle && conn->pool && conn->pool->handle) { // get the pointer from the context associated with the session lastTimeUsed = NULL; if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED, (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), (void**) &lastTimeUsed, propagateErrors, error) < 0) return DPI_FAILURE; // if pointer available and session is going to be dropped, clear // memory in order to avoid memory leak in OCI if (lastTimeUsed && conn->deadSession) { dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED, (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), NULL, 0, error); dpiOci__memoryFree(conn, lastTimeUsed, error); lastTimeUsed = NULL; // otherwise, if the pointer is not available, allocate a new // pointer and set it } else if (!lastTimeUsed && !conn->deadSession) { if (dpiOci__memoryAlloc(conn, (void**) &lastTimeUsed, sizeof(time_t), propagateErrors, error) < 0) return DPI_FAILURE; if (dpiOci__contextSetValue(conn, DPI_CONTEXT_LAST_TIME_USED, (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), lastTimeUsed, propagateErrors, error) < 0) { dpiOci__memoryFree(conn, lastTimeUsed, error); lastTimeUsed = NULL; } } // set last time used (used when acquiring a session to determine // if ping is required) if (lastTimeUsed) *lastTimeUsed = time(NULL); } // release session if (conn->deadSession) mode |= DPI_OCI_SESSRLS_DROPSESS; else if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, NULL) == DPI_SUCCESS && (mode & DPI_MODE_CONN_CLOSE_RETAG) && tag && tagLength > 0) mode |= DPI_OCI_SESSRLS_MULTIPROPERTY_TAG; if (dpiOci__sessionRelease(conn, tag, tagLength, mode, propagateErrors, error) < 0) return DPI_FAILURE; conn->sessionHandle = NULL; } conn->handle = NULL; conn->serverHandle = NULL; // destroy sharding and super sharding key descriptors, if applicable if (conn->shardingKey) { dpiOci__descriptorFree(conn->shardingKey, DPI_OCI_DTYPE_SHARDING_KEY); conn->shardingKey = NULL; } if (conn->superShardingKey) { dpiOci__descriptorFree(conn->superShardingKey, DPI_OCI_DTYPE_SHARDING_KEY); conn->superShardingKey = NULL; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__commit() [PRIVATE] // Internal method used to commit the transaction associated with the // connection. Once the commit has taken place, the transaction handle // associated with the connection is cleared. //----------------------------------------------------------------------------- int dpiConn__commit(dpiConn *conn, dpiError *error) { if (dpiOci__transCommit(conn, conn->commitMode, error) < 0) return DPI_FAILURE; if (dpiConn__clearTransaction(conn, error) < 0) return DPI_FAILURE; conn->commitMode = DPI_OCI_DEFAULT; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__create() [PRIVATE] // Perform internal initialization of the connection. //----------------------------------------------------------------------------- int dpiConn__create(dpiConn *conn, const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, dpiPool *pool, const dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiError *error) { void *envHandle = NULL; int status; // mark connection as being created so that errors that are raised do not // do dead connection detection conn->creating = 1; // allocate handle lists for statements, LOBs and objects if (dpiHandleList__create(&conn->openStmts, error) < 0) return DPI_FAILURE; if (dpiHandleList__create(&conn->openLobs, error) < 0) return DPI_FAILURE; if (dpiHandleList__create(&conn->objects, error) < 0) return DPI_FAILURE; // if an external service context handle is provided, acquire the // environment handle from it; need a temporary environment handle in order // to do so if (createParams->externalHandle) { error->env = conn->env; if (dpiOci__envNlsCreate(&conn->env->handle, DPI_OCI_DEFAULT, 0, 0, error) < 0) return DPI_FAILURE; if (dpiOci__handleAlloc(conn->env->handle, &error->handle, DPI_OCI_HTYPE_ERROR, "allocate temp OCI error", error) < 0) return DPI_FAILURE; if (dpiOci__attrGet(createParams->externalHandle, DPI_OCI_HTYPE_SVCCTX, &envHandle, NULL, DPI_OCI_ATTR_ENV, "get env handle", error) < 0) return DPI_FAILURE; dpiOci__handleFree(conn->env->handle, DPI_OCI_HTYPE_ENV); error->handle = NULL; conn->env->handle = NULL; } // initialize environment (for non-pooled connections) if (!pool && dpiEnv__init(conn->env, context, commonParams, envHandle, commonParams->createMode, error) < 0) return DPI_FAILURE; // if a handle is specified, use it if (createParams->externalHandle) return dpiConn__attachExternal(conn, createParams->externalHandle, error); // connection class, sharding and the use of session pools require the use // of the OCISessionGet() method; all other cases use the OCISessionBegin() // method which is more capable if (pool || (createParams->connectionClass && createParams->connectionClassLength > 0) || createParams->shardingKeyColumns || createParams->superShardingKeyColumns) { status = dpiConn__get(conn, userName, userNameLength, password, passwordLength, connectString, connectStringLength, commonParams, createParams, pool, error); } else { status = dpiConn__createStandalone(conn, userName, userNameLength, password, passwordLength, connectString, connectStringLength, commonParams, createParams, error); } // mark connection as no longer being created so that subsequent errors // that are raised do perform dead connection detection conn->creating = 0; return status; } //----------------------------------------------------------------------------- // dpiConn__createStandalone() [PRIVATE] // Create a standalone connection to the database using the parameters // specified. //----------------------------------------------------------------------------- static int dpiConn__createStandalone(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, const dpiConnCreateParams *createParams, dpiError *error) { uint32_t credentialType, authMode; int used = 0; // mark the connection as a standalone connection conn->standalone = 1; // allocate the server handle if (dpiOci__handleAlloc(conn->env->handle, &conn->serverHandle, DPI_OCI_HTYPE_SERVER, "allocate server handle", error) < 0) return DPI_FAILURE; // attach to the server if (dpiOci__serverAttach(conn, connectString, connectStringLength, error) < 0) return DPI_FAILURE; // allocate the service context handle if (dpiOci__handleAlloc(conn->env->handle, &conn->handle, DPI_OCI_HTYPE_SVCCTX, "allocate service context handle", error) < 0) return DPI_FAILURE; // set attribute for server handle if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->serverHandle, 0, DPI_OCI_ATTR_SERVER, "set server handle", error) < 0) return DPI_FAILURE; // allocate the session handle if (dpiOci__handleAlloc(conn->env->handle, &conn->sessionHandle, DPI_OCI_HTYPE_SESSION, "allocate session handle", error) < 0) return DPI_FAILURE; // driver name and edition are only relevant for standalone connections if (dpiUtils__setAttributesFromCommonCreateParams(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, commonParams, error) < 0) return DPI_FAILURE; // set access token for token based authentication if (commonParams->accessToken) { if (dpiUtils__setAccessTokenAttributes(conn->sessionHandle, commonParams->accessToken, conn->env->versionInfo, error) < 0) return DPI_FAILURE; } // populate attributes on the session handle if (dpiConn__setAttributesFromCreateParams(conn, conn->sessionHandle, DPI_OCI_HTYPE_SESSION, userName, userNameLength, password, passwordLength, commonParams, createParams, &used, error) < 0) return DPI_FAILURE; // set the session handle on the service context handle if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->sessionHandle, 0, DPI_OCI_ATTR_SESSION, "set session handle", error) < 0) return DPI_FAILURE; // if a new password is specified, change it (this also creates the session // so a call to OCISessionBegin() is not needed) if (createParams->newPassword && createParams->newPasswordLength > 0) { authMode = DPI_OCI_AUTH; if (createParams->authMode & DPI_MODE_AUTH_SYSDBA) authMode |= DPI_OCI_CPW_SYSDBA; if (createParams->authMode & DPI_MODE_AUTH_SYSOPER) authMode |= DPI_OCI_CPW_SYSOPER; if (createParams->authMode & DPI_MODE_AUTH_SYSASM) authMode |= DPI_OCI_CPW_SYSASM; if (createParams->authMode & DPI_MODE_AUTH_SYSBKP) authMode |= DPI_OCI_CPW_SYSBKP; if (createParams->authMode & DPI_MODE_AUTH_SYSDGD) authMode |= DPI_OCI_CPW_SYSDGD; if (createParams->authMode & DPI_MODE_AUTH_SYSKMT) authMode |= DPI_OCI_CPW_SYSKMT; return dpiOci__passwordChange(conn, userName, userNameLength, password, passwordLength, createParams->newPassword, createParams->newPasswordLength, authMode, error); } // begin the session credentialType = (createParams->externalAuth) ? DPI_OCI_CRED_EXT : DPI_OCI_CRED_RDBMS; authMode = createParams->authMode | DPI_OCI_STMT_CACHE; if (dpiOci__sessionBegin(conn, credentialType, authMode, error) < 0) return DPI_FAILURE; if (dpiConn__getServerCharset(conn, error) < 0) return DPI_FAILURE; // set the statement cache size if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, (void*) &commonParams->stmtCacheSize, 0, DPI_OCI_ATTR_STMTCACHESIZE, "set stmt cache size", error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__free() [INTERNAL] // Free the memory and any resources associated with the connection. //----------------------------------------------------------------------------- void dpiConn__free(dpiConn *conn, dpiError *error) { if (conn->handle) dpiConn__close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0, 0, error); if (conn->pool) { dpiGen__setRefCount(conn->pool, error, -1); conn->pool = NULL; conn->env = NULL; } if (conn->transactionHandle) { dpiOci__handleFree(conn->transactionHandle, DPI_OCI_HTYPE_TRANS); conn->transactionHandle = NULL; } if (conn->env) { dpiEnv__free(conn->env, error); conn->env = NULL; } if (conn->releaseString) { dpiUtils__freeMemory((void*) conn->releaseString); conn->releaseString = NULL; } if (conn->openStmts) { dpiHandleList__free(conn->openStmts); conn->openStmts = NULL; } if (conn->openLobs) { dpiHandleList__free(conn->openLobs); conn->openLobs = NULL; } if (conn->objects) { dpiHandleList__free(conn->objects); conn->objects = NULL; } if (conn->info) { dpiUtils__freeMemory(conn->info); conn->info = NULL; } dpiUtils__freeMemory(conn); } //----------------------------------------------------------------------------- // dpiConn__get() [INTERNAL] // Create a connection to the database using the parameters specified. This // method uses the simplified OCI session creation protocol which is required // when using pools and session tagging. //----------------------------------------------------------------------------- static int dpiConn__get(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiPool *pool, dpiError *error) { int externalAuth, status; void *authInfo; uint32_t mode; int used = 0; // clear pointers if length is 0 if (userNameLength == 0) userName = NULL; if (passwordLength == 0) password = NULL; // set things up for the call to acquire a session if (pool) { dpiGen__setRefCount(pool, error, 1); conn->pool = pool; mode = DPI_OCI_SESSGET_SPOOL; externalAuth = pool->externalAuth; if (userName && pool->homogeneous) return dpiError__set(error, "check proxy", DPI_ERR_INVALID_PROXY); // if the userName is provided but no password is provided and external // authentication is not being used, proxy authentication is taking // place if (userName && !password && !externalAuth) mode |= DPI_OCI_SESSGET_CREDPROXY; if (createParams->matchAnyTag) mode |= DPI_OCI_SESSGET_SPOOL_MATCHANY; if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, NULL) == DPI_SUCCESS && createParams->tag && createParams->tagLength > 0) mode |= DPI_OCI_SESSGET_MULTIPROPERTY_TAG; } else { mode = DPI_OCI_SESSGET_STMTCACHE; externalAuth = createParams->externalAuth; } if (createParams->authMode & DPI_MODE_AUTH_SYSDBA) mode |= DPI_OCI_SESSGET_SYSDBA; if (externalAuth) mode |= DPI_OCI_SESSGET_CREDEXT; // create authorization handle if (dpiOci__handleAlloc(conn->env->handle, &authInfo, DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0) return DPI_FAILURE; // set attributes for create parameters if (dpiConn__setAttributesFromCreateParams(conn, authInfo, DPI_OCI_HTYPE_AUTHINFO, userName, userNameLength, password, passwordLength, commonParams, createParams, &used, error) < 0) { dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO); return DPI_FAILURE; } // get a session from the pool status = dpiConn__getSession(conn, mode, connectString, connectStringLength, createParams, (used) ? authInfo : NULL, error); dpiOci__handleFree(authInfo, DPI_OCI_HTYPE_AUTHINFO); if (status < 0) return status; return dpiConn__getServerCharset(conn, error); } //----------------------------------------------------------------------------- // dpiConn__getAttributeText() [INTERNAL] // Get the value of the OCI attribute from a text string. //----------------------------------------------------------------------------- static int dpiConn__getAttributeText(dpiConn *conn, uint32_t attribute, const char **value, uint32_t *valueLength, const char *fnName) { dpiError error; int status; // validate parameters if (dpiConn__check(conn, fnName, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, value) DPI_CHECK_PTR_NOT_NULL(conn, valueLength) // determine pointer to pass (OCI uses different sizes) switch (attribute) { case DPI_OCI_ATTR_CURRENT_SCHEMA: case DPI_OCI_ATTR_LTXID: case DPI_OCI_ATTR_EDITION: status = dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, (void*) value, valueLength, attribute, "get session value", &error); break; case DPI_OCI_ATTR_INSTNAME: case DPI_OCI_ATTR_INTERNAL_NAME: case DPI_OCI_ATTR_EXTERNAL_NAME: case DPI_OCI_ATTR_DBNAME: case DPI_OCI_ATTR_DBDOMAIN: case DPI_OCI_ATTR_SERVICENAME: status = dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, (void*) value, valueLength, attribute, "get server value", &error); break; default: status = dpiError__set(&error, "get attribute text", DPI_ERR_NOT_SUPPORTED); break; } return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn__getHandles() [INTERNAL] // Get the server and session handle from the service context handle. //----------------------------------------------------------------------------- static int dpiConn__getHandles(dpiConn *conn, dpiError *error) { if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, (void*) &conn->sessionHandle, NULL, DPI_OCI_ATTR_SESSION, "get session handle", error) < 0) return DPI_FAILURE; if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, (void*) &conn->serverHandle, NULL, DPI_OCI_ATTR_SERVER, "get server handle", error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__getInfo() [INTERNAL] // Return information about the connection in the provided structure. //----------------------------------------------------------------------------- static int dpiConn__getInfo(dpiConn *conn, dpiError *error) { uint8_t temp8; // if the cache has been populated and we are not using DRCP, no need to do // anything further if (conn->info && conn->info->serverType != DPI_SERVER_TYPE_UNKNOWN && conn->info->serverType != DPI_SERVER_TYPE_POOLED) return DPI_SUCCESS; // allocate memory for the cached information, if needed if (!conn->info) { if (dpiUtils__allocateMemory(1, sizeof(dpiConnInfo), 1, "allocate connection info", (void**) &conn->info, error) < 0) return DPI_FAILURE; } // determine database domain if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, (void*) &conn->info->dbDomain, &conn->info->dbDomainLength, DPI_OCI_ATTR_DBDOMAIN, "get database domain", error) < 0) return DPI_FAILURE; // determine database name if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, (void*) &conn->info->dbName, &conn->info->dbNameLength, DPI_OCI_ATTR_DBNAME, "get database name", error) < 0) return DPI_FAILURE; // determine instance name if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, (void*) &conn->info->instanceName, &conn->info->instanceNameLength, DPI_OCI_ATTR_INSTNAME, "get instance name", error) < 0) return DPI_FAILURE; // determine service name if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, (void*) &conn->info->serviceName, &conn->info->serviceNameLength, DPI_OCI_ATTR_SERVICENAME, "get service name", error) < 0) return DPI_FAILURE; // determine max identifier length; this is only available with Oracle // Client 12.2 and higher; databases older than 12.2 are known to be 30; // databases newer than that cannot be determined so zero is used. if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, NULL) == DPI_SUCCESS) { if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &conn->info->maxIdentifierLength, NULL, DPI_OCI_ATTR_MAX_IDENTIFIER_LEN, "get max identifier length", error) < 0) return DPI_FAILURE; } else if (conn->versionInfo.versionNum < 12 || (conn->versionInfo.versionNum == 12 && conn->versionInfo.releaseNum < 2)) { conn->info->maxIdentifierLength = 30; } // determine max open cursors if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 1, NULL) == DPI_SUCCESS) { if (dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, &conn->info->maxOpenCursors, NULL, DPI_OCI_ATTR_MAX_OPEN_CURSORS, "get max open cursors", error) < 0) return DPI_FAILURE; } // determine the server type, if possible; it is determined last in order // to ensure that only completely cached information is returned if (dpiUtils__checkClientVersion(conn->env->versionInfo, 23, 4, NULL) == DPI_SUCCESS) { if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &temp8, NULL, DPI_OCI_ATTR_SERVER_TYPE, "get server type", error) < 0) return DPI_FAILURE; conn->info->serverType = temp8; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__getJsonTDO() [INTERNAL] // Internal method used for ensuring that the JSON TDO has been cached on the // connection. //----------------------------------------------------------------------------- int dpiConn__getJsonTDO(dpiConn *conn, dpiError *error) { if (conn->jsonTDO) return DPI_SUCCESS; return dpiOci__typeByName(conn, "SYS", 3, "JSON", 4, &conn->jsonTDO, error); } //----------------------------------------------------------------------------- // dpiConn__getRawTDO() [INTERNAL] // Internal method used for ensuring that the RAW TDO has been cached on the // connection. //----------------------------------------------------------------------------- int dpiConn__getRawTDO(dpiConn *conn, dpiError *error) { if (conn->rawTDO) return DPI_SUCCESS; return dpiOci__typeByName(conn, "SYS", 3, "RAW", 3, &conn->rawTDO, error); } //----------------------------------------------------------------------------- // dpiConn__getServerCharset() [INTERNAL] // Internal method used for retrieving the server character set. This is used // to determine if any conversion is required when transferring strings between // the client and the server. //----------------------------------------------------------------------------- static int dpiConn__getServerCharset(dpiConn *conn, dpiError *error) { return dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &conn->charsetId, NULL, DPI_OCI_ATTR_CHARSET_ID, "get server charset id", error); } //----------------------------------------------------------------------------- // dpiConn__getServerVersion() [INTERNAL] // Internal method used for ensuring that the server version has been cached // on the connection. //----------------------------------------------------------------------------- int dpiConn__getServerVersion(dpiConn *conn, int wantReleaseString, dpiError *error) { char buffer[512], *releaseString; dpiVersionInfo *tempVersionInfo; uint32_t serverRelease, mode; uint32_t releaseStringLength; int ociCanCache; // nothing to do if the server version has been cached earlier if (conn->releaseString || (conn->versionInfo.versionNum > 0 && !wantReleaseString)) return DPI_SUCCESS; // the server version is not available in the cache so it must be // determined; as of Oracle Client 20.3, a special mode is available that // causes OCI to cache the server version information, so this mode can be // used if the release string information is not desired and the client // supports it ociCanCache = ((conn->env->versionInfo->versionNum > 20 || (conn->env->versionInfo->versionNum == 20 && conn->env->versionInfo->releaseNum >= 3)) && !wantReleaseString); // for earlier versions where the OCI cache is not available, pooled // connections can cache the information on the session in order to avoid // the round trip, but again only if the release string is not desired; // nothing further needs to be done if this cache is present if (conn->pool && !ociCanCache && !wantReleaseString) { tempVersionInfo = NULL; if (dpiOci__contextGetValue(conn, DPI_CONTEXT_SERVER_VERSION, (uint32_t) (sizeof(DPI_CONTEXT_SERVER_VERSION) - 1), (void**) &tempVersionInfo, 1, error) < 0) return DPI_FAILURE; if (tempVersionInfo) { memcpy(&conn->versionInfo, tempVersionInfo, sizeof(conn->versionInfo)); return DPI_SUCCESS; } } // calculate the server version by making the appropriate call if (ociCanCache) { mode = DPI_OCI_SRVRELEASE2_CACHED; releaseString = NULL; releaseStringLength = 0; } else { mode = DPI_OCI_DEFAULT; releaseString = buffer; releaseStringLength = sizeof(buffer); } if (dpiOci__serverRelease(conn, releaseString, releaseStringLength, &serverRelease, mode, error) < 0) return DPI_FAILURE; // store release string, if applicable if (releaseString) { conn->releaseStringLength = (uint32_t) strlen(releaseString); if (dpiUtils__allocateMemory(1, conn->releaseStringLength, 0, "allocate release string", (void**) &conn->releaseString, error) < 0) return DPI_FAILURE; strncpy( (char*) conn->releaseString, releaseString, conn->releaseStringLength); } // process version number conn->versionInfo.versionNum = (int)((serverRelease >> 24) & 0xFF); if (conn->versionInfo.versionNum >= 18) { conn->versionInfo.releaseNum = (int)((serverRelease >> 16) & 0xFF); conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0x0F); conn->versionInfo.portReleaseNum = (int)((serverRelease >> 4) & 0xFF); conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xF); } else { conn->versionInfo.releaseNum = (int)((serverRelease >> 20) & 0x0F); conn->versionInfo.updateNum = (int)((serverRelease >> 12) & 0xFF); conn->versionInfo.portReleaseNum = (int)((serverRelease >> 8) & 0x0F); conn->versionInfo.portUpdateNum = (int)((serverRelease) & 0xFF); } conn->versionInfo.fullVersionNum = (uint32_t) DPI_ORACLE_VERSION_TO_NUMBER(conn->versionInfo.versionNum, conn->versionInfo.releaseNum, conn->versionInfo.updateNum, conn->versionInfo.portReleaseNum, conn->versionInfo.portUpdateNum); // for earlier versions where the OCI cache is not available, store the // version information on the session in order to avoid the round-trip the // next time the pooled session is acquired from the pool if (conn->pool && !ociCanCache) { if (dpiOci__memoryAlloc(conn, (void**) &tempVersionInfo, sizeof(conn->versionInfo), 1, error) < 0) return DPI_FAILURE; memcpy(tempVersionInfo, &conn->versionInfo, sizeof(conn->versionInfo)); if (dpiOci__contextSetValue(conn, DPI_CONTEXT_SERVER_VERSION, (uint32_t) (sizeof(DPI_CONTEXT_SERVER_VERSION) - 1), tempVersionInfo, 1, error) < 0) { dpiOci__memoryFree(conn, tempVersionInfo, error); } } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__getSession() [INTERNAL] // Ping and loop until we get a good session. When a database instance goes // down, it can leave several bad connections that need to be flushed out // before a good connection can be acquired. If the connection is brand new // (ping time context value has not been set) there is no need to do a ping. // This also ensures that the loop cannot run forever! //----------------------------------------------------------------------------- static int dpiConn__getSession(dpiConn *conn, uint32_t mode, const char *connectString, uint32_t connectStringLength, dpiConnCreateParams *params, void *authInfo, dpiError *error) { uint8_t savedBreakOnTimeout, breakOnTimeout; uint32_t savedTimeout; time_t *lastTimeUsed; while (1) { // acquire the new session params->outNewSession = 0; if (dpiOci__sessionGet(conn->env->handle, &conn->handle, authInfo, connectString, connectStringLength, params->tag, params->tagLength, ¶ms->outTag, ¶ms->outTagLength, ¶ms->outTagFound, mode, error) < 0) return DPI_FAILURE; // get session and server handles if (dpiConn__getHandles(conn, error) < 0) return DPI_FAILURE; // for standalone connections, nothing more needs to be done if (!conn->pool) { params->outNewSession = 1; break; } // remainder of the loop is for pooled connections only; get last time // used from session context; if value is not found, a new connection // has been created and there is no need to perform a ping lastTimeUsed = NULL; if (dpiOci__contextGetValue(conn, DPI_CONTEXT_LAST_TIME_USED, (uint32_t) (sizeof(DPI_CONTEXT_LAST_TIME_USED) - 1), (void**) &lastTimeUsed, 1, error) < 0) return DPI_FAILURE; if (!lastTimeUsed) { params->outNewSession = 1; // for pooled connections, set the statement cache size; when a // pool is created, the minSessions value is used to create // connections and these use the default statement cache size, not // the statement cache size specified for the pool; setting the // value here eliminates that discrepancy if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &conn->pool->stmtCacheSize, 0, DPI_OCI_ATTR_STMTCACHESIZE, "set stmt cache size", error) < 0) return DPI_FAILURE; break; } // if ping interval is negative or the ping interval (in seconds) // has not been exceeded yet, there is also no need to perform a ping if (conn->pool->pingInterval < 0 || *lastTimeUsed + conn->pool->pingInterval > time(NULL)) break; // ping needs to be done at this point; set parameters to ensure that // the ping does not take too long to complete; keep original values so // that they can be restored after the ping is completed dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &savedTimeout, NULL, DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, error); dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &conn->pool->pingTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, error); if (conn->env->versionInfo->versionNum >= 12) { dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &savedBreakOnTimeout, NULL, DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); breakOnTimeout = 0; dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &breakOnTimeout, 0, DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); } // if ping is successful, the connection is valid and can be returned; // restore original network parameters if (dpiOci__ping(conn, error) == 0) { dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &savedTimeout, 0, DPI_OCI_ATTR_RECEIVE_TIMEOUT, NULL, error); if (conn->env->versionInfo->versionNum >= 12) dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &savedBreakOnTimeout, 0, DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT, NULL, error); break; } // session is bad, need to release and drop it dpiOci__sessionRelease(conn, NULL, 0, DPI_OCI_SESSRLS_DROPSESS, 0, error); conn->handle = NULL; conn->serverHandle = NULL; conn->sessionHandle = NULL; conn->deadSession = 0; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__newVector() [INTERNAL] // Internal method for creating a vector. If vector information is supplied // the vector is populated with this information. //----------------------------------------------------------------------------- int dpiConn__newVector(dpiConn *conn, dpiVectorInfo *info, dpiVector **vector, dpiError *error) { dpiVector *tempVector; if (dpiVector__allocate(conn, &tempVector, error) < 0) return DPI_FAILURE; if (info) { if (dpiOci__vectorFromArray(tempVector, info, error) < 0) { dpiVector__free(tempVector, error); return DPI_FAILURE; } } *vector = tempVector; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__rollback() [PUBLIC] // Internal method for rolling back the transaction associated with the // connection. Once the rollback has taken place, the transaction handle // associated with the connection is cleared. //----------------------------------------------------------------------------- int dpiConn__rollback(dpiConn *conn, dpiError *error) { if (dpiOci__transRollback(conn, 1, error) < 0) return DPI_FAILURE; if (dpiConn__clearTransaction(conn, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__setAppContext() [INTERNAL] // Populate the session handle with the application context. //----------------------------------------------------------------------------- static int dpiConn__setAppContext(void *handle, uint32_t handleType, const dpiConnCreateParams *params, dpiError *error) { void *listHandle, *entryHandle; dpiAppContext *entry; uint32_t i; // set the number of application context entries if (dpiOci__attrSet(handle, handleType, (void*) ¶ms->numAppContext, sizeof(params->numAppContext), DPI_OCI_ATTR_APPCTX_SIZE, "set app context size", error) < 0) return DPI_FAILURE; // get the application context list handle if (dpiOci__attrGet(handle, handleType, &listHandle, NULL, DPI_OCI_ATTR_APPCTX_LIST, "get context list handle", error) < 0) return DPI_FAILURE; // set each application context entry for (i = 0; i < params->numAppContext; i++) { entry = ¶ms->appContext[i]; // retrieve the context element descriptor if (dpiOci__paramGet(listHandle, DPI_OCI_DTYPE_PARAM, &entryHandle, i + 1, "get context entry handle", error) < 0) return DPI_FAILURE; // set the namespace name if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, (void*) entry->namespaceName, entry->namespaceNameLength, DPI_OCI_ATTR_APPCTX_NAME, "set namespace name", error) < 0) return DPI_FAILURE; // set the name if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, (void*) entry->name, entry->nameLength, DPI_OCI_ATTR_APPCTX_ATTR, "set name", error) < 0) return DPI_FAILURE; // set the value if (dpiOci__attrSet(entryHandle, DPI_OCI_DTYPE_PARAM, (void*) entry->value, entry->valueLength, DPI_OCI_ATTR_APPCTX_VALUE, "set value", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__setAttributesFromCreateParams() [INTERNAL] // Populate the authorization info structure or session handle using the // create parameters specified. //----------------------------------------------------------------------------- static int dpiConn__setAttributesFromCreateParams(dpiConn *conn, void *handle, uint32_t handleType, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const dpiCommonCreateParams *commonParams, const dpiConnCreateParams *params, int *used, dpiError *error) { uint32_t purity; // the handle is required for all external authentication scenarios except // when token authentication is being used if (params->externalAuth && (!commonParams || !commonParams->accessToken)) *used = 1; // set credentials if (userName && userNameLength > 0) { if (dpiOci__attrSet(handle, handleType, (void*) userName, userNameLength, DPI_OCI_ATTR_USERNAME, "set user name", error) < 0) return DPI_FAILURE; *used = 1; } if (password && passwordLength > 0) { if (dpiOci__attrSet(handle, handleType, (void*) password, passwordLength, DPI_OCI_ATTR_PASSWORD, "set password", error) < 0) return DPI_FAILURE; *used = 1; } // set connection class and purity parameters if (params->connectionClass && params->connectionClassLength > 0) { if (dpiOci__attrSet(handle, handleType, (void*) params->connectionClass, params->connectionClassLength, DPI_OCI_ATTR_CONNECTION_CLASS, "set connection class", error) < 0) return DPI_FAILURE; *used = 1; } if (params->purity != DPI_OCI_ATTR_PURITY_DEFAULT) { purity = params->purity; if (dpiOci__attrSet(handle, handleType, &purity, sizeof(purity), DPI_OCI_ATTR_PURITY, "set purity", error) < 0) return DPI_FAILURE; *used = 1; } // set sharding key and super sharding key parameters if (params->shardingKeyColumns && params->numShardingKeyColumns > 0) { if (dpiConn__setShardingKey(conn, &conn->shardingKey, handle, handleType, DPI_OCI_ATTR_SHARDING_KEY, "set sharding key", params->shardingKeyColumns, params->numShardingKeyColumns, error) < 0) return DPI_FAILURE; *used = 1; } if (params->superShardingKeyColumns && params->numSuperShardingKeyColumns > 0) { if (params->numShardingKeyColumns == 0) return dpiError__set(error, "ensure sharding key", DPI_ERR_MISSING_SHARDING_KEY); if (dpiConn__setShardingKey(conn, &conn->superShardingKey, handle, handleType, DPI_OCI_ATTR_SUPER_SHARDING_KEY, "set super sharding key", params->superShardingKeyColumns, params->numSuperShardingKeyColumns, error) < 0) return DPI_FAILURE; *used = 1; } // set application context, if applicable if (handleType == DPI_OCI_HTYPE_SESSION && params->numAppContext > 0) return dpiConn__setAppContext(handle, handleType, params, error); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__setAttributeText() [INTERNAL] // Set the value of the OCI attribute from a text string. //----------------------------------------------------------------------------- static int dpiConn__setAttributeText(dpiConn *conn, uint32_t attribute, const char *value, uint32_t valueLength, const char *fnName) { dpiError error; int status; // validate parameters if (dpiConn__check(conn, fnName, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, value) // determine pointer to pass (OCI uses different sizes) switch (attribute) { case DPI_OCI_ATTR_ACTION: case DPI_OCI_ATTR_CLIENT_IDENTIFIER: case DPI_OCI_ATTR_CLIENT_INFO: case DPI_OCI_ATTR_CURRENT_SCHEMA: case DPI_OCI_ATTR_ECONTEXT_ID: case DPI_OCI_ATTR_EDITION: case DPI_OCI_ATTR_MODULE: case DPI_OCI_ATTR_DBOP: status = dpiOci__attrSet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, (void*) value, valueLength, attribute, "set session value", &error); break; case DPI_OCI_ATTR_INTERNAL_NAME: case DPI_OCI_ATTR_EXTERNAL_NAME: status = dpiOci__attrSet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, (void*) value, valueLength, attribute, "set server value", &error); break; default: status = dpiError__set(&error, "set attribute text", DPI_ERR_NOT_SUPPORTED); break; } return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn__setShardingKey() [INTERNAL] // Using the specified columns, create a sharding key and set it on the given // handle. //----------------------------------------------------------------------------- static int dpiConn__setShardingKey(dpiConn *conn, void **shardingKey, void *handle, uint32_t handleType, uint32_t attribute, const char *action, dpiShardingKeyColumn *columns, uint8_t numColumns, dpiError *error) { uint8_t i; // this is only supported on 12.2 and higher clients if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 2, error) < 0) return DPI_FAILURE; // create sharding key descriptor, if necessary if (dpiOci__descriptorAlloc(conn->env->handle, shardingKey, DPI_OCI_DTYPE_SHARDING_KEY, "allocate sharding key", error) < 0) return DPI_FAILURE; // add each column to the sharding key for (i = 0; i < numColumns; i++) { if (dpiConn__setShardingKeyValue(conn, *shardingKey, &columns[i], error) < 0) return DPI_FAILURE; } // add the sharding key to the handle if (dpiOci__attrSet(handle, handleType, *shardingKey, 0, attribute, action, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__setShardingKeyValue() [INTERNAL] // Using the specified columns, create a sharding key and set it on the given // handle. //----------------------------------------------------------------------------- static int dpiConn__setShardingKeyValue(dpiConn *conn, void *shardingKey, dpiShardingKeyColumn *column, dpiError *error) { dpiShardingOciDate shardingDateValue; uint32_t colLen = 0, descType = 0; const dpiOracleType *oracleType; dpiOciNumber numberValue; int convertOk, status; dpiOciDate dateValue; void *col = NULL; uint16_t colType; oracleType = dpiOracleType__getFromNum(column->oracleTypeNum, error); if (!oracleType) return DPI_FAILURE; convertOk = 0; colType = oracleType->oracleType; switch (column->oracleTypeNum) { case DPI_ORACLE_TYPE_VARCHAR: case DPI_ORACLE_TYPE_CHAR: case DPI_ORACLE_TYPE_RAW: if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { col = column->value.asBytes.ptr; colLen = column->value.asBytes.length; convertOk = 1; } break; case DPI_ORACLE_TYPE_NUMBER: col = &numberValue; colLen = sizeof(numberValue); if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { if (dpiDataBuffer__toOracleNumberFromDouble(&column->value, error, &numberValue) < 0) return DPI_FAILURE; convertOk = 1; } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_INT64) { if (dpiDataBuffer__toOracleNumberFromInteger(&column->value, error, &numberValue) < 0) return DPI_FAILURE; convertOk = 1; } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_UINT64) { if (dpiDataBuffer__toOracleNumberFromUnsignedInteger( &column->value, error, &numberValue) < 0) return DPI_FAILURE; convertOk = 1; } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { if (dpiDataBuffer__toOracleNumberFromText(&column->value, conn->env, error, &numberValue) < 0) return DPI_FAILURE; convertOk = 1; } break; case DPI_ORACLE_TYPE_DATE: if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { if (dpiDataBuffer__toOracleDate(&column->value, &dateValue) < 0) return DPI_FAILURE; convertOk = 1; } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { if (dpiDataBuffer__toOracleDateFromDouble(&column->value, conn->env, error, &dateValue) < 0) return DPI_FAILURE; convertOk = 1; } // for sharding only, the type must be SQLT_DAT, which uses a // different format for storing the date values if (convertOk) { col = &shardingDateValue; colLen = sizeof(shardingDateValue); colType = DPI_SQLT_DAT; shardingDateValue.century = ((uint8_t) (dateValue.year / 100)) + 100; shardingDateValue.year = (dateValue.year % 100) + 100; shardingDateValue.month = dateValue.month; shardingDateValue.day = dateValue.day; shardingDateValue.hour = dateValue.hour + 1; shardingDateValue.minute = dateValue.minute + 1; shardingDateValue.second = dateValue.second + 1; } break; case DPI_ORACLE_TYPE_TIMESTAMP: case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: colLen = sizeof(void*); colType = DPI_SQLT_TIMESTAMP; if (column->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { descType = DPI_OCI_DTYPE_TIMESTAMP; if (dpiOci__descriptorAlloc(conn->env->handle, &col, descType, "alloc timestamp", error) < 0) return DPI_FAILURE; if (dpiDataBuffer__toOracleTimestamp(&column->value, conn->env, error, col, 0) < 0) { dpiOci__descriptorFree(col, descType); return DPI_FAILURE; } convertOk = 1; } else if (column->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { descType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; if (dpiOci__descriptorAlloc(conn->env->handle, &col, descType, "alloc LTZ timestamp", error) < 0) return DPI_FAILURE; if (dpiDataBuffer__toOracleTimestampFromDouble(&column->value, DPI_ORACLE_TYPE_TIMESTAMP_LTZ, conn->env, error, col) < 0) { dpiOci__descriptorFree(col, descType); return DPI_FAILURE; } convertOk = 1; } break; default: break; } if (!convertOk) return dpiError__set(error, "check type", DPI_ERR_NOT_SUPPORTED); status = dpiOci__shardingKeyColumnAdd(shardingKey, col, colLen, colType, error); if (descType) dpiOci__descriptorFree(col, descType); return status; } //----------------------------------------------------------------------------- // dpiConn__setXid() [INTERNAL] // Internal method for associating an XID with the connection. //----------------------------------------------------------------------------- static int dpiConn__setXid(dpiConn *conn, dpiXid *xid, dpiError *error) { void *transactionHandle; dpiOciXID ociXid; // validate XID if (xid->globalTransactionIdLength > 0 && !xid->globalTransactionId) return dpiError__set(error, "check XID transaction id ptr", DPI_ERR_PTR_LENGTH_MISMATCH, "xid->globalTransactionId"); if (xid->branchQualifierLength > 0 && !xid->branchQualifier) return dpiError__set(error, "check XID branch id ptr", DPI_ERR_PTR_LENGTH_MISMATCH, "xid->branchQualifier"); if (xid->globalTransactionIdLength > DPI_XA_MAXGTRIDSIZE) return dpiError__set(error, "check size of XID transaction id", DPI_ERR_TRANS_ID_TOO_LARGE, xid->globalTransactionIdLength, DPI_XA_MAXGTRIDSIZE); if (xid->branchQualifierLength > DPI_XA_MAXBQUALSIZE) return dpiError__set(error, "check size of XID branch qualifier", DPI_ERR_BRANCH_ID_TOO_LARGE, xid->branchQualifierLength, DPI_XA_MAXBQUALSIZE); // associate the XID with the transaction, unless a transaction not started // by us is in progress (which is determined by the returned transaction // handle being NULL) if (dpiUtils__getTransactionHandle(conn, &transactionHandle, error) < 0) return DPI_FAILURE; if (transactionHandle) { ociXid.formatID = xid->formatId; ociXid.gtrid_length = xid->globalTransactionIdLength; ociXid.bqual_length = xid->branchQualifierLength; if (xid->globalTransactionIdLength > 0) memcpy(ociXid.data, xid->globalTransactionId, xid->globalTransactionIdLength); if (xid->branchQualifierLength > 0) memcpy(&ociXid.data[xid->globalTransactionIdLength], xid->branchQualifier, xid->branchQualifierLength); if (dpiOci__attrSet(transactionHandle, DPI_OCI_HTYPE_TRANS, &ociXid, sizeof(dpiOciXID), DPI_OCI_ATTR_XID, "set XID", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__startSessionlessTransaction() [INTERNAL] // Internal function to begin/resume a sessionless transaction. //----------------------------------------------------------------------------- static int dpiConn__startSessionlessTransaction(dpiConn *conn, dpiSessionlessTransactionId *transactionId, uint32_t timeout, uint32_t flag, int deferRoundTrip, dpiError *error) { void *transactionHandle; dpiOciXID *ociXid; // perform checks if (dpiUtils__checkClientVersion(conn->env->versionInfo, 23, 6, error) < 0) return DPI_FAILURE; // set the transaction id on the transaction, unless a transaction not // started by us is in progress (which is determined by the returned // transaction handle being NULL) if (dpiUtils__getTransactionHandle(conn, &transactionHandle, error) < 0) return DPI_FAILURE; if (transactionHandle) { if (dpiOci__attrSet(transactionHandle, DPI_OCI_HTYPE_TRANS, transactionId->value, transactionId->length, DPI_OCI_ATTR_TRANS_NAME, "set transaction id", error) < 0) return DPI_FAILURE; } // start the transaction if (dpiOci__transStart(conn, timeout, DPI_OCI_TRANS_SESSIONLESS | flag, error) < 0) return DPI_FAILURE; // populate the value of transactionId if one was not supplied; OCI will // have generated a random value which will be returned for use by // subsequent calls if (transactionId->length == 0) { if (dpiOci__attrGet(transactionHandle, DPI_OCI_HTYPE_TRANS, &ociXid, NULL, DPI_OCI_ATTR_XID, "get transactionId", error) < 0) return DPI_FAILURE; memcpy(transactionId->value, ociXid->data, ociXid->gtrid_length); transactionId->length = (uint32_t) ociXid->gtrid_length; } // perform round trip, unless the round trip has been deferred if (!deferRoundTrip && dpiOci__ping(conn, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiConn__startupDatabase() [INTERNAL] // Internal method for starting up a database. This is equivalent to // "startup nomount" in SQL*Plus. //----------------------------------------------------------------------------- static int dpiConn__startupDatabase(dpiConn *conn, const char *pfile, uint32_t pfileLength, dpiStartupMode mode, dpiError *error) { void *adminHandle = NULL; int status; // if a PFILE has been specified, create an admin handle and populate it if (pfileLength > 0) { if (dpiOci__handleAlloc(conn->env->handle, &adminHandle, DPI_OCI_HTYPE_ADMIN, "create admin handle", error) < 0) return DPI_FAILURE; if (dpiOci__attrSet(adminHandle, DPI_OCI_HTYPE_ADMIN, (void*) pfile, pfileLength, DPI_OCI_ATTR_ADMIN_PFILE, "associate PFILE", error) < 0) { dpiOci__handleFree(adminHandle, DPI_OCI_HTYPE_ADMIN); return DPI_FAILURE; } } // perform actual startup call status = dpiOci__dbStartup(conn, adminHandle, mode, error); // destroy admin handle, if needed if (pfileLength > 0) dpiOci__handleFree(adminHandle, DPI_OCI_HTYPE_ADMIN); return status; } //----------------------------------------------------------------------------- // dpiConn__suspendSessionlessTransaction() [INTERNAL] // Suspend a sessionless transaction based on flag (default/postcall). //----------------------------------------------------------------------------- int dpiConn__suspendSessionlessTransaction(dpiConn *conn, uint32_t flag, dpiError *error) { void *transactionHandle; if (dpiUtils__checkClientVersion(conn->env->versionInfo, 23, 6, error) < 0) return DPI_FAILURE; // associate a transaction handle with the connection if one is not already // associated; this ensures that OCI throws the proper error (such as // ORA-26202) instead of a vague error like "invalid handle" if (dpiUtils__getTransactionHandle(conn, &transactionHandle, error)) return DPI_FAILURE; return dpiOci__transDetach(conn, DPI_OCI_TRANS_SESSIONLESS | flag, error); } //----------------------------------------------------------------------------- // dpiConn_addRef() [PUBLIC] // Add a reference to the connection. //----------------------------------------------------------------------------- int dpiConn_addRef(dpiConn *conn) { return dpiGen__addRef(conn, DPI_HTYPE_CONN, __func__); } //----------------------------------------------------------------------------- // dpiConn_beginSessionlessTransaction() [PUBLIC] // Begin a sessionless transaction. //----------------------------------------------------------------------------- int dpiConn_beginSessionlessTransaction(dpiConn *conn, dpiSessionlessTransactionId *transactionId, uint32_t timeout, int deferRoundTrip) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, transactionId); status = dpiConn__startSessionlessTransaction(conn, transactionId, timeout, DPI_TPC_BEGIN_NEW, deferRoundTrip, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_breakExecution() [PUBLIC] // Break (interrupt) the currently executing operation. //----------------------------------------------------------------------------- int dpiConn_breakExecution(dpiConn *conn) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__break(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_changePassword() [PUBLIC] // Change the password for the specified user. //----------------------------------------------------------------------------- int dpiConn_changePassword(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *oldPassword, uint32_t oldPasswordLength, const char *newPassword, uint32_t newPasswordLength) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, userName) DPI_CHECK_PTR_AND_LENGTH(conn, oldPassword) DPI_CHECK_PTR_AND_LENGTH(conn, newPassword) status = dpiOci__passwordChange(conn, userName, userNameLength, oldPassword, oldPasswordLength, newPassword, newPasswordLength, DPI_OCI_DEFAULT, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_close() [PUBLIC] // Close the connection and ensure it can no longer be used. //----------------------------------------------------------------------------- int dpiConn_close(dpiConn *conn, dpiConnCloseMode mode, const char *tag, uint32_t tagLength) { int propagateErrors = !(mode & DPI_MODE_CONN_CLOSE_DROP); dpiError error; int closing; // validate parameters if (dpiGen__startPublicFn(conn, DPI_HTYPE_CONN, __func__, &error) < 0) return DPI_FAILURE; if (!conn->handle || conn->closing || (conn->pool && !conn->pool->handle)) { dpiError__set(&error, "check connected", DPI_ERR_NOT_CONNECTED); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } DPI_CHECK_PTR_AND_LENGTH(conn, tag) if (mode && !conn->pool) { dpiError__set(&error, "check in pool", DPI_ERR_CONN_NOT_IN_POOL); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } if (conn->externalHandle) { dpiError__set(&error, "check external", DPI_ERR_CONN_IS_EXTERNAL); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } // determine whether connection is already being closed and if not, mark // connection as being closed; this MUST be done while holding the lock // (if in threaded mode) to avoid race conditions! if (conn->env->threaded) dpiMutex__acquire(conn->env->mutex); closing = conn->closing; conn->closing = 1; if (conn->env->threaded) dpiMutex__release(conn->env->mutex); // if connection is already being closed, raise an exception if (closing) { dpiError__set(&error, "check closing", DPI_ERR_NOT_CONNECTED); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } // if actual close fails, reset closing flag; again, this must be done // while holding the lock (if in threaded mode) in order to avoid race // conditions! if (dpiConn__close(conn, mode, tag, tagLength, propagateErrors, &error) < 0) { if (conn->env->threaded) dpiMutex__acquire(conn->env->mutex); conn->closing = 0; if (conn->env->threaded) dpiMutex__release(conn->env->mutex); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_commit() [PUBLIC] // Commit the transaction associated with the connection. //----------------------------------------------------------------------------- int dpiConn_commit(dpiConn *conn) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiConn__commit(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_create() [PUBLIC] // Create a standalone connection to the database using the parameters // specified. //----------------------------------------------------------------------------- int dpiConn_create(const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiConn **conn) { dpiCommonCreateParams localCommonParams; dpiConnCreateParams localCreateParams; dpiConn *tempConn; dpiError error; int status; // validate parameters if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, conn) DPI_CHECK_PTR_AND_LENGTH(context, userName) DPI_CHECK_PTR_AND_LENGTH(context, password) DPI_CHECK_PTR_AND_LENGTH(context, connectString) // use default parameters if none provided if (!commonParams) { dpiContext__initCommonCreateParams(context, &localCommonParams); commonParams = &localCommonParams; } if (!createParams) { dpiContext__initConnCreateParams(&localCreateParams); createParams = &localCreateParams; } // password must not be specified if external authentication is desired if (createParams->externalAuth && password && passwordLength > 0) { dpiError__set(&error, "verify no password with external auth", DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } // the username must be enclosed within [] if external authentication // with proxy is desired if (createParams->externalAuth && userName && userNameLength > 0 && (userName[0] != '[' || userName[userNameLength - 1] != ']')) { dpiError__set(&error, "verify proxy user name with external auth", DPI_ERR_EXT_AUTH_INVALID_PROXY); return dpiGen__endPublicFn(context, DPI_FAILURE, &error ); } if (commonParams->accessToken) { // externalAuth must be set to true for token based authentication if (!createParams->externalAuth) return dpiError__set(&error, "check externalAuth value", DPI_ERR_STANDALONE_TOKEN_BASED_AUTH); // cannot set username for token based authentication if (userName && userNameLength > 0) return dpiError__set(&error, "verify user in token based auth", DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); } // connectionClass and edition cannot be specified at the same time if (createParams->connectionClass && createParams->connectionClassLength > 0 && commonParams->edition && commonParams->editionLength > 0) { dpiError__set(&error, "check edition/conn class", DPI_ERR_NO_EDITION_WITH_CONN_CLASS); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } // newPassword and edition cannot be specified at the same time if (createParams->newPassword && createParams->newPasswordLength > 0 && commonParams->edition && commonParams->editionLength > 0) { dpiError__set(&error, "check edition/new password", DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } // handle case where pool is specified if (createParams->pool) { if (dpiGen__checkHandle(createParams->pool, DPI_HTYPE_POOL, "verify pool", &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); if (!createParams->pool->handle) { dpiError__set(&error, "check pool", DPI_ERR_NOT_CONNECTED); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } status = dpiPool__acquireConnection(createParams->pool, userName, userNameLength, password, passwordLength, createParams, conn, &error); return dpiGen__endPublicFn(context, status, &error); } // create connection if (dpiGen__allocate(DPI_HTYPE_CONN, NULL, (void**) &tempConn, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); if (dpiConn__create(tempConn, context, userName, userNameLength, password, passwordLength, connectString, connectStringLength, NULL, commonParams, createParams, &error) < 0) { dpiConn__free(tempConn, &error); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } *conn = tempConn; dpiHandlePool__release(tempConn->env->errorHandles, &error.handle); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_deqObject() [PUBLIC] // Dequeue a message from the specified queue. //----------------------------------------------------------------------------- int dpiConn_deqObject(dpiConn *conn, const char *queueName, uint32_t queueNameLength, dpiDeqOptions *options, dpiMsgProps *props, dpiObject *payload, const char **msgId, uint32_t *msgIdLength) { dpiError error; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(options, DPI_HTYPE_DEQ_OPTIONS, "verify options", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, "verify message properties", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, queueName) DPI_CHECK_PTR_NOT_NULL(conn, msgId) DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength) // dequeue message if (dpiOci__aqDeq(conn, queueName, options->handle, props->handle, payload->type->tdo, &payload->instance, &payload->indicator, &props->msgIdRaw, &error) < 0) { if (error.buffer->code == 25228) { *msgId = NULL; *msgIdLength = 0; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } dpiMsgProps__extractMsgId(props, msgId, msgIdLength); return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_enqObject() [PUBLIC] // Enqueue a message to the specified queue. //----------------------------------------------------------------------------- int dpiConn_enqObject(dpiConn *conn, const char *queueName, uint32_t queueNameLength, dpiEnqOptions *options, dpiMsgProps *props, dpiObject *payload, const char **msgId, uint32_t *msgIdLength) { dpiError error; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(options, DPI_HTYPE_ENQ_OPTIONS, "verify options", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, "verify message properties", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(payload, DPI_HTYPE_OBJECT, "verify payload", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, queueName) DPI_CHECK_PTR_NOT_NULL(conn, msgId) DPI_CHECK_PTR_NOT_NULL(conn, msgIdLength) // enqueue message if (dpiOci__aqEnq(conn, queueName, options->handle, props->handle, payload->type->tdo, &payload->instance, &payload->indicator, &props->msgIdRaw, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); dpiMsgProps__extractMsgId(props, msgId, msgIdLength); return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_getCallTimeout() [PUBLIC] // Return the call timeout (in milliseconds) used for round-trips to the // database. This is only valid in Oracle Client 18c and higher. //----------------------------------------------------------------------------- int dpiConn_getCallTimeout(dpiConn *conn, uint32_t *value) { dpiError error; int status; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, value) if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); // get call timeout status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, (void*) value, 0, DPI_OCI_ATTR_CALL_TIMEOUT, "get call timeout", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getCurrentSchema() [PUBLIC] // Return the current schema associated with the connection. //----------------------------------------------------------------------------- int dpiConn_getCurrentSchema(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getDbDomain() [PUBLIC] // Returns the name of the database domain. //----------------------------------------------------------------------------- int dpiConn_getDbDomain(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_DBDOMAIN, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getDbName() [PUBLIC] // Returns the name of the database. //----------------------------------------------------------------------------- int dpiConn_getDbName(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_DBNAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getEdition() [PUBLIC] // Return the edition associated with the connection. //----------------------------------------------------------------------------- int dpiConn_getEdition(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EDITION, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getEncodingInfo() [PUBLIC] // Get the encodings from the connection. //----------------------------------------------------------------------------- int dpiConn_getEncodingInfo(dpiConn *conn, dpiEncodingInfo *info) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiEnv__getEncodingInfo(conn->env, info); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getExternalName() [PUBLIC] // Return the external name associated with the connection. //----------------------------------------------------------------------------- int dpiConn_getExternalName(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getHandle() [PUBLIC] // Get the OCI service context handle associated with the connection. This is // available in order to allow for extensions to the library using OCI // directly. //----------------------------------------------------------------------------- int dpiConn_getHandle(dpiConn *conn, void **handle) { dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, handle) *handle = conn->handle; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_getInfo() [PUBLIC] // Return information about the connection in the provided structure. //----------------------------------------------------------------------------- int dpiConn_getInfo(dpiConn *conn, dpiConnInfo *info) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, info) status = dpiConn__getInfo(conn, &error); if (status == DPI_SUCCESS) memcpy(info, conn->info, sizeof(dpiConnInfo)); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getInstanceName() [PUBLIC] // Return the instance name associated with the connection. //----------------------------------------------------------------------------- int dpiConn_getInstanceName(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_INSTNAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getInternalName() [PUBLIC] // Return the internal name associated with the connection. //----------------------------------------------------------------------------- int dpiConn_getInternalName(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getIsHealthy() [PUBLIC] // Return the health of the connection. //----------------------------------------------------------------------------- int dpiConn_getIsHealthy(dpiConn *conn, int *isHealthy) { dpiError error; int status; uint32_t serverStatus; if (dpiGen__startPublicFn(conn, DPI_HTYPE_CONN, __func__, &error) < 0) return DPI_FAILURE; if (!conn->handle || !conn->serverHandle || conn->closing || conn->deadSession || (conn->pool && !conn->pool->handle)) { *isHealthy = 0; status = DPI_SUCCESS; } else { DPI_CHECK_PTR_NOT_NULL(conn, isHealthy) status = dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &serverStatus, NULL, DPI_OCI_ATTR_SERVER_STATUS, "get server status", &error); *isHealthy = (serverStatus == DPI_OCI_SERVER_NORMAL); } return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getLTXID() [PUBLIC] // Return the logical transaction id associated with the connection. //----------------------------------------------------------------------------- int dpiConn_getLTXID(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_LTXID, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getMaxOpenCursors() [PUBLIC] // Returns the maximum number of cursors that can be opened by the database. // This is the value of the "open_cursors" parameter in init.ora. //----------------------------------------------------------------------------- int dpiConn_getMaxOpenCursors(dpiConn *conn, uint32_t *maxOpenCursors) { dpiError error; int status; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, maxOpenCursors) if (dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 1, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, maxOpenCursors, NULL, DPI_OCI_ATTR_MAX_OPEN_CURSORS, "get max open cursors", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getObjectType() [PUBLIC] // Look up an object type given its name and return it. //----------------------------------------------------------------------------- int dpiConn_getObjectType(dpiConn *conn, const char *name, uint32_t nameLength, dpiObjectType **objType) { void *describeHandle, *param, *tdo; int status, useTypeByFullName; dpiError error; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, name) DPI_CHECK_PTR_NOT_NULL(conn, objType) // allocate describe handle if (dpiOci__handleAlloc(conn->env->handle, &describeHandle, DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); // Oracle Client 12.1 is capable of using OCITypeByFullName() but will // fail if accessing an Oracle 11.2 database useTypeByFullName = 1; if (conn->env->versionInfo->versionNum < 12) useTypeByFullName = 0; else if (dpiConn__getServerVersion(conn, 0, &error) < 0) return DPI_FAILURE; else if (conn->versionInfo.versionNum < 12) useTypeByFullName = 0; // new API is supported so use it if (useTypeByFullName) { if (dpiOci__typeByFullName(conn, name, nameLength, &tdo, &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } if (dpiOci__describeAny(conn, tdo, 0, DPI_OCI_OTYPE_PTR, describeHandle, &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } // use older API } else { if (dpiOci__describeAny(conn, (void*) name, nameLength, DPI_OCI_OTYPE_NAME, describeHandle, &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } } // get the parameter handle if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, DPI_OCI_ATTR_PARAM, "get param", &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } // create object type status = dpiObjectType__allocate(conn, param, DPI_OCI_HTYPE_DESCRIBE, objType, &error); dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getOciAttr() [PUBLIC] // Get the OCI attribute directly. This is intended for testing of attributes // not currently exposed by ODPI-C and should only be used for that purpose. //----------------------------------------------------------------------------- int dpiConn_getOciAttr(dpiConn *conn, uint32_t handleType, uint32_t attribute, dpiDataBuffer *value, uint32_t *valueLength) { const void *handle; dpiError error; int status; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, value) DPI_CHECK_PTR_NOT_NULL(conn, valueLength) switch (handleType) { case DPI_OCI_HTYPE_SVCCTX: handle = conn->handle; break; case DPI_OCI_HTYPE_SERVER: handle = conn->serverHandle; break; case DPI_OCI_HTYPE_SESSION: handle = conn->sessionHandle; break; default: dpiError__set(&error, "check handle type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } // get attribute value status = dpiOci__attrGet(handle, handleType, &value->asRaw, valueLength, attribute, "generic get OCI attribute", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getServerVersion() [PUBLIC] // Get the server version string from the database. //----------------------------------------------------------------------------- int dpiConn_getServerVersion(dpiConn *conn, const char **releaseString, uint32_t *releaseStringLength, dpiVersionInfo *versionInfo) { dpiError error; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, versionInfo) // get server version if (dpiConn__getServerVersion(conn, (releaseString != NULL), &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (releaseString) *releaseString = conn->releaseString; if (releaseStringLength) *releaseStringLength = conn->releaseStringLength; memcpy(versionInfo, &conn->versionInfo, sizeof(dpiVersionInfo)); return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_getServiceName() [PUBLIC] // Returns the name of the service used to connect to the database. //----------------------------------------------------------------------------- int dpiConn_getServiceName(dpiConn *conn, const char **value, uint32_t *valueLength) { return dpiConn__getAttributeText(conn, DPI_OCI_ATTR_SERVICENAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_getSodaDb() [PUBLIC] // Create a new SODA collection with the given name and metadata. //----------------------------------------------------------------------------- int dpiConn_getSodaDb(dpiConn *conn, dpiSodaDb **db) { dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 3, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiUtils__checkDatabaseVersion(conn, 18, 0, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__allocate(DPI_HTYPE_SODA_DB, conn->env, (void**) db, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); dpiGen__setRefCount(conn, &error, 1); (*db)->conn = conn; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_getStmtCacheSize() [PUBLIC] // Return the current size of the statement cache. //----------------------------------------------------------------------------- int dpiConn_getStmtCacheSize(dpiConn *conn, uint32_t *cacheSize) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, cacheSize) status = dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, cacheSize, NULL, DPI_OCI_ATTR_STMTCACHESIZE, "get stmt cache size", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_getTransactionInProgress() [PUBLIC] // Returns whether or not a transaction is in progress. This can be used to // determine if a COMMIT is required or not. //----------------------------------------------------------------------------_ int dpiConn_getTransactionInProgress(dpiConn *conn, int *value) { dpiError error; uint32_t temp; int status; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, value); status = dpiOci__attrGet(conn->sessionHandle, DPI_OCI_HTYPE_SESSION, &temp, NULL, DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS, "get Transaction in progress", &error); *value = (temp == 0) ? 0: 1; return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_newDeqOptions() [PUBLIC] // Create a new dequeue options object and return it. //----------------------------------------------------------------------------- int dpiConn_newDeqOptions(dpiConn *conn, dpiDeqOptions **options) { dpiDeqOptions *tempOptions; dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, options) if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, conn->env, (void**) &tempOptions, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiDeqOptions__create(tempOptions, conn, &error) < 0) { dpiDeqOptions__free(tempOptions, &error); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } *options = tempOptions; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_newEnqOptions() [PUBLIC] // Create a new enqueue options object and return it. //----------------------------------------------------------------------------- int dpiConn_newEnqOptions(dpiConn *conn, dpiEnqOptions **options) { dpiEnqOptions *tempOptions; dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, options) if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, conn->env, (void**) &tempOptions, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiEnqOptions__create(tempOptions, conn, &error) < 0) { dpiEnqOptions__free(tempOptions, &error); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } *options = tempOptions; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_newJson() [PUBLIC] // Create a new JSON object and return it. //----------------------------------------------------------------------------- int dpiConn_newJson(dpiConn *conn, dpiJson **json) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, json); status = dpiJson__allocate(conn, NULL, json, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_newJsonQueue() [PUBLIC] // Create a new AQ queue object with JSON payload and return it. //----------------------------------------------------------------------------- int dpiConn_newJsonQueue(dpiConn *conn, const char *name, uint32_t nameLength, dpiQueue **queue) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, name) DPI_CHECK_PTR_NOT_NULL(conn, queue) status = dpiQueue__allocate(conn, name, nameLength, NULL, queue, 1, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_newMsgProps() [PUBLIC] // Create a new message properties object and return it. //----------------------------------------------------------------------------- int dpiConn_newMsgProps(dpiConn *conn, dpiMsgProps **props) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, props) status = dpiMsgProps__allocate(conn, props, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_newQueue() [PUBLIC] // Create a new AQ queue object and return it. //----------------------------------------------------------------------------- int dpiConn_newQueue(dpiConn *conn, const char *name, uint32_t nameLength, dpiObjectType *payloadType, dpiQueue **queue) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, name) DPI_CHECK_PTR_NOT_NULL(conn, queue) status = dpiQueue__allocate(conn, name, nameLength, payloadType, queue, 0, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_newTempLob() [PUBLIC] // Create a new temporary LOB and return it. //----------------------------------------------------------------------------- int dpiConn_newTempLob(dpiConn *conn, dpiOracleTypeNum lobType, dpiLob **lob) { const dpiOracleType *type; dpiLob *tempLob; dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, lob) switch (lobType) { case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_NCLOB: type = dpiOracleType__getFromNum(lobType, &error); break; default: dpiError__set(&error, "check lob type", DPI_ERR_INVALID_ORACLE_TYPE, lobType); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } if (dpiLob__allocate(conn, type, &tempLob, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiOci__lobCreateTemporary(tempLob, &error) < 0) { dpiLob__free(tempLob, &error); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } *lob = tempLob; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_newVar() [PUBLIC] // Create a new variable and return it. //----------------------------------------------------------------------------- int dpiConn_newVar(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, dpiData **data) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, var) DPI_CHECK_PTR_NOT_NULL(conn, data) status = dpiVar__allocate(conn, oracleTypeNum, nativeTypeNum, maxArraySize, size, sizeIsBytes, isArray, objType, var, data, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_newVector() [PUBLIC] // Create a new variable and return it. //----------------------------------------------------------------------------- int dpiConn_newVector(dpiConn *conn, dpiVectorInfo *info, dpiVector **vector) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, vector) status = dpiConn__newVector(conn, info, vector, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_ping() [PUBLIC] // Makes a round trip call to the server to confirm that the connection and // server are still active. //----------------------------------------------------------------------------- int dpiConn_ping(dpiConn *conn) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__ping(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_prepareStmt() [PUBLIC] // Create a new statement and return it after preparing the specified SQL. //----------------------------------------------------------------------------- int dpiConn_prepareStmt(dpiConn *conn, int scrollable, const char *sql, uint32_t sqlLength, const char *tag, uint32_t tagLength, dpiStmt **stmt) { dpiStmt *tempStmt; dpiError error; *stmt = NULL; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, sql) DPI_CHECK_PTR_AND_LENGTH(conn, tag) DPI_CHECK_PTR_NOT_NULL(conn, stmt) if (dpiStmt__allocate(conn, scrollable, &tempStmt, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiStmt__prepare(tempStmt, sql, sqlLength, tag, tagLength, &error) < 0) { dpiStmt__free(tempStmt, &error); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } *stmt = tempStmt; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_release() [PUBLIC] // Release a reference to the connection. //----------------------------------------------------------------------------- int dpiConn_release(dpiConn *conn) { return dpiGen__release(conn, DPI_HTYPE_CONN, __func__); } //----------------------------------------------------------------------------- // dpiConn_rollback() [PUBLIC] // Rollback the transaction associated with the connection. //----------------------------------------------------------------------------- int dpiConn_rollback(dpiConn *conn) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiConn__rollback(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_setAction() [PUBLIC] // Set the action associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setAction(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_ACTION, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setCallTimeout() [PUBLIC] // Set the call timeout (in milliseconds) used for round-trips to the // database. This is only valid in Oracle Client 18c and higher. //----------------------------------------------------------------------------- int dpiConn_setCallTimeout(dpiConn *conn, uint32_t value) { dpiError error; int status; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiUtils__checkClientVersion(conn->env->versionInfo, 18, 1, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); // set call timeout status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &value, 0, DPI_OCI_ATTR_CALL_TIMEOUT, "set call timeout", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_setClientIdentifier() [PUBLIC] // Set the client identifier associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setClientIdentifier(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_IDENTIFIER, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setClientInfo() [PUBLIC] // Set the client info associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setClientInfo(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CLIENT_INFO, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setCurrentSchema() [PUBLIC] // Set the current schema associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setCurrentSchema(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_CURRENT_SCHEMA, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setDbOp() [PUBLIC] // Set the database operation associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setDbOp(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_DBOP, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setEcontextId() [PUBLIC] // Set the execute context id associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setEcontextId(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_ECONTEXT_ID, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setExternalName() [PUBLIC] // Set the external name associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setExternalName(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_EXTERNAL_NAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setInternalName() [PUBLIC] // Set the internal name associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setInternalName(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_INTERNAL_NAME, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setModule() [PUBLIC] // Set the module associated with the connection. //----------------------------------------------------------------------------- int dpiConn_setModule(dpiConn *conn, const char *value, uint32_t valueLength) { return dpiConn__setAttributeText(conn, DPI_OCI_ATTR_MODULE, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiConn_setOciAttr() [PUBLIC] // Set the OCI attribute directly. This is intended for testing of attributes // not currently exposed by ODPI-C and should only be used for that purpose. //----------------------------------------------------------------------------- int dpiConn_setOciAttr(dpiConn *conn, uint32_t handleType, uint32_t attribute, void *value, uint32_t valueLength) { dpiError error; void *handle; int status; // validate parameters if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, value) switch (handleType) { case DPI_OCI_HTYPE_SVCCTX: handle = conn->handle; break; case DPI_OCI_HTYPE_SERVER: handle = conn->serverHandle; break; case DPI_OCI_HTYPE_SESSION: handle = conn->sessionHandle; break; default: dpiError__set(&error, "check handle type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } // set attribute value status = dpiOci__attrSet(handle, handleType, value, valueLength, attribute, "generic set OCI attribute", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_setStmtCacheSize() [PUBLIC] // Set the size of the statement cache. //----------------------------------------------------------------------------- int dpiConn_setStmtCacheSize(dpiConn *conn, uint32_t cacheSize) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, &cacheSize, 0, DPI_OCI_ATTR_STMTCACHESIZE, "set stmt cache size", &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_resumeSessionlessTransaction() [PUBLIC] // Resume a sessionless transaction //----------------------------------------------------------------------------- int dpiConn_resumeSessionlessTransaction(dpiConn *conn, dpiSessionlessTransactionId *transactionId, uint32_t timeout, int deferRoundTrip) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, transactionId); status = dpiConn__startSessionlessTransaction(conn, transactionId, timeout, DPI_TPC_BEGIN_RESUME, deferRoundTrip, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_shutdownDatabase() [PUBLIC] // Shutdown the database. Note that this must be done in two phases except in // the situation where the instance is being aborted. //----------------------------------------------------------------------------- int dpiConn_shutdownDatabase(dpiConn *conn, dpiShutdownMode mode) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__dbShutdown(conn, mode, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_startupDatabase() [PUBLIC] // Startup the database. This is equivalent to "startup nomount" in SQL*Plus. //----------------------------------------------------------------------------- int dpiConn_startupDatabase(dpiConn *conn, dpiStartupMode mode) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiConn__startupDatabase(conn, NULL, 0, mode, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_startupDatabaseWithPfile() [PUBLIC] // Startup the database with a parameter file (PFILE). This is equivalent to // "startup nomount pfile=" in SQL*Plus. //----------------------------------------------------------------------------- int dpiConn_startupDatabaseWithPfile(dpiConn *conn, const char *pfile, uint32_t pfileLength, dpiStartupMode mode) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(conn, pfile) status = dpiConn__startupDatabase(conn, pfile, pfileLength, mode, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_subscribe() [PUBLIC] // Subscribe to events in the database. A subscription is created and // returned. This replaces dpiConn_newSubscription(). //----------------------------------------------------------------------------- int dpiConn_subscribe(dpiConn *conn, dpiSubscrCreateParams *params, dpiSubscr **subscr) { dpiSubscr *tempSubscr; dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, params) DPI_CHECK_PTR_NOT_NULL(conn, subscr) if (!conn->env->events) { dpiError__set(&error, "subscribe", DPI_ERR_EVENTS_MODE_REQUIRED); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } if (dpiGen__allocate(DPI_HTYPE_SUBSCR, conn->env, (void**) &tempSubscr, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiSubscr__create(tempSubscr, conn, params, &error) < 0) { dpiSubscr__free(tempSubscr, &error); return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } *subscr = tempSubscr; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_suspendSessionlessTransaction() [PUBLIC] // Suspend a sessionless transaction //----------------------------------------------------------------------------- int dpiConn_suspendSessionlessTransaction(dpiConn *conn) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiConn__suspendSessionlessTransaction(conn, DPI_OCI_SUSPEND_DEFAULT, &error); if (status == DPI_SUCCESS) status = dpiConn__clearTransaction(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_tpcBegin() [PUBLIC] // Begin a TPC (two-phase commit) transaction. //----------------------------------------------------------------------------- int dpiConn_tpcBegin(dpiConn *conn, dpiXid *xid, uint32_t transactionTimeout, uint32_t flags) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, xid) if (dpiConn__setXid(conn, xid, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__transStart(conn, transactionTimeout, flags, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_tpcCommit() [PUBLIC] // Commit a TPC (two-phase commit) transaction. This method is equivalent to // calling dpiConn_commit() if no XID is specified. //----------------------------------------------------------------------------- int dpiConn_tpcCommit(dpiConn *conn, dpiXid *xid, int onePhase) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (xid) { if (dpiConn__setXid(conn, xid, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); conn->commitMode = (onePhase) ? DPI_OCI_DEFAULT : DPI_OCI_TRANS_TWOPHASE; } status = dpiConn__commit(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_tpcEnd() [PUBLIC] // End (detach from) a TPC (two-phase commit) transaction. //----------------------------------------------------------------------------- int dpiConn_tpcEnd(dpiConn *conn, dpiXid *xid, uint32_t flags) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (xid) { if (dpiConn__setXid(conn, xid, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } status = dpiOci__transDetach(conn, flags, &error); if (status == DPI_SUCCESS) status = dpiConn__clearTransaction(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_tpcForget() [PUBLIC] // Forget a TPC (two-phase commit) transaction. //----------------------------------------------------------------------------- int dpiConn_tpcForget(dpiConn *conn, dpiXid *xid) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, xid) if (dpiConn__setXid(conn, xid, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); status = dpiOci__transForget(conn, &error); if (status == DPI_SUCCESS) status = dpiConn__clearTransaction(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_tpcPrepare() [PUBLIC] // Prepare a TPC (two-phase commit) transaction for commit. A boolean is // returned indicating if a commit is actually needed as an attempt to perform // a commit when nothing is actually prepared results in ORA-24756 (transaction // does not exist). This is determined by the return value from // OCITransPrepare() which is OCI_SUCCESS_WITH_INFO if there is no transaction // requiring commit. //----------------------------------------------------------------------------- int dpiConn_tpcPrepare(dpiConn *conn, dpiXid *xid, int *commitNeeded) { dpiError error; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(conn, commitNeeded) if (xid) { if (dpiConn__setXid(conn, xid, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } if (dpiOci__transPrepare(conn, commitNeeded, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (*commitNeeded) conn->commitMode = DPI_OCI_TRANS_TWOPHASE; return dpiGen__endPublicFn(conn, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiConn_tpcRollback() [PUBLIC] // Rollback a TPC (two-phase commit) transaction. This method is equivalent // to calling dpiConn_rollback() if no XID is specified. //----------------------------------------------------------------------------- int dpiConn_tpcRollback(dpiConn *conn, dpiXid *xid) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (xid) { if (dpiConn__setXid(conn, xid, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); } status = dpiConn__rollback(conn, &error); return dpiGen__endPublicFn(conn, status, &error); } //----------------------------------------------------------------------------- // dpiConn_unsubscribe() [PUBLIC] // Unsubscribe from events in the database. Once this call completes // successfully no further notifications will be sent. //----------------------------------------------------------------------------- int dpiConn_unsubscribe(dpiConn *conn, dpiSubscr *subscr) { dpiError error; int status; if (dpiConn__check(conn, __func__, &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (dpiGen__checkHandle(subscr, DPI_HTYPE_SUBSCR, "check subscription", &error) < 0) return dpiGen__endPublicFn(conn, DPI_FAILURE, &error); if (subscr->registered) { dpiMutex__acquire(subscr->mutex); status = dpiOci__subscriptionUnRegister(conn, subscr, &error); if (status == DPI_SUCCESS) subscr->registered = 0; dpiMutex__release(subscr->mutex); if (status < 0) return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); } dpiGen__setRefCount(subscr, &error, -1); return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); } odpi-5.6.4/src/dpiContext.c000066400000000000000000000412301510466437300155460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiContext.c // Implementation of context. Each context uses a specific version of the // ODPI-C library, which is checked for compatibility before allowing its use. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static void dpiContext__free(dpiContext *context); //----------------------------------------------------------------------------- // dpiContext__create() [INTERNAL] // Helper function for dpiContext__create(). //----------------------------------------------------------------------------- static int dpiContext__create(const char *fnName, unsigned int majorVersion, unsigned int minorVersion, dpiContextCreateParams *params, dpiContext **context, dpiError *error) { dpiVersionInfo *versionInfo; dpiContext *tempContext; // ensure global infrastructure is initialized if (dpiGlobal__ensureInitialized(fnName, params, &versionInfo, error) < 0) return DPI_FAILURE; // validate context handle if (!context) return dpiError__set(error, "check context handle", DPI_ERR_NULL_POINTER_PARAMETER, "context"); // verify that the supplied version is supported by the library if (majorVersion != DPI_MAJOR_VERSION || minorVersion > DPI_MINOR_VERSION) return dpiError__set(error, "check version", DPI_ERR_VERSION_NOT_SUPPORTED, majorVersion, majorVersion, minorVersion, DPI_MAJOR_VERSION, DPI_MINOR_VERSION); // allocate context and initialize it if (dpiGen__allocate(DPI_HTYPE_CONTEXT, NULL, (void**) &tempContext, error) < 0) return DPI_FAILURE; tempContext->dpiMinorVersion = (uint8_t) minorVersion; tempContext->versionInfo = versionInfo; // using a SODA JSON descriptor is only allowed with 23.4 and higher so // only set the flag if that version is being used; otherwise, ignore the // flag completely if (versionInfo->versionNum > 23 || (versionInfo->versionNum == 23 && versionInfo->releaseNum >= 4)) { tempContext->sodaUseJsonDesc = params->sodaUseJsonDesc; tempContext->useJsonId = params->useJsonId; } else { params->sodaUseJsonDesc = 0; } // store default encoding, if applicable if (params->defaultEncoding) { if (dpiUtils__allocateMemory(1, strlen(params->defaultEncoding) + 1, 0, "allocate default encoding", (void**) &tempContext->defaultEncoding, error) < 0) { dpiContext__free(tempContext); return DPI_FAILURE; } strcpy(tempContext->defaultEncoding, params->defaultEncoding); } // store default driver name, if applicable if (params->defaultDriverName) { if (dpiUtils__allocateMemory(1, strlen(params->defaultDriverName) + 1, 0, "allocate default driver name", (void**) &tempContext->defaultDriverName, error) < 0) { dpiContext__free(tempContext); return DPI_FAILURE; } strcpy(tempContext->defaultDriverName, params->defaultDriverName); } *context = tempContext; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiContext__free() [INTERNAL] // Free the memory and any resources associated with the context. //----------------------------------------------------------------------------- static void dpiContext__free(dpiContext *context) { if (context->defaultDriverName) { dpiUtils__freeMemory((void*) context->defaultDriverName); context->defaultDriverName = NULL; } if (context->defaultEncoding) { dpiUtils__freeMemory((void*) context->defaultEncoding); context->defaultEncoding = NULL; } dpiUtils__freeMemory(context); } //----------------------------------------------------------------------------- // dpiContext__initCommonCreateParams() [INTERNAL] // Initialize the common connection/pool creation parameters to default // values. //----------------------------------------------------------------------------- void dpiContext__initCommonCreateParams(const dpiContext *context, dpiCommonCreateParams *params) { memset(params, 0, sizeof(dpiCommonCreateParams)); if (context->defaultEncoding) { params->encoding = context->defaultEncoding; params->nencoding = context->defaultEncoding; } else { params->encoding = DPI_CHARSET_NAME_UTF8; params->nencoding = DPI_CHARSET_NAME_UTF8; } if (context->defaultDriverName) { params->driverName = context->defaultDriverName; params->driverNameLength = (uint32_t) strlen(context->defaultDriverName); } else { params->driverName = DPI_DEFAULT_DRIVER_NAME; params->driverNameLength = (uint32_t) strlen(params->driverName); } params->stmtCacheSize = DPI_DEFAULT_STMT_CACHE_SIZE; } //----------------------------------------------------------------------------- // dpiContext__initConnCreateParams() [INTERNAL] // Initialize the connection creation parameters to default values. Return // the structure size as a convenience for calling functions which may have to // differentiate between different ODPI-C application versions. //----------------------------------------------------------------------------- void dpiContext__initConnCreateParams(dpiConnCreateParams *params) { memset(params, 0, sizeof(dpiConnCreateParams)); } //----------------------------------------------------------------------------- // dpiContext__initPoolCreateParams() [INTERNAL] // Initialize the pool creation parameters to default values. //----------------------------------------------------------------------------- void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params) { memset(params, 0, sizeof(dpiPoolCreateParams)); params->minSessions = 1; params->maxSessions = 1; params->sessionIncrement = 0; params->homogeneous = 1; params->getMode = DPI_MODE_POOL_GET_NOWAIT; params->pingInterval = DPI_DEFAULT_PING_INTERVAL; params->pingTimeout = DPI_DEFAULT_PING_TIMEOUT; } //----------------------------------------------------------------------------- // dpiContext__initSodaOperOptions() [INTERNAL] // Initialize the SODA operation options to default values. //----------------------------------------------------------------------------- void dpiContext__initSodaOperOptions(dpiSodaOperOptions *options) { memset(options, 0, sizeof(dpiSodaOperOptions)); } //----------------------------------------------------------------------------- // dpiContext__initSubscrCreateParams() [INTERNAL] // Initialize the subscription creation parameters to default values. //----------------------------------------------------------------------------- void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params) { memset(params, 0, sizeof(dpiSubscrCreateParams)); params->subscrNamespace = DPI_SUBSCR_NAMESPACE_DBCHANGE; params->groupingType = DPI_SUBSCR_GROUPING_TYPE_SUMMARY; } //----------------------------------------------------------------------------- // dpiContext_createWithParams() [PUBLIC] // Create a new context for interaction with the library. The major versions // must match and the minor version of the caller must be less than or equal to // the minor version compiled into the library. The supplied parameters can be // used to modify how the Oracle client library is loaded. //----------------------------------------------------------------------------- int dpiContext_createWithParams(unsigned int majorVersion, unsigned int minorVersion, dpiContextCreateParams *params, dpiContext **context, dpiErrorInfo *errorInfo) { int status, update_use_soda_json_desc = 0; dpiContextCreateParams localParams; dpiErrorInfo localErrorInfo; dpiError error; // make a copy of the parameters so that the addition of defaults doesn't // modify the original parameters that were passed; then add defaults, if // needed if (params) { if (majorVersion < 5 || (majorVersion == 5 && minorVersion < 2)) { memcpy(&localParams, params, sizeof(dpiContextCreateParams__v51)); } else { memcpy(&localParams, params, sizeof(localParams)); update_use_soda_json_desc = 1; } } else { memset(&localParams, 0, sizeof(localParams)); } if (!localParams.loadErrorUrl) localParams.loadErrorUrl = DPI_DEFAULT_LOAD_ERROR_URL; status = dpiContext__create(__func__, majorVersion, minorVersion, &localParams, context, &error); if (status < 0) { dpiError__getInfo(&error, &localErrorInfo); memcpy(errorInfo, &localErrorInfo, sizeof(dpiErrorInfo__v33)); } if (update_use_soda_json_desc) params->sodaUseJsonDesc = localParams.sodaUseJsonDesc; if (params && !params->oracleClientConfigDir && localParams.oracleClientConfigDir) params->oracleClientConfigDir = localParams.oracleClientConfigDir; if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) dpiDebug__print("fn end %s -> %d\n", __func__, status); return status; } //----------------------------------------------------------------------------- // dpiContext_destroy() [PUBLIC] // Destroy an existing context. The structure will be checked for validity // first. //----------------------------------------------------------------------------- int dpiContext_destroy(dpiContext *context) { char message[80]; dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); dpiUtils__clearMemory(&context->checkInt, sizeof(context->checkInt)); if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) dpiDebug__print("ref %p (%s) -> 0\n", context, context->typeDef->name); if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) (void) sprintf(message, "fn end %s(%p) -> %d", __func__, context, DPI_SUCCESS); dpiContext__free(context); if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) dpiDebug__print("%s\n", message); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiContext_freeStringList() [PUBLIC] // Frees the contents of a string list. //----------------------------------------------------------------------------- int dpiContext_freeStringList(dpiContext *context, dpiStringList *list) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, list) dpiStringList__free(list); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiContext_getClientVersion() [PUBLIC] // Return the version of the Oracle client that is in use. //----------------------------------------------------------------------------- int dpiContext_getClientVersion(const dpiContext *context, dpiVersionInfo *versionInfo) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, versionInfo) memcpy(versionInfo, context->versionInfo, sizeof(dpiVersionInfo)); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiContext_getError() [PUBLIC] // Return information about the error that was last populated. //----------------------------------------------------------------------------- void dpiContext_getError(const dpiContext *context, dpiErrorInfo *info) { dpiError error; dpiGlobal__initError(NULL, &error); dpiGen__checkHandle(context, DPI_HTYPE_CONTEXT, "check handle", &error); dpiError__getInfo(&error, info); } //----------------------------------------------------------------------------- // dpiContext_initCommonCreateParams() [PUBLIC] // Initialize the common connection/pool creation parameters to default // values. //----------------------------------------------------------------------------- int dpiContext_initCommonCreateParams(const dpiContext *context, dpiCommonCreateParams *params) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, params) dpiContext__initCommonCreateParams(context, params); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiContext_initConnCreateParams() [PUBLIC] // Initialize the connection creation parameters to default values. //----------------------------------------------------------------------------- int dpiContext_initConnCreateParams(const dpiContext *context, dpiConnCreateParams *params) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, params) dpiContext__initConnCreateParams(params); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiContext_initPoolCreateParams() [PUBLIC] // Initialize the pool creation parameters to default values. //----------------------------------------------------------------------------- int dpiContext_initPoolCreateParams(const dpiContext *context, dpiPoolCreateParams *params) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, params) dpiContext__initPoolCreateParams(params); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiContext_initSodaOperOptions() [PUBLIC] // Initialize the SODA operation options to default values. //----------------------------------------------------------------------------- int dpiContext_initSodaOperOptions(const dpiContext *context, dpiSodaOperOptions *options) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, options) dpiContext__initSodaOperOptions(options); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiContext_initSubscrCreateParams() [PUBLIC] // Initialize the subscription creation parameters to default values. //----------------------------------------------------------------------------- int dpiContext_initSubscrCreateParams(const dpiContext *context, dpiSubscrCreateParams *params) { dpiError error; if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(context, params) dpiContext__initSubscrCreateParams(params); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } odpi-5.6.4/src/dpiData.c000066400000000000000000001051171510466437300150000ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiData.c // Implementation of transformation routines. //----------------------------------------------------------------------------- #include "dpiImpl.h" // constants used for converting timestamps to/from an interval #define DPI_MS_DAY 86400000 // 24 * 60 * 60 * 1000 #define DPI_MS_HOUR 3600000 // 60 * 60 * 1000 #define DPI_MS_MINUTE 60000 // 60 * 1000 #define DPI_MS_SECOND 1000 // ms per sec #define DPI_MS_FSECOND 1000000 // 1000 * 1000 //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleDate() [INTERNAL] // Populate the data from an dpiOciDate structure. //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue) { dpiTimestamp *timestamp = &data->asTimestamp; timestamp->year = oracleValue->year; timestamp->month = oracleValue->month; timestamp->day = oracleValue->day; timestamp->hour = oracleValue->hour; timestamp->minute = oracleValue->minute; timestamp->second = oracleValue->second; timestamp->fsecond = 0; timestamp->tzHourOffset = 0; timestamp->tzMinuteOffset = 0; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleDateAsDouble() [INTERNAL] // Populate the data from an dpiOciDate structure as a double value (number // of milliseconds since January 1, 1970). //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data, dpiEnv *env, dpiError *error, dpiOciDate *oracleValue) { void *timestamp; int status; // allocate and populate a timestamp with the value of the date if (dpiOci__descriptorAlloc(env->handle, ×tamp, DPI_OCI_DTYPE_TIMESTAMP, "alloc timestamp", error) < 0) return DPI_FAILURE; if (dpiOci__dateTimeConstruct(env->handle, timestamp, oracleValue->year, oracleValue->month, oracleValue->day, oracleValue->hour, oracleValue->minute, oracleValue->second, 0, NULL, 0, error) < 0) { dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); return DPI_FAILURE; } // now calculate the number of milliseconds since January 1, 1970 status = dpiDataBuffer__fromOracleTimestampAsDouble(data, DPI_ORACLE_TYPE_TIMESTAMP, env, error, timestamp); dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); return status; } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleIntervalDS() [INTERNAL] // Populate the data from an OCIInterval structure (days/seconds). //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue) { dpiIntervalDS *interval = &data->asIntervalDS; return dpiOci__intervalGetDaySecond(env->handle, &interval->days, &interval->hours, &interval->minutes, &interval->seconds, &interval->fseconds, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleIntervalYM() [INTERNAL] // Populate the data from an OCIInterval structure (years/months). //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue) { dpiIntervalYM *interval = &data->asIntervalYM; return dpiOci__intervalGetYearMonth(env->handle, &interval->years, &interval->months, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleNumberAsDouble() [INTERNAL] // Populate the data from an OCINumber structure as a double. //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data, dpiError *error, void *oracleValue) { return dpiOci__numberToReal(&data->asDouble, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleNumberAsInteger() [INTERNAL] // Populate the data from an OCINumber structure as an integer. //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue) { return dpiOci__numberToInt(oracleValue, &data->asInt64, sizeof(int64_t), DPI_OCI_NUMBER_SIGNED, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleNumberAsUnsignedInteger() [INTERNAL] // Populate the data from an OCINumber structure as an unsigned integer. //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue) { return dpiOci__numberToInt(oracleValue, &data->asUint64, sizeof(uint64_t), DPI_OCI_NUMBER_UNSIGNED, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleNumberAsText() [INTERNAL] // Populate the data from an OCINumber structure as text. //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue) { uint8_t *target, numDigits, digits[DPI_NUMBER_MAX_DIGITS]; int16_t decimalPointIndex, i; uint16_t *targetUtf16; uint32_t numBytes; dpiBytes *bytes; int isNegative; // parse the OCINumber structure if (dpiUtils__parseOracleNumber(oracleValue, &isNegative, &decimalPointIndex, &numDigits, digits, error) < 0) return DPI_FAILURE; // calculate the number of bytes that will be required for the string numBytes = numDigits; if (isNegative) numBytes++; if (decimalPointIndex <= 0) numBytes += -decimalPointIndex + 2; else if (decimalPointIndex < numDigits) numBytes++; else if (decimalPointIndex > numDigits) numBytes += decimalPointIndex - numDigits; if (env->charsetId == DPI_CHARSET_ID_UTF16) numBytes *= 2; // verify that the provided buffer is large enough bytes = &data->asBytes; if (numBytes > bytes->length) return dpiError__set(error, "check number to text size", DPI_ERR_BUFFER_SIZE_TOO_SMALL, bytes->length); bytes->length = numBytes; // UTF-16 must be handled differently; the platform endianness is used in // order to be compatible with OCI which has this restriction if (env->charsetId == DPI_CHARSET_ID_UTF16) { targetUtf16 = (uint16_t*) bytes->ptr; // if negative, include the sign if (isNegative) *targetUtf16++ = '-'; // if the decimal point index is 0 or less, add the decimal point and // any leading zeroes that are needed if (decimalPointIndex <= 0) { *targetUtf16++ = '0'; *targetUtf16++ = '.'; for (; decimalPointIndex < 0; decimalPointIndex++) *targetUtf16++ = '0'; } // add each of the digits for (i = 0; i < numDigits; i++) { if (i > 0 && i == decimalPointIndex) *targetUtf16++ = '.'; *targetUtf16++ = '0' + digits[i]; } // if the decimal point index exceeds the number of digits, add any // trailing zeroes that are needed if (decimalPointIndex > numDigits) { for (i = numDigits; i < decimalPointIndex; i++) *targetUtf16++ = '0'; } // add NULL terminator for ease of use by C conversion functions like // strtoll(), strtod(), etc. *targetUtf16++ = 0; // the following should be the same logic as the section above for UTF-16, // simply with single byte encodings instead } else { target = (uint8_t*) bytes->ptr; // if negative, include the sign if (isNegative) *target++ = '-'; // if the decimal point index is 0 or less, add the decimal point and // any leading zeroes that are needed if (decimalPointIndex <= 0) { *target++ = '0'; *target++ = '.'; for (; decimalPointIndex < 0; decimalPointIndex++) *target++ = '0'; } // add each of the digits for (i = 0; i < numDigits; i++) { if (i > 0 && i == decimalPointIndex) *target++ = '.'; *target++ = '0' + digits[i]; } // if the decimal point index exceeds the number of digits, add any // trailing zeroes that are needed if (decimalPointIndex > numDigits) { for (i = numDigits; i < decimalPointIndex; i++) *target++ = '0'; } // add NULL terminator for ease of use by C conversion functions like // strtoll(), strtod(), etc. *target++ = 0; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleTimestamp() [INTERNAL] // Populate the data from an OCIDateTime structure. //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue, int withTZ) { dpiTimestamp *timestamp = &data->asTimestamp; if (dpiOci__dateTimeGetDate(env->handle, oracleValue, ×tamp->year, ×tamp->month, ×tamp->day, error) < 0) return DPI_FAILURE; if (dpiOci__dateTimeGetTime(env->handle, oracleValue, ×tamp->hour, ×tamp->minute, ×tamp->second, ×tamp->fsecond, error) < 0) return DPI_FAILURE; if (withTZ) { if (dpiOci__dateTimeGetTimeZoneOffset(env->handle, oracleValue, ×tamp->tzHourOffset, ×tamp->tzMinuteOffset, error) < 0) return DPI_FAILURE; } else { timestamp->tzHourOffset = 0; timestamp->tzMinuteOffset = 0; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__fromOracleTimestampAsDouble() [INTERNAL] // Populate the data from an OCIDateTime structure as a double value (number // of milliseconds since January 1, 1970). //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data, uint32_t dataType, dpiEnv *env, dpiError *error, void *oracleValue) { int32_t day, hour, minute, second, fsecond; void *interval, *baseDate; int status; // determine the base date to use for the given data type if (dpiEnv__getBaseDate(env, dataType, &baseDate, error) < 0) return DPI_FAILURE; // allocate interval to use in calculation if (dpiOci__descriptorAlloc(env->handle, &interval, DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0) return DPI_FAILURE; // subtract dates to determine interval between date and base date if (dpiOci__dateTimeSubtract(env->handle, oracleValue, baseDate, interval, error) < 0) { dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); return DPI_FAILURE; } // get the days, hours, minutes and seconds from the interval status = dpiOci__intervalGetDaySecond(env->handle, &day, &hour, &minute, &second, &fsecond, interval, error); dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); if (status < 0) return DPI_FAILURE; // calculate milliseconds since January 1, 1970 data->asDouble = ((double) day) * DPI_MS_DAY + hour * DPI_MS_HOUR + minute * DPI_MS_MINUTE + second * DPI_MS_SECOND + fsecond / DPI_MS_FSECOND; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleDate() [INTERNAL] // Populate the data in an dpiOciDate structure. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue) { dpiTimestamp *timestamp = &data->asTimestamp; oracleValue->year = timestamp->year; oracleValue->month = timestamp->month; oracleValue->day = timestamp->day; oracleValue->hour = timestamp->hour; oracleValue->minute = timestamp->minute; oracleValue->second = timestamp->second; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleDateFromDouble() [INTERNAL] // Populate the data in an dpiOciDate structure given a double (number of // milliseconds since January 1, 1970). //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env, dpiError *error, dpiOciDate *oracleValue) { uint32_t fsecond; void *timestamp; // allocate a descriptor to acquire a timestamp if (dpiOci__descriptorAlloc(env->handle, ×tamp, DPI_OCI_DTYPE_TIMESTAMP, "alloc timestamp", error) < 0) return DPI_FAILURE; if (dpiDataBuffer__toOracleTimestampFromDouble(data, DPI_ORACLE_TYPE_TIMESTAMP, env, error, timestamp) < 0) { dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); return DPI_FAILURE; } // populate date structure if (dpiOci__dateTimeGetDate(env->handle, timestamp, &oracleValue->year, &oracleValue->month, &oracleValue->day, error) < 0) { dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); return DPI_FAILURE; } if (dpiOci__dateTimeGetTime(env->handle, timestamp, &oracleValue->hour, &oracleValue->minute, &oracleValue->second, &fsecond, error) < 0) { dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); return DPI_FAILURE; } dpiOci__descriptorFree(timestamp, DPI_OCI_DTYPE_TIMESTAMP); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleIntervalDS() [INTERNAL] // Populate the data in an OCIInterval structure (days/seconds). //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue) { dpiIntervalDS *interval = &data->asIntervalDS; return dpiOci__intervalSetDaySecond(env->handle, interval->days, interval->hours, interval->minutes, interval->seconds, interval->fseconds, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleIntervalYM() [INTERNAL] // Populate the data in an OCIInterval structure (years/months). //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue) { dpiIntervalYM *interval = &data->asIntervalYM; return dpiOci__intervalSetYearMonth(env->handle, interval->years, interval->months, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleNumberFromDouble() [INTERNAL] // Populate the data in an OCINumber structure from a double. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data, dpiError *error, void *oracleValue) { if (isnan(data->asDouble)) return dpiError__set(error, "convert double to Oracle number", DPI_ERR_NAN); return dpiOci__numberFromReal(data->asDouble, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleNumberFromInteger() [INTERNAL] // Populate the data in an OCINumber structure from an integer. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue) { return dpiOci__numberFromInt(&data->asInt64, sizeof(int64_t), DPI_OCI_NUMBER_SIGNED, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleNumberFromText() [INTERNAL] // Populate the data in an OCINumber structure from text. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue) { uint8_t numDigits, digits[DPI_NUMBER_AS_TEXT_CHARS], *source, *target, i; int isNegative, prependZero, appendSentinel; dpiBytes *value = &data->asBytes; int16_t decimalPointIndex; uint8_t byte, numPairs; int8_t ociExponent; // parse the string into its constituent components if (dpiUtils__parseNumberString(value->ptr, value->length, env->charsetId, &isNegative, &decimalPointIndex, &numDigits, digits, error) < 0) return DPI_FAILURE; // if the exponent is odd, prepend a zero prependZero = (decimalPointIndex > 0 && decimalPointIndex % 2 == 1) || (decimalPointIndex < 0 && decimalPointIndex % 2 == -1); if (prependZero && numDigits != 0) { digits[numDigits++] = 0; decimalPointIndex++; } // determine the number of digit pairs; if the number of digits is odd, // append a zero to make the number of digits even if (numDigits % 2 == 1) digits[numDigits++] = 0; numPairs = numDigits / 2; // append a sentinel 102 byte for negative numbers if there is room appendSentinel = (isNegative && numDigits > 0 && numDigits < DPI_NUMBER_MAX_DIGITS); // initialize the OCINumber value // the length is the number of pairs, plus one for the exponent // include an extra byte for the sentinel if applicable target = (uint8_t*) oracleValue; *target++ = (uint8_t) (numPairs + 1 + appendSentinel); // if the number of digits is zero, the value is itself zero since all // leading and trailing zeroes are removed from the digits string; the OCI // value for zero is a special case if (numDigits == 0) { *target = 128; return DPI_SUCCESS; } // calculate the exponent ociExponent = (int8_t) ((decimalPointIndex - 2) / 2 + 193); if (isNegative) ociExponent = ~ociExponent; *target++ = (uint8_t) ociExponent; // calculate the mantissa bytes source = digits; for (i = 0; i < numPairs; i++) { if (i == 0 && prependZero) byte = *source++; else { byte = *source++ * 10; byte += *source++; } if (isNegative) byte = 101 - byte; else byte++; *target++ = byte; } // append 102 byte for negative numbers if the number of digits is less // than the maximum allowable if (appendSentinel) *target = 102; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleNumberFromUnsignedInteger() [INTERNAL] // Populate the data in an OCINumber structure from an integer. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue) { return dpiOci__numberFromInt(&data->asUint64, sizeof(uint64_t), DPI_OCI_NUMBER_UNSIGNED, oracleValue, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleTimestamp() [INTERNAL] // Populate the data in an OCIDateTime structure. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue, int withTZ) { dpiTimestamp *timestamp = &data->asTimestamp; char tzOffsetBuffer[10], *tzOffset = NULL; size_t tzOffsetLength = 0; char sign; if (withTZ) { sign = (timestamp->tzHourOffset < 0 || timestamp->tzMinuteOffset < 0) ? '-' : '+'; tzOffsetLength = (size_t) sprintf(tzOffsetBuffer, "%c%.2d:%.2d", sign, abs(timestamp->tzHourOffset), abs(timestamp->tzMinuteOffset)); tzOffset = tzOffsetBuffer; } return dpiOci__dateTimeConstruct(env->handle, oracleValue, timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second, timestamp->fsecond, tzOffset, tzOffsetLength, error); } //----------------------------------------------------------------------------- // dpiDataBuffer__toOracleTimestampFromDouble() [INTERNAL] // Populate the data in an OCIDateTime structure, given the number of // milliseconds since January 1, 1970. //----------------------------------------------------------------------------- int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data, uint32_t dataType, dpiEnv *env, dpiError *error, void *oracleValue) { int32_t day, hour, minute, second, fsecond; void *interval, *baseDate; int status; double ms; // determine the base date to use for the given data type if (dpiEnv__getBaseDate(env, dataType, &baseDate, error) < 0) return DPI_FAILURE; // allocate interval to use in calculation if (dpiOci__descriptorAlloc(env->handle, &interval, DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval", error) < 0) return DPI_FAILURE; // determine the interval ms = data->asDouble; day = (int32_t) (ms / DPI_MS_DAY); ms = ms - ((double) day) * DPI_MS_DAY; hour = (int32_t) (ms / DPI_MS_HOUR); ms = ms - (hour * DPI_MS_HOUR); minute = (int32_t) (ms / DPI_MS_MINUTE); ms = ms - (minute * DPI_MS_MINUTE); second = (int32_t) (ms / DPI_MS_SECOND); ms = ms - (second * DPI_MS_SECOND); fsecond = (int32_t)(ms * DPI_MS_FSECOND); if (dpiOci__intervalSetDaySecond(env->handle, day, hour, minute, second, fsecond, interval, error) < 0) { dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); return DPI_FAILURE; } // add the interval to the base date status = dpiOci__dateTimeIntervalAdd(env->handle, baseDate, interval, oracleValue, error); dpiOci__descriptorFree(interval, DPI_OCI_DTYPE_INTERVAL_DS); return status; } //----------------------------------------------------------------------------- // dpiData_getBool() [PUBLIC] // Return the boolean portion of the data. //----------------------------------------------------------------------------- int dpiData_getBool(dpiData *data) { return data->value.asBoolean; } //----------------------------------------------------------------------------- // dpiData_getBytes() [PUBLIC] // Return the bytes portion of the data. //----------------------------------------------------------------------------- dpiBytes *dpiData_getBytes(dpiData *data) { return &data->value.asBytes; } //----------------------------------------------------------------------------- // dpiData_getDouble() [PUBLIC] // Return the double portion of the data. //----------------------------------------------------------------------------- double dpiData_getDouble(dpiData *data) { return data->value.asDouble; } //----------------------------------------------------------------------------- // dpiData_getFloat() [PUBLIC] // Return the float portion of the data. //----------------------------------------------------------------------------- float dpiData_getFloat(dpiData *data) { return data->value.asFloat; } //----------------------------------------------------------------------------- // dpiData_getInt64() [PUBLIC] // Return the integer portion of the data. //----------------------------------------------------------------------------- int64_t dpiData_getInt64(dpiData *data) { return data->value.asInt64; } //----------------------------------------------------------------------------- // dpiData_getIntervalDS() [PUBLIC] // Return the interval (days/seconds) portion of the data. //----------------------------------------------------------------------------- dpiIntervalDS *dpiData_getIntervalDS(dpiData *data) { return &data->value.asIntervalDS; } //----------------------------------------------------------------------------- // dpiData_getIntervalYM() [PUBLIC] // Return the interval (years/months) portion of the data. //----------------------------------------------------------------------------- dpiIntervalYM *dpiData_getIntervalYM(dpiData *data) { return &data->value.asIntervalYM; } //----------------------------------------------------------------------------- // dpiData_getIsNull() [PUBLIC] // Return a boolean indicating if the value is null or not. //----------------------------------------------------------------------------- int dpiData_getIsNull(dpiData *data) { return data->isNull; } //----------------------------------------------------------------------------- // dpiData_getLOB() [PUBLIC] // Return the LOB portion of the data. //----------------------------------------------------------------------------- dpiLob *dpiData_getLOB(dpiData *data) { return data->value.asLOB; } //----------------------------------------------------------------------------- // dpiData_getJson() [PUBLIC] // Return the JSON portion of the data. //----------------------------------------------------------------------------- dpiJson *dpiData_getJson(dpiData *data) { return data->value.asJson; } //----------------------------------------------------------------------------- // dpiData_getJsonArray() [PUBLIC] // Return the JSON Array portion of the data. //----------------------------------------------------------------------------- dpiJsonArray *dpiData_getJsonArray(dpiData *data) { return &data->value.asJsonArray; } //----------------------------------------------------------------------------- // dpiData_getJsonObject() [PUBLIC] // Return the JSON Object portion of the data. //----------------------------------------------------------------------------- dpiJsonObject *dpiData_getJsonObject(dpiData *data) { return &data->value.asJsonObject; } //----------------------------------------------------------------------------- // dpiData_getObject() [PUBLIC] // Return the object portion of the data. //----------------------------------------------------------------------------- dpiObject *dpiData_getObject(dpiData *data) { return data->value.asObject; } //----------------------------------------------------------------------------- // dpiData_getStmt() [PUBLIC] // Return the statement portion of the data. //----------------------------------------------------------------------------- dpiStmt *dpiData_getStmt(dpiData *data) { return data->value.asStmt; } //----------------------------------------------------------------------------- // dpiData_getTimestamp() [PUBLIC] // Return the timestamp portion of the data. //----------------------------------------------------------------------------- dpiTimestamp *dpiData_getTimestamp(dpiData *data) { return &data->value.asTimestamp; } //----------------------------------------------------------------------------- // dpiData_getUint64() [PUBLIC] // Return the unsigned integer portion of the data. //----------------------------------------------------------------------------- uint64_t dpiData_getUint64(dpiData *data) { return data->value.asUint64; } //----------------------------------------------------------------------------- // dpiData_getVector() [PUBLIC] // Return the VECTOR portion of the data. //----------------------------------------------------------------------------- dpiVector *dpiData_getVector(dpiData *data) { return data->value.asVector; } //----------------------------------------------------------------------------- // dpiData_setBool() [PUBLIC] // Set the boolean portion of the data. //----------------------------------------------------------------------------- void dpiData_setBool(dpiData *data, int value) { data->isNull = 0; data->value.asBoolean = value; } //----------------------------------------------------------------------------- // dpiData_setBytes() [PUBLIC] // Set the bytes portion of the data. //----------------------------------------------------------------------------- void dpiData_setBytes(dpiData *data, char *ptr, uint32_t length) { data->isNull = 0; data->value.asBytes.ptr = ptr; data->value.asBytes.length = length; } //----------------------------------------------------------------------------- // dpiData_setDouble() [PUBLIC] // Set the double portion of the data. //----------------------------------------------------------------------------- void dpiData_setDouble(dpiData *data, double value) { data->isNull = 0; data->value.asDouble = value; } //----------------------------------------------------------------------------- // dpiData_setFloat() [PUBLIC] // Set the float portion of the data. //----------------------------------------------------------------------------- void dpiData_setFloat(dpiData *data, float value) { data->isNull = 0; data->value.asFloat = value; } //----------------------------------------------------------------------------- // dpiData_setInt64() [PUBLIC] // Set the integer portion of the data. //----------------------------------------------------------------------------- void dpiData_setInt64(dpiData *data, int64_t value) { data->isNull = 0; data->value.asInt64 = value; } //----------------------------------------------------------------------------- // dpiData_setIntervalDS() [PUBLIC] // Set the interval (days/seconds) portion of the data. //----------------------------------------------------------------------------- void dpiData_setIntervalDS(dpiData *data, int32_t days, int32_t hours, int32_t minutes, int32_t seconds, int32_t fseconds) { dpiIntervalDS *interval = &data->value.asIntervalDS; data->isNull = 0; interval->days = days; interval->hours = hours; interval->minutes = minutes; interval->seconds = seconds; interval->fseconds = fseconds; } //----------------------------------------------------------------------------- // dpiData_setIntervalYM() [PUBLIC] // Set the interval (years/months) portion of the data. //----------------------------------------------------------------------------- void dpiData_setIntervalYM(dpiData *data, int32_t years, int32_t months) { dpiIntervalYM *interval = &data->value.asIntervalYM; data->isNull = 0; interval->years = years; interval->months = months; } //----------------------------------------------------------------------------- // dpiData_setLOB() [PUBLIC] // Set the LOB portion of the data. //----------------------------------------------------------------------------- void dpiData_setLOB(dpiData *data, dpiLob *lob) { data->isNull = 0; data->value.asLOB = lob; } //----------------------------------------------------------------------------- // dpiData_setNull() [PUBLIC] // Set the data to be treated as a null value. //----------------------------------------------------------------------------- void dpiData_setNull(dpiData *data) { data->isNull = 1; } //----------------------------------------------------------------------------- // dpiData_setObject() [PUBLIC] // Set the object portion of the data. //----------------------------------------------------------------------------- void dpiData_setObject(dpiData *data, dpiObject *obj) { data->isNull = 0; data->value.asObject = obj; } //----------------------------------------------------------------------------- // dpiData_setStmt() [PUBLIC] // Set the statement portion of the data. //----------------------------------------------------------------------------- void dpiData_setStmt(dpiData *data, dpiStmt *obj) { data->isNull = 0; data->value.asStmt = obj; } //----------------------------------------------------------------------------- // dpiData_setTimestamp() [PUBLIC] // Set the timestamp portion of the data. //----------------------------------------------------------------------------- void dpiData_setTimestamp(dpiData *data, int16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t fsecond, int8_t tzHourOffset, int8_t tzMinuteOffset) { dpiTimestamp *timestamp = &data->value.asTimestamp; data->isNull = 0; timestamp->year = year; timestamp->month = month; timestamp->day = day; timestamp->hour = hour; timestamp->minute = minute; timestamp->second = second; timestamp->fsecond = fsecond; timestamp->tzHourOffset = tzHourOffset; timestamp->tzMinuteOffset = tzMinuteOffset; } //----------------------------------------------------------------------------- // dpiData_setUint64() [PUBLIC] // Set the unsigned integer portion of the data. //----------------------------------------------------------------------------- void dpiData_setUint64(dpiData *data, uint64_t value) { data->isNull = 0; data->value.asUint64 = value; } odpi-5.6.4/src/dpiDebug.c000066400000000000000000000164231510466437300151560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiDebug.c // Methods used for debugging ODPI-C. //----------------------------------------------------------------------------- #include "dpiImpl.h" #define DPI_DEBUG_THREAD_FORMAT "%.5" PRIu64 #define DPI_DEBUG_DATE_FORMAT "%.4d-%.2d-%.2d" #define DPI_DEBUG_TIME_FORMAT "%.2d:%.2d:%.2d.%.3d" // debug level (populated by environment variable DPI_DEBUG_LEVEL) unsigned long dpiDebugLevel = 0; // debug prefix format (populated by environment variable DPI_DEBUG_PREFIX) static char dpiDebugPrefixFormat[64] = "ODPI [%i] %d %t: "; // debug file for printing (currently unchangeable) static FILE *dpiDebugStream = NULL; //----------------------------------------------------------------------------- // dpiDebug__getFormatWithPrefix() [INTERNAL] // Adjust the provided format to include the prefix requested by the user. // This method is not permitted to fail, so if there is not enough space, the // prefix is truncated as needed -- although this is a very unlikely scenario. //----------------------------------------------------------------------------- static void dpiDebug__getFormatWithPrefix(const char *format, char *formatWithPrefix, size_t maxFormatWithPrefixSize) { char *sourcePtr, *targetPtr; int gotTime, tempSize; uint64_t threadId; size_t size; #ifdef _WIN32 SYSTEMTIME time; #else struct timeval timeOfDay; struct tm time; #endif gotTime = 0; sourcePtr = dpiDebugPrefixFormat; targetPtr = formatWithPrefix; size = maxFormatWithPrefixSize - strlen(format); while (*sourcePtr && size > 20) { // all characters except '%' are copied verbatim to the target if (*sourcePtr != '%') { *targetPtr++ = *sourcePtr++; maxFormatWithPrefixSize--; continue; } // handle the different directives sourcePtr++; switch (*sourcePtr) { case 'i': #ifdef _WIN32 threadId = (uint64_t) GetCurrentThreadId(); #elif defined __linux threadId = (uint64_t) syscall(SYS_gettid); #elif defined __APPLE__ pthread_threadid_np(NULL, &threadId); #else threadId = (uint64_t) pthread_self(); #endif tempSize = sprintf(targetPtr, DPI_DEBUG_THREAD_FORMAT, threadId); size -= tempSize; targetPtr += tempSize; sourcePtr++; break; case 'd': case 't': if (!gotTime) { gotTime = 1; #ifdef _WIN32 GetLocalTime(&time); #else gettimeofday(&timeOfDay, NULL); localtime_r(&timeOfDay.tv_sec, &time); #endif } #ifdef _WIN32 if (*sourcePtr == 'd') tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT, time.wYear, time.wMonth, time.wDay); else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds); #else if (*sourcePtr == 'd') tempSize = sprintf(targetPtr, DPI_DEBUG_DATE_FORMAT, time.tm_year + 1900, time.tm_mon + 1, time.tm_mday); else tempSize = sprintf(targetPtr, DPI_DEBUG_TIME_FORMAT, time.tm_hour, time.tm_min, time.tm_sec, (int) (timeOfDay.tv_usec / 1000)); #endif size -= tempSize; targetPtr += tempSize; sourcePtr++; break; case '\0': break; default: *targetPtr++ = '%'; *targetPtr++ = *sourcePtr++; break; } } // append original format strcpy(targetPtr, format); } //----------------------------------------------------------------------------- // dpiDebug__initialize() [INTERNAL] // Initialize debugging infrastructure. This reads the environment variables // and populates the global variables used for determining which messages to // print and what prefix should be placed in front of each message. //----------------------------------------------------------------------------- void dpiDebug__initialize(void) { char *envValue; // determine the value of the environment variable DPI_DEBUG_LEVEL and // convert to an integer; if the value in the environment variable is not a // valid integer, it is ignored envValue = getenv("DPI_DEBUG_LEVEL"); if (envValue) dpiDebugLevel = (unsigned long) strtol(envValue, NULL, 10); // determine the value of the environment variable DPI_DEBUG_PREFIX and // store it in the static buffer available for it; a static buffer is used // since this runs during startup and may not fail; if the value of the // environment variable is too large for the buffer, the value is ignored // and the default value is used instead envValue = getenv("DPI_DEBUG_PREFIX"); if (envValue && strlen(envValue) < sizeof(dpiDebugPrefixFormat)) strcpy(dpiDebugPrefixFormat, envValue); // messages are written to stderr dpiDebugStream = stderr; // for any debugging level > 0 print a message indicating that tracing // has started if (dpiDebugLevel) { dpiDebug__print("ODPI-C %s\n", DPI_VERSION_STRING); dpiDebug__print("debugging messages initialized at level %lu\n", dpiDebugLevel); } } //----------------------------------------------------------------------------- // dpiDebug__print() [INTERNAL] // Print the specified debugging message with a newly calculated prefix. //----------------------------------------------------------------------------- void dpiDebug__print(const char *format, ...) { char formatWithPrefix[512]; va_list varArgs; dpiDebug__getFormatWithPrefix(format, formatWithPrefix, sizeof(formatWithPrefix)); va_start(varArgs, format); (void) vfprintf(dpiDebugStream, formatWithPrefix, varArgs); va_end(varArgs); } odpi-5.6.4/src/dpiDeqOptions.c000066400000000000000000000363261510466437300162210ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiDeqOptions.c // Implementation of AQ dequeue options. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiDeqOptions__create() [INTERNAL] // Create a new subscription structure and return it. In case of error NULL // is returned. //----------------------------------------------------------------------------- int dpiDeqOptions__create(dpiDeqOptions *options, dpiConn *conn, dpiError *error) { dpiGen__setRefCount(conn, error, 1); options->conn = conn; return dpiOci__descriptorAlloc(conn->env->handle, &options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, "allocate descriptor", error); } //----------------------------------------------------------------------------- // dpiDeqOptions__free() [INTERNAL] // Free the memory for a dequeue options structure. //----------------------------------------------------------------------------- void dpiDeqOptions__free(dpiDeqOptions *options, dpiError *error) { if (options->msgIdRaw) { dpiOci__rawResize(options->env->handle, &options->msgIdRaw, 0, error); options->msgIdRaw = NULL; } if (options->handle) { dpiOci__descriptorFree(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS); options->handle = NULL; } if (options->conn) { dpiGen__setRefCount(options->conn, error, -1); options->conn = NULL; } dpiUtils__freeMemory(options); } //----------------------------------------------------------------------------- // dpiDeqOptions__getAttrValue() [INTERNAL] // Get the attribute value in OCI. //----------------------------------------------------------------------------- static int dpiDeqOptions__getAttrValue(dpiDeqOptions *options, uint32_t attribute, const char *fnName, void *value, uint32_t *valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, fnName, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(options, value) DPI_CHECK_PTR_NOT_NULL(options, valueLength) status = dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, value, valueLength, attribute, "get attribute value", &error); return dpiGen__endPublicFn(options, status, &error); } //----------------------------------------------------------------------------- // dpiDeqOptions__setAttrValue() [INTERNAL] // Set the attribute value in OCI. //----------------------------------------------------------------------------- static int dpiDeqOptions__setAttrValue(dpiDeqOptions *options, uint32_t attribute, const char *fnName, const void *value, uint32_t valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, fnName, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(options, value) status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, (void*) value, valueLength, attribute, "set attribute value", &error); return dpiGen__endPublicFn(options, status, &error); } //----------------------------------------------------------------------------- // dpiDeqOptions_addRef() [PUBLIC] // Add a reference to the dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_addRef(dpiDeqOptions *options) { return dpiGen__addRef(options, DPI_HTYPE_DEQ_OPTIONS, __func__); } //----------------------------------------------------------------------------- // dpiDeqOptions_getCondition() [PUBLIC] // Return condition associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getCondition(dpiDeqOptions *options, const char **value, uint32_t *valueLength) { return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_DEQCOND, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getConsumerName() [PUBLIC] // Return consumer name associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getConsumerName(dpiDeqOptions *options, const char **value, uint32_t *valueLength) { return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_CONSUMER_NAME, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getCorrelation() [PUBLIC] // Return correlation associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getCorrelation(dpiDeqOptions *options, const char **value, uint32_t *valueLength) { return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_CORRELATION, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getMode() [PUBLIC] // Return mode associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getMode(dpiDeqOptions *options, dpiDeqMode *value) { uint32_t valueLength = sizeof(uint32_t); return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_DEQ_MODE, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getMsgId() [PUBLIC] // Return message id associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getMsgId(dpiDeqOptions *options, const char **value, uint32_t *valueLength) { dpiError error; void *rawValue; if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, __func__, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(options, value) DPI_CHECK_PTR_NOT_NULL(options, valueLength) if (dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, &rawValue, NULL, DPI_OCI_ATTR_DEQ_MSGID, "get attribute value", &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); dpiOci__rawPtr(options->env->handle, rawValue, (void**) value); dpiOci__rawSize(options->env->handle, rawValue, valueLength); return dpiGen__endPublicFn(options, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiDeqOptions_getNavigation() [PUBLIC] // Return navigation associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getNavigation(dpiDeqOptions *options, dpiDeqNavigation *value) { uint32_t valueLength = sizeof(uint32_t); return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_NAVIGATION, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getTransformation() [PUBLIC] // Return transformation associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getTransformation(dpiDeqOptions *options, const char **value, uint32_t *valueLength) { return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getVisibility() [PUBLIC] // Return visibility associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_getVisibility(dpiDeqOptions *options, dpiVisibility *value) { uint32_t valueLength = sizeof(uint32_t); return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_VISIBILITY, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_getWait() [PUBLIC] // Return the number of seconds to wait for a message when dequeuing. //----------------------------------------------------------------------------- int dpiDeqOptions_getWait(dpiDeqOptions *options, uint32_t *value) { uint32_t valueLength = sizeof(uint32_t); return dpiDeqOptions__getAttrValue(options, DPI_OCI_ATTR_WAIT, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_release() [PUBLIC] // Release a reference to the dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_release(dpiDeqOptions *options) { return dpiGen__release(options, DPI_HTYPE_DEQ_OPTIONS, __func__); } //----------------------------------------------------------------------------- // dpiDeqOptions_setCondition() [PUBLIC] // Set condition associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setCondition(dpiDeqOptions *options, const char *value, uint32_t valueLength) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_DEQCOND, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_setConsumerName() [PUBLIC] // Set consumer name associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setConsumerName(dpiDeqOptions *options, const char *value, uint32_t valueLength) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_CONSUMER_NAME, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_setCorrelation() [PUBLIC] // Set correlation associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setCorrelation(dpiDeqOptions *options, const char *value, uint32_t valueLength) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_CORRELATION, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_setDeliveryMode() [PUBLIC] // Set the delivery mode associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setDeliveryMode(dpiDeqOptions *options, dpiMessageDeliveryMode value) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_MSG_DELIVERY_MODE, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiDeqOptions_setMode() [PUBLIC] // Set the mode associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setMode(dpiDeqOptions *options, dpiDeqMode value) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_DEQ_MODE, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiDeqOptions_setMsgId() [PUBLIC] // Set the message id associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setMsgId(dpiDeqOptions *options, const char *value, uint32_t valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(options, DPI_HTYPE_DEQ_OPTIONS, __func__, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(options, value) if (dpiOci__rawAssignBytes(options->env->handle, value, valueLength, &options->msgIdRaw, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQDEQ_OPTIONS, (void*) &options->msgIdRaw, valueLength, DPI_OCI_ATTR_DEQ_MSGID, "set value", &error); return dpiGen__endPublicFn(options, status, &error); } //----------------------------------------------------------------------------- // dpiDeqOptions_setNavigation() [PUBLIC] // Set navigation associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setNavigation(dpiDeqOptions *options, dpiDeqNavigation value) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_NAVIGATION, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiDeqOptions_setTransformation() [PUBLIC] // Set transformation associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setTransformation(dpiDeqOptions *options, const char *value, uint32_t valueLength) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiDeqOptions_setVisibility() [PUBLIC] // Set visibility associated with dequeue options. //----------------------------------------------------------------------------- int dpiDeqOptions_setVisibility(dpiDeqOptions *options, dpiVisibility value) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_VISIBILITY, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiDeqOptions_setWait() [PUBLIC] // Set the number of seconds to wait for a message when dequeuing. //----------------------------------------------------------------------------- int dpiDeqOptions_setWait(dpiDeqOptions *options, uint32_t value) { return dpiDeqOptions__setAttrValue(options, DPI_OCI_ATTR_WAIT, __func__, &value, 0); } odpi-5.6.4/src/dpiEnqOptions.c000066400000000000000000000166001510466437300162240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiEnqOptions.c // Implementation of AQ enqueue options. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiEnqOptions__create() [INTERNAL] // Create a new subscription structure and return it. In case of error NULL // is returned. //----------------------------------------------------------------------------- int dpiEnqOptions__create(dpiEnqOptions *options, dpiConn *conn, dpiError *error) { dpiGen__setRefCount(conn, error, 1); options->conn = conn; return dpiOci__descriptorAlloc(conn->env->handle, &options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, "allocate descriptor", error); } //----------------------------------------------------------------------------- // dpiEnqOptions__free() [INTERNAL] // Free the memory for a enqueue options structure. //----------------------------------------------------------------------------- void dpiEnqOptions__free(dpiEnqOptions *options, dpiError *error) { if (options->handle) { dpiOci__descriptorFree(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS); options->handle = NULL; } if (options->conn) { dpiGen__setRefCount(options->conn, error, -1); options->conn = NULL; } dpiUtils__freeMemory(options); } //----------------------------------------------------------------------------- // dpiEnqOptions__getAttrValue() [INTERNAL] // Get the attribute value in OCI. //----------------------------------------------------------------------------- static int dpiEnqOptions__getAttrValue(dpiEnqOptions *options, uint32_t attribute, const char *fnName, void *value, uint32_t *valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(options, DPI_HTYPE_ENQ_OPTIONS, fnName, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(options, value) DPI_CHECK_PTR_NOT_NULL(options, valueLength) status = dpiOci__attrGet(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, value, valueLength, attribute, "get attribute value", &error); return dpiGen__endPublicFn(options, status, &error); } //----------------------------------------------------------------------------- // dpiEnqOptions__setAttrValue() [INTERNAL] // Set the attribute value in OCI. //----------------------------------------------------------------------------- static int dpiEnqOptions__setAttrValue(dpiEnqOptions *options, uint32_t attribute, const char *fnName, const void *value, uint32_t valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(options, DPI_HTYPE_ENQ_OPTIONS, fnName, &error) < 0) return dpiGen__endPublicFn(options, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(options, value) status = dpiOci__attrSet(options->handle, DPI_OCI_DTYPE_AQENQ_OPTIONS, (void*) value, valueLength, attribute, "set attribute value", &error); return dpiGen__endPublicFn(options, status, &error); } //----------------------------------------------------------------------------- // dpiEnqOptions_addRef() [PUBLIC] // Add a reference to the enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_addRef(dpiEnqOptions *options) { return dpiGen__addRef(options, DPI_HTYPE_ENQ_OPTIONS, __func__); } //----------------------------------------------------------------------------- // dpiEnqOptions_getTransformation() [PUBLIC] // Return transformation associated with enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_getTransformation(dpiEnqOptions *options, const char **value, uint32_t *valueLength) { return dpiEnqOptions__getAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiEnqOptions_getVisibility() [PUBLIC] // Return visibility associated with enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_getVisibility(dpiEnqOptions *options, dpiVisibility *value) { uint32_t valueLength = sizeof(uint32_t); return dpiEnqOptions__getAttrValue(options, DPI_OCI_ATTR_VISIBILITY, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiEnqOptions_release() [PUBLIC] // Release a reference to the enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_release(dpiEnqOptions *options) { return dpiGen__release(options, DPI_HTYPE_ENQ_OPTIONS, __func__); } //----------------------------------------------------------------------------- // dpiEnqOptions_setDeliveryMode() [PUBLIC] // Set the delivery mode associated with enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_setDeliveryMode(dpiEnqOptions *options, dpiMessageDeliveryMode value) { return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_MSG_DELIVERY_MODE, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiEnqOptions_setTransformation() [PUBLIC] // Set transformation associated with enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_setTransformation(dpiEnqOptions *options, const char *value, uint32_t valueLength) { return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_TRANSFORMATION, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiEnqOptions_setVisibility() [PUBLIC] // Set visibility associated with enqueue options. //----------------------------------------------------------------------------- int dpiEnqOptions_setVisibility(dpiEnqOptions *options, dpiVisibility value) { return dpiEnqOptions__setAttrValue(options, DPI_OCI_ATTR_VISIBILITY, __func__, &value, 0); } odpi-5.6.4/src/dpiEnv.c000066400000000000000000000225411510466437300146560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiEnv.c // Implementation of environment. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiEnv__getBaseDate() [INTERNAL] // Return the base date (January 1, 1970 UTC) for the specified handle type. // OCI doesn't permit mixing and matching types so a separate bae date is // required for each of the three timestamp types. If the type has not been // populated already it is created. //----------------------------------------------------------------------------- int dpiEnv__getBaseDate(dpiEnv *env, uint32_t dataType, void **baseDate, dpiError *error) { uint32_t descriptorType; char timezoneBuffer[20]; size_t timezoneLength; void **storedBaseDate; // determine type of descriptor and location of stored base date switch (dataType) { case DPI_ORACLE_TYPE_TIMESTAMP: storedBaseDate = &env->baseDate; descriptorType = DPI_OCI_DTYPE_TIMESTAMP; break; case DPI_ORACLE_TYPE_TIMESTAMP_TZ: storedBaseDate = &env->baseDateTZ; descriptorType = DPI_OCI_DTYPE_TIMESTAMP_TZ; break; case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: storedBaseDate = &env->baseDateLTZ; descriptorType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; break; default: return dpiError__set(error, "get base date", DPI_ERR_UNHANDLED_DATA_TYPE, dataType); } // if a base date has not been stored already, create it if (!*storedBaseDate) { if (dpiOci__descriptorAlloc(env->handle, storedBaseDate, descriptorType, "alloc base date descriptor", error) < 0) return DPI_FAILURE; if (dpiOci__nlsCharSetConvert(env->handle, env->charsetId, timezoneBuffer, sizeof(timezoneBuffer), DPI_CHARSET_ID_ASCII, "+00:00", 6, &timezoneLength, error) < 0) return DPI_FAILURE; if (dpiOci__dateTimeConstruct(env->handle, *storedBaseDate, 1970, 1, 1, 0, 0, 0, 0, timezoneBuffer, timezoneLength, error) < 0) return DPI_FAILURE; } *baseDate = *storedBaseDate; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiEnv__free() [INTERNAL] // Free the memory associated with the environment. //----------------------------------------------------------------------------- void dpiEnv__free(dpiEnv *env, dpiError *error) { if (env->threaded) dpiMutex__destroy(env->mutex); if (env->handle && !env->externalHandle) { dpiOci__handleFree(env->handle, DPI_OCI_HTYPE_ENV); env->handle = NULL; } if (env->errorHandles) { dpiHandlePool__free(env->errorHandles); env->errorHandles = NULL; error->handle = NULL; } dpiUtils__freeMemory(env); } //----------------------------------------------------------------------------- // dpiEnv__getCharacterSetIdAndName() [INTERNAL] // Retrieve and store the IANA character set name for the attribute. //----------------------------------------------------------------------------- static int dpiEnv__getCharacterSetIdAndName(dpiEnv *env, uint16_t attribute, uint16_t *charsetId, char *encoding, dpiError *error) { *charsetId = 0; dpiOci__attrGet(env->handle, DPI_OCI_HTYPE_ENV, charsetId, NULL, attribute, "get environment", error); return dpiGlobal__lookupEncoding(*charsetId, encoding, error); } //----------------------------------------------------------------------------- // dpiEnv__getEncodingInfo() [INTERNAL] // Populate the structure with the encoding info. //----------------------------------------------------------------------------- int dpiEnv__getEncodingInfo(dpiEnv *env, dpiEncodingInfo *info) { info->encoding = env->encoding; info->maxBytesPerCharacter = env->maxBytesPerCharacter; info->nencoding = env->nencoding; info->nmaxBytesPerCharacter = env->nmaxBytesPerCharacter; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiEnv__init() [INTERNAL] // Initialize the environment structure. If an external handle is provided it // is used directly; otherwise, a new OCI environment handle is created. In // either case, information about the environment is stored for later use. //----------------------------------------------------------------------------- int dpiEnv__init(dpiEnv *env, const dpiContext *context, const dpiCommonCreateParams *params, void *externalHandle, dpiCreateMode createMode, dpiError *error) { int temp; // store context and version information env->context = context; env->versionInfo = context->versionInfo; // an external handle is available, use it directly if (externalHandle) { env->handle = externalHandle; env->externalHandle = 1; // otherwise, lookup encodings } else { // lookup encoding if (params->encoding && dpiGlobal__lookupCharSet(params->encoding, &env->charsetId, error) < 0) return DPI_FAILURE; // check for identical encoding before performing lookup of national // character set encoding if (params->nencoding && params->encoding && strcmp(params->nencoding, params->encoding) == 0) env->ncharsetId = env->charsetId; else if (params->nencoding && dpiGlobal__lookupCharSet(params->nencoding, &env->ncharsetId, error) < 0) return DPI_FAILURE; // both charsetId and ncharsetId must be zero or both must be non-zero // use NLS routine to look up missing value, if needed if (env->charsetId && !env->ncharsetId) { if (dpiOci__nlsEnvironmentVariableGet(DPI_OCI_NLS_NCHARSET_ID, &env->ncharsetId, error) < 0) return DPI_FAILURE; } else if (!env->charsetId && env->ncharsetId) { if (dpiOci__nlsEnvironmentVariableGet(DPI_OCI_NLS_CHARSET_ID, &env->charsetId, error) < 0) return DPI_FAILURE; } // create new environment handle if (dpiOci__envNlsCreate(&env->handle, createMode | DPI_OCI_OBJECT, env->charsetId, env->ncharsetId, error) < 0) return DPI_FAILURE; } // create the error handle pool if (dpiHandlePool__create(&env->errorHandles, error) < 0) return DPI_FAILURE; error->env = env; // if threaded, create mutex for reference counts if (createMode & DPI_OCI_THREADED) dpiMutex__initialize(env->mutex); // determine encodings in use if (dpiEnv__getCharacterSetIdAndName(env, DPI_OCI_ATTR_CHARSET_ID, &env->charsetId, env->encoding, error) < 0) return DPI_FAILURE; if (dpiEnv__getCharacterSetIdAndName(env, DPI_OCI_ATTR_NCHARSET_ID, &env->ncharsetId, env->nencoding, error) < 0) return DPI_FAILURE; // acquire max bytes per character if (dpiOci__nlsNumericInfoGet(env->handle, &env->maxBytesPerCharacter, DPI_OCI_NLS_CHARSET_MAXBYTESZ, error) < 0) return DPI_FAILURE; // for NCHAR we have no idea of how many so we simply take the worst case // unless the charsets are identical if (env->ncharsetId == env->charsetId) env->nmaxBytesPerCharacter = env->maxBytesPerCharacter; else env->nmaxBytesPerCharacter = 4; // set whether or not we are threaded if (createMode & DPI_MODE_CREATE_THREADED) env->threaded = 1; // set whether or not events mode has been set if (createMode & DPI_MODE_CREATE_EVENTS) env->events = 1; // enable SODA metadata cache, if applicable if (params->sodaMetadataCache) { if (dpiUtils__checkClientVersionMulti(env->versionInfo, 19, 11, 21, 3, error) < 0) return DPI_FAILURE; temp = 1; if (dpiOci__attrSet(env->handle, DPI_OCI_HTYPE_ENV, &temp, 0, DPI_OCI_ATTR_SODA_METADATA_CACHE, "set SODA metadata cache", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } odpi-5.6.4/src/dpiError.c000066400000000000000000000333601510466437300152200ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiError.c // Implementation of error. //----------------------------------------------------------------------------- #include "dpiImpl.h" #include "dpiErrorMessages.h" //----------------------------------------------------------------------------- // dpiError__getInfo() [INTERNAL] // Get the error state from the error structure. Returns DPI_FAILURE as a // convenience to the caller. //----------------------------------------------------------------------------- int dpiError__getInfo(dpiError *error, dpiErrorInfo *info) { if (!info) return DPI_FAILURE; info->code = error->buffer->code; info->offset = error->buffer->offset; info->offset16 = (uint16_t) error->buffer->offset; info->message = error->buffer->message; info->messageLength = error->buffer->messageLength; info->fnName = error->buffer->fnName; info->action = error->buffer->action; info->isRecoverable = error->buffer->isRecoverable; info->encoding = error->buffer->encoding; info->isWarning = error->buffer->isWarning; if (info->code == 12154) { info->sqlState = "42S02"; } else if (error->buffer->errorNum == DPI_ERR_CONN_CLOSED) { info->sqlState = "01002"; } else if (error->buffer->code == 0 && error->buffer->errorNum == (dpiErrorNum) 0) { info->sqlState = "00000"; } else { info->sqlState = "HY000"; } return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiError__initHandle() [INTERNAL] // Retrieve the OCI error handle to use for error handling, from a pool of // error handles common to the environment handle stored on the error. This // environment also controls the encoding of OCI errors (which uses the CHAR // encoding of the environment). //----------------------------------------------------------------------------- int dpiError__initHandle(dpiError *error) { if (dpiHandlePool__acquire(error->env->errorHandles, &error->handle, error) < 0) return DPI_FAILURE; if (!error->handle) { if (dpiOci__handleAlloc(error->env->handle, &error->handle, DPI_OCI_HTYPE_ERROR, "allocate OCI error", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiError__set() [INTERNAL] // Set the error buffer to the specified DPI error. Returns DPI_FAILURE as a // convenience to the caller. //----------------------------------------------------------------------------- int dpiError__set(dpiError *error, const char *action, dpiErrorNum errorNum, ...) { va_list varArgs; if (error) { error->buffer->code = 0; error->buffer->isRecoverable = 0; error->buffer->isWarning = 0; error->buffer->offset = 0; strcpy(error->buffer->encoding, DPI_CHARSET_NAME_UTF8); error->buffer->action = action; error->buffer->errorNum = errorNum; va_start(varArgs, errorNum); (void) vsnprintf(error->buffer->message, sizeof(error->buffer->message), dpiErrorMessages[errorNum - DPI_ERR_NO_ERR], varArgs); va_end(varArgs); error->buffer->messageLength = (uint32_t) strlen(error->buffer->message); if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) dpiDebug__print("internal error %.*s (%s / %s)\n", error->buffer->messageLength, error->buffer->message, error->buffer->fnName, action); } return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiError__setFromOCI() [INTERNAL] // Called when an OCI error has occurred and sets the error structure with // the contents of that error. Note that trailing newlines and spaces are // truncated from the message if they exist. If the connection is not NULL a // check is made to see if the connection is no longer viable. The value // DPI_FAILURE is returned as a convenience to the caller, except when the // status of the call is DPI_OCI_SUCCESS_WITH_INFO, which is treated as a // successful call. //----------------------------------------------------------------------------- int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn, const char *action) { uint32_t callTimeout, serverStatus; // special error cases if (status == DPI_OCI_INVALID_HANDLE) return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, "OCI"); else if (!error) return DPI_FAILURE; else if (!error->handle) return dpiError__set(error, action, DPI_ERR_ERR_NOT_INITIALIZED); else if (status != DPI_OCI_ERROR && status != DPI_OCI_NO_DATA && status != DPI_OCI_SUCCESS_WITH_INFO) return dpiError__set(error, action, DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, status, error->buffer->fnName); // fetch OCI error error->buffer->action = action; strcpy(error->buffer->encoding, error->env->encoding); if (dpiOci__errorGet(error->handle, DPI_OCI_HTYPE_ERROR, error->env->charsetId, action, error) < 0) return DPI_FAILURE; if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) dpiDebug__print("OCI error %.*s (%s / %s)\n", error->buffer->messageLength, error->buffer->message, error->buffer->fnName, action); if (status == DPI_OCI_SUCCESS_WITH_INFO) { error->buffer->isWarning = 1; return DPI_SUCCESS; } // determine if error is recoverable (Transaction Guard) // if the attribute cannot be read properly, simply leave it as false; // otherwise, that error will mask the one that we really want to see error->buffer->isRecoverable = 0; dpiOci__attrGet(error->handle, DPI_OCI_HTYPE_ERROR, (void*) &error->buffer->isRecoverable, 0, DPI_OCI_ATTR_ERROR_IS_RECOVERABLE, NULL, error); // check the health of the connection (if one was specified in this call // and we are not in the middle of creating that connection) if (conn && !conn->creating && !conn->deadSession) { // first check the attribute specifically designed to check the health // of the connection, if possible if (conn->serverHandle) { if (dpiOci__attrGet(conn->serverHandle, DPI_OCI_HTYPE_SERVER, &serverStatus, NULL, DPI_OCI_ATTR_SERVER_STATUS, "get server status", error) < 0 || serverStatus != DPI_OCI_SERVER_NORMAL) { conn->deadSession = 1; } } // check for certain errors which indicate that the session is dead if (!conn->deadSession) { switch (error->buffer->code) { case 22: // invalid session ID; access denied case 28: // your session has been killed case 31: // your session has been marked for kill case 45: // your session has been terminated with no replay case 378: // buffer pools cannot be created as specified case 602: // internal programming exception case 603: // ORACLE server session terminated by fatal error case 609: // could not attach to incoming connection case 1012: // not logged on case 1041: // internal error. hostdef extension doesn't exist case 1043: // user side memory corruption case 1089: // immediate shutdown or close in progress case 1092: // ORACLE instance terminated. Disconnection forced case 2396: // exceeded maximum idle time, please connect again case 3113: // end-of-file on communication channel case 3114: // not connected to ORACLE case 3122: // attempt to close ORACLE-side window on user side case 3135: // connection lost contact case 12153: // TNS:not connected case 12537: // TNS:connection closed case 12547: // TNS:lost contact case 12570: // TNS:packet reader failure case 12583: // TNS:no reader case 27146: // post/wait initialization failed case 28511: // lost RPC connection case 56600: // an illegal OCI function call was issued conn->deadSession = 1; break; } } // if session is marked as dead, return a unified error message if (conn->deadSession) return dpiError__wrap(error, DPI_ERR_CONN_CLOSED, error->buffer->code); // check for call timeout and return a unified message instead switch (error->buffer->code) { case 3136: // inbound connection timed out case 3156: // OCI call timed out case 12161: // TNS:internal error: partial data received callTimeout = 0; if (conn->env->versionInfo->versionNum >= 18) dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, (void*) &callTimeout, 0, DPI_OCI_ATTR_CALL_TIMEOUT, NULL, error); if (callTimeout > 0) return dpiError__wrap(error, DPI_ERR_CALL_TIMEOUT, callTimeout, error->buffer->code); break; } } return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiError__setFromOS() [INTERNAL] // Set the error buffer to a general OS error. Returns DPI_FAILURE as a // convenience to the caller. //----------------------------------------------------------------------------- int dpiError__setFromOS(dpiError *error, const char *action) { char *message; #ifdef _WIN32 size_t messageLength = 0; message = NULL; if (dpiUtils__getWindowsError(GetLastError(), &message, &messageLength, error) < 0) return DPI_FAILURE; dpiError__set(error, action, DPI_ERR_OS, message); dpiUtils__freeMemory(message); #else char buffer[512]; int err = errno; #if defined(__GLIBC__) || defined(__CYGWIN__) message = strerror_r(err, buffer, sizeof(buffer)); #else message = (strerror_r(err, buffer, sizeof(buffer)) == 0) ? buffer : NULL; #endif if (!message) { (void) sprintf(buffer, "unable to get OS error %d", err); message = buffer; } dpiError__set(error, action, DPI_ERR_OS, message); #endif return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiError__wrap() [INTERNAL] // Set the error buffer to the specified DPI error but retain the error that // was already set and concatenate it to the new error. It is assumed that the // error that is wrapping accepts one argument: the original error number that // was raised. Returns DPI_FAILURE as a convenience to the caller. // ----------------------------------------------------------------------------- int dpiError__wrap(dpiError *error, dpiErrorNum errorNum, ...) { uint32_t origMessageLength; char *origMessage, *ptr; size_t ptrLength; va_list varArgs; // retain copy of original message, if possible origMessageLength = error->buffer->messageLength; origMessage = malloc(origMessageLength); if (origMessage) memcpy(origMessage, error->buffer->message, origMessageLength); // clear original error and set new error error->buffer->code = 0; error->buffer->errorNum = errorNum; va_start(varArgs, errorNum); (void) vsnprintf(error->buffer->message, sizeof(error->buffer->message), dpiErrorMessages[errorNum - DPI_ERR_NO_ERR], varArgs); va_end(varArgs); error->buffer->messageLength = (uint32_t) strlen(error->buffer->message); // concatenate original message to new one (separated by line feed) if (origMessage) { ptr = error->buffer->message + error->buffer->messageLength; ptrLength = sizeof(error->buffer->message) - error->buffer->messageLength; (void) snprintf(ptr, ptrLength, "\n%.*s", origMessageLength, origMessage); free(origMessage); error->buffer->messageLength = (uint32_t) strlen(error->buffer->message); } // log message, if applicable if (dpiDebugLevel & DPI_DEBUG_LEVEL_ERRORS) dpiDebug__print("internal error %.*s (%s / %s)\n", error->buffer->messageLength, error->buffer->message, error->buffer->fnName, error->buffer->action); return DPI_FAILURE; } odpi-5.6.4/src/dpiErrorMessages.h000066400000000000000000000222041510466437300167100ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiErrorMessages.h // Definition of error messages used in ODPI-C. //----------------------------------------------------------------------------- #include "dpiImpl.h" static const char* const dpiErrorMessages[DPI_ERR_MAX - DPI_ERR_NO_ERR] = { "DPI-1000: no error", // DPI_ERR_NO_ERR "DPI-1001: out of memory", // DPI_ERR_NO_MEMORY "DPI-1002: invalid %s handle", // DPI_ERR_INVALID_HANDLE "DPI-1003: OCI error handle is not initialized", // DPI_ERR_ERR_NOT_INITIALIZED "DPI-1004: unable to get error message", // DPI_ERR_GET_FAILED "DPI-1005: unable to acquire Oracle environment handle", // DPI_ERR_CREATE_ENV "DPI-1006: unable to convert text to session character set", // DPI_ERR_CONVERT_TEXT "DPI-1007: no query has been executed", // DPI_ERR_QUERY_NOT_EXECUTED "DPI-1008: data type %d is not supported", // DPI_ERR_UNHANDLED_DATA_TYPE "DPI-1009: zero-based position %u is not valid with max array size of %u", // DPI_ERR_INVALID_ARRAY_POSITION "DPI-1010: not connected", // DPI_ERR_NOT_CONNECTED "DPI-1011: connection was not acquired from a session pool", // DPI_ERR_CONN_NOT_IN_POOL "DPI-1012: proxy authentication is not possible with homogeneous pools", // DPI_ERR_INVALID_PROXY "DPI-1013: not supported", // DPI_ERR_NOT_SUPPORTED "DPI-1014: conversion between Oracle type %d and native type %d is not implemented", // DPI_ERR_UNHANDLED_CONVERSION "DPI-1015: array size of %u is too large", // DPI_ERR_ARRAY_SIZE_TOO_BIG "DPI-1016: invalid date", // DPI_ERR_INVALID_DATE "DPI-1017: value is null", // DPI_ERR_VALUE_IS_NULL "DPI-1018: array size of %u is too small", // DPI_ERR_ARRAY_SIZE_TOO_SMALL "DPI-1019: buffer size of %u is too small", // DPI_ERR_BUFFER_SIZE_TOO_SMALL "DPI-1020: application requires ODPI-C %d (min %d.%d) but is using a shared library at version %d.%d", // DPI_ERR_VERSION_NOT_SUPPORTED "DPI-1021: Oracle type %u is invalid", // DPI_ERR_INVALID_ORACLE_TYPE "DPI-1022: attribute %.*s is not part of object type %.*s.%.*s", // DPI_ERR_WRONG_ATTR "DPI-1023: object %.*s.%.*s is not a collection", // DPI_ERR_NOT_COLLECTION "DPI-1024: element at index %d does not exist", // DPI_ERR_INVALID_INDEX "DPI-1025: no object type specified for object variable", // DPI_ERR_NO_OBJECT_TYPE "DPI-1026: invalid character set %s", // DPI_ERR_INVALID_CHARSET "DPI-1027: scroll operation would go out of the result set", // DPI_ERR_SCROLL_OUT_OF_RS "DPI-1028: query position %u is invalid", // DPI_ERR_QUERY_POSITION_INVALID "DPI-1029: no row currently fetched", // DPI_ERR_NO_ROW_FETCHED "DPI-1030: unable to get or set error structure for thread local storage", // DPI_ERR_TLS_ERROR "DPI-1031: array size cannot be zero", // DPI_ERR_ARRAY_SIZE_ZERO "DPI-1032: user name and password cannot be set when using external authentication", // DPI_ERR_EXT_AUTH_WITH_CREDENTIALS "DPI-1033: unable to get row offset", // DPI_ERR_CANNOT_GET_ROW_OFFSET "DPI-1034: connection created from external handle cannot be closed", // DPI_ERR_CONN_IS_EXTERNAL "DPI-1035: size of the transaction ID is %u and cannot exceed %u", // DPI_ERR_TRANS_ID_TOO_LARGE "DPI-1036: size of the branch ID is %u and cannot exceed %u", // DPI_ERR_BRANCH_ID_TOO_LARGE "DPI-1037: column at array position %u fetched with error %u", // DPI_ERR_COLUMN_FETCH "DPI-1039: statement was already closed", // DPI_ERR_STMT_CLOSED "DPI-1040: LOB was already closed", // DPI_ERR_LOB_CLOSED "DPI-1041: invalid character set id %d", // DPI_ERR_INVALID_CHARSET_ID "DPI-1042: invalid OCI number", // DPI_ERR_INVALID_OCI_NUMBER "DPI-1043: invalid number", // DPI_ERR_INVALID_NUMBER "DPI-1044: value cannot be represented as an Oracle number", // DPI_ERR_NUMBER_NO_REPR "DPI-1045: strings converted to numbers can only be up to 172 characters long", // DPI_ERR_NUMBER_STRING_TOO_LONG "DPI-1046: parameter %s cannot be a NULL pointer", // DPI_ERR_NULL_POINTER_PARAMETER "DPI-1047: Cannot locate a %s-bit Oracle Client library: \"%s\". See %s for help", // DPI_ERR_LOAD_LIBRARY "DPI-1049: symbol %s not found in OCI library", // DPI_ERR_LOAD_SYMBOL "DPI-1050: Oracle Client library is at version %d.%d but version %d.%d or higher is needed", // DPI_ERR_ORACLE_CLIENT_TOO_OLD "DPI-1052: unable to get NLS environment variable", // DPI_ERR_NLS_ENV_VAR_GET, "DPI-1053: parameter %s cannot be a NULL pointer while corresponding length parameter is non-zero", // DPI_ERR_PTR_LENGTH_MISMATCH "DPI-1055: value is not a number (NaN) and cannot be used in Oracle numbers", // DPI_ERR_NAN "DPI-1056: found object of type %.*s.%.*s when expecting object of type %.*s.%.*s", // DPI_ERR_WRONG_TYPE "DPI-1057: buffer size of %u is too large (max %u)", // DPI_ERR_BUFFER_SIZE_TOO_LARGE "DPI-1058: edition not supported with connection class", // DPI_ERR_NO_EDITION_WITH_CONN_CLASS "DPI-1059: bind variables are not supported in DDL statements", // DPI_ERR_NO_BIND_VARS_IN_DDL "DPI-1060: subscription was already closed", // DPI_ERR_SUBSCR_CLOSED "DPI-1061: edition is not supported when a new password is specified", // DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD "DPI-1062: unexpected OCI return value %d in function %s", // DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE "DPI-1063: modes DPI_MODE_EXEC_BATCH_ERRORS and DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS can only be used with insert, update, delete and merge statements", // DPI_ERR_EXEC_MODE_ONLY_FOR_DML "DPI-1064: array variables are not supported with dpiStmt_executeMany()", // DPI_ERR_ARRAY_VAR_NOT_SUPPORTED "DPI-1065: events mode is required to subscribe to events in the database", // DPI_ERR_EVENTS_MODE_REQUIRED "DPI-1066: Oracle Database is at version %d.%d but version %d.%d or higher is needed", // DPI_ERR_ORACLE_DB_TOO_OLD "DPI-1067: call timeout of %u ms exceeded with ORA-%05d", // DPI_ERR_CALL_TIMEOUT "DPI-1068: SODA cursor was already closed", // DPI_ERR_SODA_CURSOR_CLOSED "DPI-1069: proxy user name must be enclosed in [] when using external authentication", // DPI_ERR_EXT_AUTH_INVALID_PROXY "DPI-1070: no payload provided in message properties", // DPI_ERR_QUEUE_NO_PAYLOAD "DPI-1071: payload type in message properties must match the payload type of the queue", // DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE "DPI-1072: the Oracle Client library version is unsupported", // DPI_ERR_ORACLE_CLIENT_UNSUPPORTED "DPI-1073: sharding key is required when specifying a super sharding key", // DPI_ERR_MISSING_SHARDING_KEY "DPI-1074: ODPI-C context not created", // DPI_ERR_CONTEXT_NOT_CREATED "DPI-1075: OS error: %s", // DPI_ERR_OS "DPI-1076: JSON node type %d is not supported", // DPI_ERR_UNHANDLED_JSON_NODE_TYPE "DPI-1077: JSON scalar type %d is not supported", // DPI_ERR_UNHANDLED_JSON_SCALAR_TYPE "DPI-1078: native type %d with Oracle type %d is not supported by JSON", // DPI_ERR_UNHANDLED_CONVERSION_TO_JSON "DPI-1079: Oracle Client library is at version %d.%d but either version %d.%d (or later DBRU) or version %d.%d (or higher) is needed", // DPI_ERR_ORACLE_CLIENT_TOO_OLD_MULTI "DPI-1080: connection was closed by ORA-%05d", // DPI_ERR_CONN_CLOSED "DPI-1081: invalid dpiAccessToken structure. The token must contain a value", // DPI_ERR_TOKEN_BASED_AUTH "DPI-1082: invalid connection pool configuration for token based authentication. Both homogeneous and externalAuth fields in the dpiPoolCreateParams structure must be set to 1", //DPI_ERR_POOL_TOKEN_BASED_AUTH "DPI-1083: invalid standalone connection configuration for token based authentication. The externalAuth field in the dpiConnCreateParams structure must be set to 1", // DPI_ERR_STANDALONE_TOKEN_BASED_AUTH "DPI-1084: unsupported vector format %d", // DPI_ERR_UNSUPPORTED_VECTOR_FORMAT "DPI-1085: SODA document has JSON content. Call dpiJson_getJsonContent() instead.", // DPI_ERR_SODA_DOC_IS_JSON "DPI-1086: SODA document does not have JSON content. Call dpiJson_getContent() instead.", // DPI_ERR_SODA_DOC_IS_NOT_JSON }; odpi-5.6.4/src/dpiGen.c000066400000000000000000000317311510466437300146400ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiGen.c // Generic routines for managing the types available through public APIs. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // definition of handle types //----------------------------------------------------------------------------- static const dpiTypeDef dpiAllTypeDefs[DPI_HTYPE_MAX - DPI_HTYPE_NONE - 1] = { { "dpiConn", // name sizeof(dpiConn), // size of structure 0x49DC600C, // check integer (dpiTypeFreeProc) dpiConn__free }, { "dpiPool", // name sizeof(dpiPool), // size of structure 0x18E1AA4B, // check integer (dpiTypeFreeProc) dpiPool__free }, { "dpiStmt", // name sizeof(dpiStmt), // size of structure 0x31B02B2E, // check integer (dpiTypeFreeProc) dpiStmt__free }, { "dpiVar", // name sizeof(dpiVar), // size of structure 0x2AE8C6DC, // check integer (dpiTypeFreeProc) dpiVar__free }, { "dpiLob", // name sizeof(dpiLob), // size of structure 0xD8F31746, // check integer (dpiTypeFreeProc) dpiLob__free }, { "dpiObject", // name sizeof(dpiObject), // size of structure 0x38616080, // check integer (dpiTypeFreeProc) dpiObject__free }, { "dpiObjectType", // name sizeof(dpiObjectType), // size of structure 0x86036059, // check integer (dpiTypeFreeProc) dpiObjectType__free }, { "dpiObjectAttr", // name sizeof(dpiObjectAttr), // size of structure 0xea6d5dde, // check integer (dpiTypeFreeProc) dpiObjectAttr__free }, { "dpiSubscr", // name sizeof(dpiSubscr), // size of structure 0xa415a1c0, // check integer (dpiTypeFreeProc) dpiSubscr__free }, { "dpiDeqOptions", // name sizeof(dpiDeqOptions), // size of structure 0x70ee498d, // check integer (dpiTypeFreeProc) dpiDeqOptions__free }, { "dpiEnqOptions", // name sizeof(dpiEnqOptions), // size of structure 0x682f3946, // check integer (dpiTypeFreeProc) dpiEnqOptions__free }, { "dpiMsgProps", // name sizeof(dpiMsgProps), // size of structure 0xa2b75506, // check integer (dpiTypeFreeProc) dpiMsgProps__free }, { "dpiRowid", // name sizeof(dpiRowid), // size of structure 0x6204fa04, // check integer (dpiTypeFreeProc) dpiRowid__free }, { "dpiContext", // name sizeof(dpiContext), // size of structure 0xd81b9181, // check integer NULL }, { "dpiSodaColl", // name sizeof(dpiSodaColl), // size of structure 0x3684db22, // check integer (dpiTypeFreeProc) dpiSodaColl__free }, { "dpiSodaCollCursor", // name sizeof(dpiSodaCollCursor), // size of structure 0xcdc73b86, // check integer (dpiTypeFreeProc) dpiSodaCollCursor__free }, { "dpiSodaDb", // name sizeof(dpiSodaDb), // size of structure 0x1f386121, // check integer (dpiTypeFreeProc) dpiSodaDb__free }, { "dpiSodaDoc", // name sizeof(dpiSodaDoc), // size of structure 0xaffd950a, // check integer (dpiTypeFreeProc) dpiSodaDoc__free }, { "dpiSodaDocCursor", // name sizeof(dpiSodaDocCursor), // size of structure 0x80ceb83b, // check integer (dpiTypeFreeProc) dpiSodaDocCursor__free }, { "dpiQueue", // name sizeof(dpiQueue), // size of structure 0x54904ba2, // check integer (dpiTypeFreeProc) dpiQueue__free }, { "dpiJson", // name sizeof(dpiJson), // size of structure 0xf6712bec, // check integer (dpiTypeFreeProc) dpiJson__free }, { "dpiVector", // name sizeof(dpiVector), // size of structure 0x6c3dd6e9, // check integer (dpiTypeFreeProc) dpiVector__free } }; //----------------------------------------------------------------------------- // dpiGen__addRef() [INTERNAL] // Add a reference to the specified handle. //----------------------------------------------------------------------------- int dpiGen__addRef(void *ptr, dpiHandleTypeNum typeNum, const char *fnName) { dpiError error; if (dpiGen__startPublicFn(ptr, typeNum, fnName, &error) < 0) return dpiGen__endPublicFn(ptr, DPI_FAILURE, &error); dpiGen__setRefCount(ptr, &error, 1); return dpiGen__endPublicFn(ptr, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiGen__allocate() [INTERNAL] // Allocate memory for the specified type and initialize the base fields. The // type specified is assumed to be valid. If the environment is specified, use // it; otherwise, create a new one. No additional initialization is performed. //----------------------------------------------------------------------------- int dpiGen__allocate(dpiHandleTypeNum typeNum, dpiEnv *env, void **handle, dpiError *error) { const dpiTypeDef *typeDef; dpiBaseType *value; typeDef = &dpiAllTypeDefs[typeNum - DPI_HTYPE_NONE - 1]; if (dpiUtils__allocateMemory(1, typeDef->size, 1, "allocate handle", (void**) &value, error) < 0) return DPI_FAILURE; value->typeDef = typeDef; value->checkInt = typeDef->checkInt; value->refCount = 1; if (!env && typeNum != DPI_HTYPE_CONTEXT) { if (dpiUtils__allocateMemory(1, sizeof(dpiEnv), 1, "allocate env", (void**) &env, error) < 0) { dpiUtils__freeMemory(value); return DPI_FAILURE; } } value->env = env; if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) dpiDebug__print("ref %p (%s) -> 1 [NEW]\n", value, typeDef->name); *handle = value; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiGen__checkHandle() [INTERNAL] // Check that the specific handle is valid, that it matches the type // requested and that the check integer is still in place. //----------------------------------------------------------------------------- int dpiGen__checkHandle(const void *ptr, dpiHandleTypeNum typeNum, const char *action, dpiError *error) { dpiBaseType *value = (dpiBaseType*) ptr; const dpiTypeDef *typeDef; typeDef = &dpiAllTypeDefs[typeNum - DPI_HTYPE_NONE - 1]; if (!ptr || value->typeDef != typeDef || value->checkInt != typeDef->checkInt) return dpiError__set(error, action, DPI_ERR_INVALID_HANDLE, typeDef->name); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiGen__endPublicFn() [INTERNAL] // This method should be the last call made in any public method using an // ODPI-C handle (other than dpiContext which is handled differently). //----------------------------------------------------------------------------- int dpiGen__endPublicFn(const void *ptr, int returnValue, dpiError *error) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) dpiDebug__print("fn end %s(%p) -> %d\n", error->buffer->fnName, ptr, returnValue); if (error->handle) dpiHandlePool__release(error->env->errorHandles, &error->handle); return returnValue; } //----------------------------------------------------------------------------- // dpiGen__release() [INTERNAL] // Release a reference to the specified handle. If the reference count // reaches zero, the resources associated with the handle are released and // the memory associated with the handle is freed. Any internal references // held to other handles are also released. //----------------------------------------------------------------------------- int dpiGen__release(void *ptr, dpiHandleTypeNum typeNum, const char *fnName) { dpiError error; if (dpiGen__startPublicFn(ptr, typeNum, fnName, &error) < 0) return dpiGen__endPublicFn(ptr, DPI_FAILURE, &error); dpiGen__setRefCount(ptr, &error, -1); return dpiGen__endPublicFn(ptr, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiGen__setRefCount() [INTERNAL] // Increase or decrease the reference count by the given amount. The handle // is assumed to be valid at this point. If the environment is in threaded // mode, acquire the mutex first before making any adjustments to the reference // count. If the operation sets the reference count to zero, release all // resources and free the memory associated with the structure. //----------------------------------------------------------------------------- void dpiGen__setRefCount(void *ptr, dpiError *error, int increment) { dpiBaseType *value = (dpiBaseType*) ptr; unsigned localRefCount; // if threaded need to protect modification of the refCount with a mutex; // also ensure that if the reference count reaches zero that it is // immediately marked invalid in order to avoid race conditions if (value->env->threaded) dpiMutex__acquire(value->env->mutex); value->refCount += increment; localRefCount = value->refCount; if (localRefCount == 0) dpiUtils__clearMemory(&value->checkInt, sizeof(value->checkInt)); if (value->env->threaded) dpiMutex__release(value->env->mutex); // reference count debugging if (dpiDebugLevel & DPI_DEBUG_LEVEL_REFS) dpiDebug__print("ref %p (%s) -> %d\n", ptr, value->typeDef->name, localRefCount); // if the refCount has reached zero, call the free routine if (localRefCount == 0) (*value->typeDef->freeProc)(value, error); } //----------------------------------------------------------------------------- // dpiGen__startPublicFn() [INTERNAL] // This method should be the first call made in any public method using an // ODPI-C handle (other than dpiContext which is handled differently). The // handle is checked for validity and an error handle is acquired for use in // all subsequent calls. //----------------------------------------------------------------------------- int dpiGen__startPublicFn(const void *ptr, dpiHandleTypeNum typeNum, const char *fnName, dpiError *error) { dpiBaseType *value = (dpiBaseType*) ptr; if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) dpiDebug__print("fn start %s(%p)\n", fnName, ptr); if (dpiGlobal__initError(fnName, error) < 0) return DPI_FAILURE; if (dpiGen__checkHandle(ptr, typeNum, "check main handle", error) < 0) return DPI_FAILURE; error->env = value->env; return DPI_SUCCESS; } odpi-5.6.4/src/dpiGlobal.c000066400000000000000000000362301510466437300153260ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiGlobal.c // Global environment used for managing errors in a thread safe manner as // well as for looking up encodings. //----------------------------------------------------------------------------- #include "dpiImpl.h" // cross platform way of defining an initializer that runs at application // startup (similar to what is done for the constructor calls for static C++ // objects) #if defined(_MSC_VER) #pragma section(".CRT$XCU", read) #define DPI_INITIALIZER_HELPER(f, p) \ static void f(void); \ __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \ __pragma(comment(linker,"/include:" p #f "_")) \ static void f(void) #ifdef _WIN64 #define DPI_INITIALIZER(f) DPI_INITIALIZER_HELPER(f, "") #else #define DPI_INITIALIZER(f) DPI_INITIALIZER_HELPER(f, "_") #endif #else #define DPI_INITIALIZER(f) \ static void f(void) __attribute__((constructor)); \ static void f(void) #endif // a global OCI environment is used for managing error buffers in a thread-safe // manner; each thread is given its own error buffer; OCI error handles, // though, must be created within the OCI environment created for use by // standalone connections and session pools static void *dpiGlobalEnvHandle = NULL; static void *dpiGlobalErrorHandle = NULL; static void *dpiGlobalThreadKey = NULL; static dpiErrorBuffer dpiGlobalErrorBuffer; static dpiVersionInfo dpiGlobalClientVersionInfo; static int dpiGlobalInitialized = 0; // a global mutex is used to ensure that only one thread is used to perform // initialization of ODPI-C static dpiMutexType dpiGlobalMutex; // a global null terminated string is retained containing a calculated // configuration directory based on the location of the library that has been // loaded; this is only performed if a configuration directory is not supplied // by the first call that initialized the Oracle Client libraries static char *dpiGlobalConfigDir = NULL; // forward declarations of internal functions only used in this file static int dpiGlobal__extendedInitialize(dpiContextCreateParams *params, const char *fnName, dpiError *error); static void dpiGlobal__finalize(void); static int dpiGlobal__getErrorBuffer(const char *fnName, dpiError *error); //----------------------------------------------------------------------------- // dpiGlobal__ensureInitialized() [INTERNAL] // Ensure that all initializations of the global infrastructure used by // ODPI-C have been performed. This is done by the first thread to execute // this function and includes loading the Oracle Call Interface (OCI) library // and creating a thread key used for managing error buffers in a thread-safe // manner. //----------------------------------------------------------------------------- int dpiGlobal__ensureInitialized(const char *fnName, dpiContextCreateParams *params, dpiVersionInfo **clientVersionInfo, dpiError *error) { // initialize error buffer output to global error buffer structure; this is // the value that is used if an error takes place before the thread local // error structure can be returned error->handle = NULL; error->buffer = &dpiGlobalErrorBuffer; error->buffer->fnName = fnName; // perform global initializations, if needed if (!dpiGlobalInitialized) { dpiMutex__acquire(dpiGlobalMutex); if (!dpiGlobalInitialized) dpiGlobal__extendedInitialize(params, fnName, error); dpiMutex__release(dpiGlobalMutex); if (!dpiGlobalInitialized) return DPI_FAILURE; } *clientVersionInfo = &dpiGlobalClientVersionInfo; return dpiGlobal__getErrorBuffer(fnName, error); } //----------------------------------------------------------------------------- // dpiGlobal__extendedInitialize() [INTERNAL] // Create the global environment used for managing error buffers in a // thread-safe manner. This environment is solely used for implementing thread // local storage for the error buffers and for looking up encodings given an // IANA or Oracle character set name. //----------------------------------------------------------------------------- static int dpiGlobal__extendedInitialize(dpiContextCreateParams *params, const char *fnName, dpiError *error) { int status; // initialize debugging dpiDebug__initialize(); if (dpiDebugLevel & DPI_DEBUG_LEVEL_FNS) dpiDebug__print("fn start %s\n", fnName); // load OCI library if (dpiOci__loadLib(params, &dpiGlobalClientVersionInfo, &dpiGlobalConfigDir, error) < 0) return DPI_FAILURE; // create threaded OCI environment for storing error buffers and for // looking up character sets; use character set AL32UTF8 solely to avoid // the overhead of processing the environment variables; no error messages // from this environment are ever used (ODPI-C specific error messages are // used) if (dpiOci__envNlsCreate(&dpiGlobalEnvHandle, DPI_OCI_THREADED, DPI_CHARSET_ID_UTF8, DPI_CHARSET_ID_UTF8, error) < 0) return DPI_FAILURE; // create global error handle if (dpiOci__handleAlloc(dpiGlobalEnvHandle, &dpiGlobalErrorHandle, DPI_OCI_HTYPE_ERROR, "create global error", error) < 0) { dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); return DPI_FAILURE; } // create global thread key status = dpiOci__threadKeyInit(dpiGlobalEnvHandle, dpiGlobalErrorHandle, &dpiGlobalThreadKey, (void*) dpiUtils__freeMemory, error); if (status < 0) { dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); return DPI_FAILURE; } // mark library as fully initialized dpiGlobalInitialized = 1; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiGlobal__finalize() [INTERNAL] // Called when the process terminates and ensures that everything is cleaned // up. //----------------------------------------------------------------------------- static void dpiGlobal__finalize(void) { void *errorBuffer = NULL; dpiError error; dpiMutex__acquire(dpiGlobalMutex); dpiGlobalInitialized = 0; error.buffer = &dpiGlobalErrorBuffer; if (dpiGlobalThreadKey) { dpiOci__threadKeyGet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, dpiGlobalThreadKey, &errorBuffer, &error); if (errorBuffer) { dpiOci__threadKeySet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, dpiGlobalThreadKey, NULL, &error); dpiUtils__freeMemory(errorBuffer); } dpiOci__threadKeyDestroy(dpiGlobalEnvHandle, dpiGlobalErrorHandle, &dpiGlobalThreadKey, &error); dpiGlobalThreadKey = NULL; } if (dpiGlobalEnvHandle) { dpiOci__handleFree(dpiGlobalEnvHandle, DPI_OCI_HTYPE_ENV); dpiGlobalEnvHandle = NULL; } if (dpiGlobalConfigDir) { free(dpiGlobalConfigDir); dpiGlobalConfigDir = NULL; } dpiMutex__release(dpiGlobalMutex); } //----------------------------------------------------------------------------- // dpiGlobal__getErrorBuffer() [INTERNAL] // Get the thread local error buffer. This will replace use of the global // error buffer which is used until this function has completed successfully. // At this point it is assumed that the global infrastructure has been // initialialized successfully. //----------------------------------------------------------------------------- static int dpiGlobal__getErrorBuffer(const char *fnName, dpiError *error) { dpiErrorBuffer *tempErrorBuffer; // look up the error buffer specific to this thread if (dpiOci__threadKeyGet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, dpiGlobalThreadKey, (void**) &tempErrorBuffer, error) < 0) return DPI_FAILURE; // if NULL, key has never been set for this thread, allocate new error // buffer and set it if (!tempErrorBuffer) { if (dpiUtils__allocateMemory(1, sizeof(dpiErrorBuffer), 1, "allocate error buffer", (void**) &tempErrorBuffer, error) < 0) return DPI_FAILURE; if (dpiOci__threadKeySet(dpiGlobalEnvHandle, dpiGlobalErrorHandle, dpiGlobalThreadKey, tempErrorBuffer, error) < 0) { dpiUtils__freeMemory(tempErrorBuffer); return DPI_FAILURE; } } // if a function name has been specified, clear error // the only time a function name is not specified is for // dpiContext_getError() when the error information is being retrieved if (fnName) { tempErrorBuffer->code = 0; tempErrorBuffer->offset = 0; tempErrorBuffer->errorNum = (dpiErrorNum) 0; tempErrorBuffer->isRecoverable = 0; tempErrorBuffer->messageLength = 0; tempErrorBuffer->fnName = fnName; tempErrorBuffer->action = "start"; tempErrorBuffer->isWarning = 0; strcpy(tempErrorBuffer->encoding, DPI_CHARSET_NAME_UTF8); } error->buffer = tempErrorBuffer; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiGlobal__initError() [INTERNAL] // Get the thread local error structure for use in all other functions. If // an error structure cannot be determined for some reason, the global error // buffer structure is returned instead. //----------------------------------------------------------------------------- int dpiGlobal__initError(const char *fnName, dpiError *error) { // initialize error buffer output to global error buffer structure; this is // the value that is used if an error takes place before the thread local // error structure can be returned error->handle = NULL; error->buffer = &dpiGlobalErrorBuffer; if (fnName) error->buffer->fnName = fnName; // check to see if global environment has been initialized; if not, no call // to dpiContext_createWithParams() was made successfully if (!dpiGlobalInitialized) return dpiError__set(error, "check context creation", DPI_ERR_CONTEXT_NOT_CREATED); // acquire error buffer for the thread, if possible return dpiGlobal__getErrorBuffer(fnName, error); } //----------------------------------------------------------------------------- // dpiGlobal__initialize() [INTERNAL] // Initialization function that runs at process startup or when the library // is first loaded. Some operating systems have limits on what can be run in // this function, so most work is done in the dpiGlobal__extendedInitialize() // function that runs when the first call to dpiContext_createWithParams() is // made. //----------------------------------------------------------------------------- DPI_INITIALIZER(dpiGlobal__initialize) { memset(&dpiGlobalErrorBuffer, 0, sizeof(dpiGlobalErrorBuffer)); strcpy(dpiGlobalErrorBuffer.encoding, DPI_CHARSET_NAME_UTF8); dpiMutex__initialize(dpiGlobalMutex); atexit(dpiGlobal__finalize); } //----------------------------------------------------------------------------- // dpiGlobal__lookupCharSet() [INTERNAL] // Lookup the character set id that can be used in the call to // OCINlsEnvCreate(). //----------------------------------------------------------------------------- int dpiGlobal__lookupCharSet(const char *name, uint16_t *charsetId, dpiError *error) { char oraCharsetName[DPI_OCI_NLS_MAXBUFSZ]; // check for well-known encodings first if (strcmp(name, DPI_CHARSET_NAME_UTF8) == 0) *charsetId = DPI_CHARSET_ID_UTF8; else if (strcmp(name, DPI_CHARSET_NAME_UTF16) == 0) *charsetId = DPI_CHARSET_ID_UTF16; else if (strcmp(name, DPI_CHARSET_NAME_ASCII) == 0) *charsetId = DPI_CHARSET_ID_ASCII; else if (strcmp(name, DPI_CHARSET_NAME_UTF16LE) == 0 || strcmp(name, DPI_CHARSET_NAME_UTF16BE) == 0) return dpiError__set(error, "check encoding", DPI_ERR_NOT_SUPPORTED); // perform lookup; check for the Oracle character set name first and if // that fails, lookup using the IANA character set name else { if (dpiOci__nlsCharSetNameToId(dpiGlobalEnvHandle, name, charsetId, error) < 0) return DPI_FAILURE; if (!*charsetId) { if (dpiOci__nlsNameMap(dpiGlobalEnvHandle, oraCharsetName, sizeof(oraCharsetName), name, DPI_OCI_NLS_CS_IANA_TO_ORA, error) < 0) return dpiError__set(error, "lookup charset", DPI_ERR_INVALID_CHARSET, name); dpiOci__nlsCharSetNameToId(dpiGlobalEnvHandle, oraCharsetName, charsetId, error); } } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiGlobal__lookupEncoding() [INTERNAL] // Get the IANA character set name (encoding) given the Oracle character set // id. //----------------------------------------------------------------------------- int dpiGlobal__lookupEncoding(uint16_t charsetId, char *encoding, dpiError *error) { char oracleName[DPI_OCI_NLS_MAXBUFSZ]; // check for well-known encodings first switch (charsetId) { case DPI_CHARSET_ID_UTF8: strcpy(encoding, DPI_CHARSET_NAME_UTF8); return DPI_SUCCESS; case DPI_CHARSET_ID_UTF16: strcpy(encoding, DPI_CHARSET_NAME_UTF16); return DPI_SUCCESS; case DPI_CHARSET_ID_ASCII: strcpy(encoding, DPI_CHARSET_NAME_ASCII); return DPI_SUCCESS; } // get character set name if (dpiOci__nlsCharSetIdToName(dpiGlobalEnvHandle, oracleName, sizeof(oracleName), charsetId, error) < 0) return dpiError__set(error, "lookup Oracle character set name", DPI_ERR_INVALID_CHARSET_ID, charsetId); // get IANA character set name if (dpiOci__nlsNameMap(dpiGlobalEnvHandle, encoding, DPI_OCI_NLS_MAXBUFSZ, oracleName, DPI_OCI_NLS_CS_ORA_TO_IANA, error) < 0) return dpiError__set(error, "lookup IANA name", DPI_ERR_INVALID_CHARSET_ID, charsetId); return DPI_SUCCESS; } odpi-5.6.4/src/dpiHandleList.c000066400000000000000000000124701510466437300161550ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiHandleList.c // Implementation of a list of handles which are managed in a thread-safe // manner. The references to these handles are assumed to be held by other // structures. No references are held by the list of handles defined here. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiHandleList__addHandle() [INTERNAL] // Add a handle to the list. The list is expanded in sets of 8 handles as // needed. A current position is maintained to reduce the number of scans of // the list are required. An empty slot is designated by a NULL pointer. The // slot number returned is incremented by 1 so that a non-zero slot number is // indicative that the handle was added to the list. //----------------------------------------------------------------------------- int dpiHandleList__addHandle(dpiHandleList *list, void *handle, uint32_t *slotNum, dpiError *error) { uint32_t numSlots, i, actualSlotNum; void **tempHandles; dpiMutex__acquire(list->mutex); if (list->numUsedSlots == list->numSlots) { numSlots = list->numSlots + 8; if (dpiUtils__allocateMemory(numSlots, sizeof(void*), 1, "allocate slots", (void**) &tempHandles, error) < 0) { dpiMutex__release(list->mutex); return DPI_FAILURE; } memcpy(tempHandles, list->handles, list->numSlots * sizeof(void*)); dpiUtils__freeMemory(list->handles); list->handles = tempHandles; list->numSlots = numSlots; actualSlotNum = list->numUsedSlots++; list->currentPos = list->numUsedSlots; } else { for (i = 0; i < list->numSlots; i++) { if (!list->handles[list->currentPos]) break; list->currentPos++; if (list->currentPos == list->numSlots) list->currentPos = 0; } list->numUsedSlots++; actualSlotNum = list->currentPos++; if (list->currentPos == list->numSlots) list->currentPos = 0; } list->handles[actualSlotNum] = handle; dpiMutex__release(list->mutex); *slotNum = actualSlotNum + 1; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiHandleList__create() [INTERNAL] // Create a new (empty) list of handles. //----------------------------------------------------------------------------- int dpiHandleList__create(dpiHandleList **list, dpiError *error) { dpiHandleList *tempList; if (dpiUtils__allocateMemory(1, sizeof(dpiHandleList), 0, "allocate handle list", (void**) &tempList, error) < 0) return DPI_FAILURE; tempList->numSlots = 8; tempList->numUsedSlots = 0; if (dpiUtils__allocateMemory(tempList->numSlots, sizeof(void*), 1, "allocate handle list slots", (void**) &tempList->handles, error) < 0) { dpiUtils__freeMemory(tempList); return DPI_FAILURE; } dpiMutex__initialize(tempList->mutex); tempList->currentPos = 0; *list = tempList; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiHandleList__free() [INTERNAL] // Free the memory associated with the handle list. //----------------------------------------------------------------------------- void dpiHandleList__free(dpiHandleList *list) { if (list->handles) { dpiUtils__freeMemory(list->handles); list->handles = NULL; } dpiMutex__destroy(list->mutex); dpiUtils__freeMemory(list); } //----------------------------------------------------------------------------- // dpiHandleList__removeHandle() [INTERNAL] // Remove the handle at the specified location from the list. //----------------------------------------------------------------------------- void dpiHandleList__removeHandle(dpiHandleList *list, uint32_t slotNum) { if (slotNum > 0) { dpiMutex__acquire(list->mutex); list->handles[slotNum - 1] = NULL; list->numUsedSlots--; dpiMutex__release(list->mutex); } } odpi-5.6.4/src/dpiHandlePool.c000066400000000000000000000124271510466437300161550ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiHandlePool.c // Implementation of a pool of handles which can be acquired and released in // a thread-safe manner. The pool is a circular queue where handles are // acquired from the front and released to the back. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiHandlePool__acquire() [INTERNAL] // Acquire a handle from the pool. If a handle is available, it will be // cleared out of the pool and returned to the caller. It is the caller's // responsibility to return the handle back to the pool when it is finished // with it. If no handle is available, a NULL value is returned. The caller is // expected to create a new handle and return it to the pool when it is // finished with it. //----------------------------------------------------------------------------- int dpiHandlePool__acquire(dpiHandlePool *pool, void **handle, dpiError *error) { void **tempHandles; uint32_t numSlots; dpiMutex__acquire(pool->mutex); if (pool->acquirePos != pool->releasePos) { *handle = pool->handles[pool->acquirePos]; pool->handles[pool->acquirePos++] = NULL; if (pool->acquirePos == pool->numSlots) pool->acquirePos = 0; } else { *handle = NULL; pool->numUsedSlots++; if (pool->numUsedSlots > pool->numSlots) { numSlots = pool->numSlots + 8; if (dpiUtils__allocateMemory(numSlots, sizeof(void*), 1, "allocate slots", (void**) &tempHandles, error) < 0) { dpiMutex__release(pool->mutex); return DPI_FAILURE; } memcpy(tempHandles, pool->handles, pool->numSlots * sizeof(void*)); dpiUtils__freeMemory(pool->handles); pool->handles = tempHandles; pool->numSlots = numSlots; } } dpiMutex__release(pool->mutex); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiHandlePool__create() [INTERNAL] // Create a new handle pool. //----------------------------------------------------------------------------- int dpiHandlePool__create(dpiHandlePool **pool, dpiError *error) { dpiHandlePool *tempPool; if (dpiUtils__allocateMemory(1, sizeof(dpiHandlePool), 0, "allocate handle pool", (void**) &tempPool, error) < 0) return DPI_FAILURE; tempPool->numSlots = 8; tempPool->numUsedSlots = 0; if (dpiUtils__allocateMemory(tempPool->numSlots, sizeof(void*), 1, "allocate handle pool slots", (void**) &tempPool->handles, error) < 0) { dpiUtils__freeMemory(tempPool); return DPI_FAILURE; } dpiMutex__initialize(tempPool->mutex); tempPool->acquirePos = 0; tempPool->releasePos = 0; *pool = tempPool; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiHandlePool__free() [INTERNAL] // Free the memory associated with the error pool. //----------------------------------------------------------------------------- void dpiHandlePool__free(dpiHandlePool *pool) { if (pool->handles) { dpiUtils__freeMemory(pool->handles); pool->handles = NULL; } dpiMutex__destroy(pool->mutex); dpiUtils__freeMemory(pool); } //----------------------------------------------------------------------------- // dpiHandlePool__release() [INTERNAL] // Release a handle back to the pool. No checks are performed on the handle // that is being returned to the pool; It will simply be placed back in the // pool. The handle is then NULLed in order to avoid multiple attempts to // release the handle back to the pool. //----------------------------------------------------------------------------- void dpiHandlePool__release(dpiHandlePool *pool, void **handle) { dpiMutex__acquire(pool->mutex); pool->handles[pool->releasePos++] = *handle; *handle = NULL; if (pool->releasePos == pool->numSlots) pool->releasePos = 0; dpiMutex__release(pool->mutex); } odpi-5.6.4/src/dpiImpl.h000066400000000000000000003344141510466437300150410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiImpl.h // Include file for implementation of ODPI-C library. The definitions in this // file are subject to change without warning. Only the definitions in the file // dpi.h are intended to be used publicly. //----------------------------------------------------------------------------- #ifndef DPI_IMPL #define DPI_IMPL // for gcc, ensure that GNU extensions are enabled so that dladdr() and // dlinfo() are available on platforms like Linux #if defined(__GNUC__) && !defined(_GNU_SOURCE) #define _GNU_SOURCE #endif // Visual Studio 2005 introduced deprecation warnings for "insecure" and POSIX // functions; silence these warnings #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS 1 #endif #include #include #include #include #include #include #include #include #include "dpi.h" #ifdef _WIN32 #include #ifndef isnan #define isnan _isnan #endif #else #include #include #include #include #endif #ifdef __linux #include #include #endif #ifdef _MSC_VER #if _MSC_VER < 1900 #define PRId64 "I64d" #define PRIu64 "I64u" #define snprintf _snprintf #endif #endif #ifndef PRIu64 #include #endif #ifdef __GNUC__ #define UNUSED __attribute((unused)) #else #define UNUSED #endif // define debugging level (defined in dpiGlobal.c) extern unsigned long dpiDebugLevel; // define max error size #define DPI_MAX_ERROR_SIZE 3072 // define context name for ping interval #define DPI_CONTEXT_LAST_TIME_USED "DPI_LAST_TIME_USED" // define context name for server version information #define DPI_CONTEXT_SERVER_VERSION "DPI_SERVER_VERSION" // define size of buffer used for numbers transferred to/from Oracle as text #define DPI_NUMBER_AS_TEXT_CHARS 173 // define maximum number of digits possible in an Oracle number #define DPI_NUMBER_MAX_DIGITS 40 // define maximum size in bytes supported by basic string handling #define DPI_MAX_BASIC_BUFFER_SIZE 32767 // define internal chunk size used for dynamic binding/fetching #define DPI_DYNAMIC_BYTES_CHUNK_SIZE 65536 // define maximum buffer size permitted in variables #define DPI_MAX_VAR_BUFFER_SIZE (1024 * 1024 * 1024 - 2) // define subscription grouping repeat count #define DPI_SUBSCR_GROUPING_FOREVER -1 // define default load error URL #if defined _WIN32 || defined __CYGWIN__ #define DPI_ERR_LOAD_URL_FRAGMENT "#windows" #elif __APPLE__ #define DPI_ERR_LOAD_URL_FRAGMENT "#macos" #elif __linux__ #define DPI_ERR_LOAD_URL_FRAGMENT "#linux" #else #define DPI_ERR_LOAD_URL_FRAGMENT "" #endif #define DPI_DEFAULT_LOAD_ERROR_URL "https://oracle.github.io/odpi/doc/installation.html" DPI_ERR_LOAD_URL_FRAGMENT // define well-known character sets #define DPI_CHARSET_ID_ASCII 1 #define DPI_CHARSET_ID_UTF8 873 #define DPI_CHARSET_ID_UTF16 1000 #define DPI_CHARSET_ID_UTF16BE 2000 #define DPI_CHARSET_ID_UTF16LE 2002 #define DPI_CHARSET_NAME_ASCII "ASCII" #define DPI_CHARSET_NAME_UTF8 "UTF-8" #define DPI_CHARSET_NAME_UTF16 "UTF-16" #define DPI_CHARSET_NAME_UTF16BE "UTF-16BE" #define DPI_CHARSET_NAME_UTF16LE "UTF-16LE" // define handle types used for allocating OCI handles #define DPI_OCI_HTYPE_ENV 1 #define DPI_OCI_HTYPE_ERROR 2 #define DPI_OCI_HTYPE_SVCCTX 3 #define DPI_OCI_HTYPE_STMT 4 #define DPI_OCI_HTYPE_BIND 5 #define DPI_OCI_HTYPE_DEFINE 6 #define DPI_OCI_HTYPE_DESCRIBE 7 #define DPI_OCI_HTYPE_SERVER 8 #define DPI_OCI_HTYPE_SESSION 9 #define DPI_OCI_HTYPE_AUTHINFO 9 #define DPI_OCI_HTYPE_TRANS 10 #define DPI_OCI_HTYPE_SUBSCRIPTION 13 #define DPI_OCI_HTYPE_SPOOL 27 #define DPI_OCI_HTYPE_ADMIN 28 #define DPI_OCI_HTYPE_SODA_COLLECTION 30 #define DPI_OCI_HTYPE_SODA_DOCUMENT 31 #define DPI_OCI_HTYPE_SODA_COLL_CURSOR 32 #define DPI_OCI_HTYPE_SODA_OPER_OPTIONS 33 #define DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS 34 #define DPI_OCI_HTYPE_SODA_DOC_CURSOR 36 // define OCI descriptor types #define DPI_OCI_DTYPE_LOB 50 #define DPI_OCI_DTYPE_PARAM 53 #define DPI_OCI_DTYPE_ROWID 54 #define DPI_OCI_DTYPE_AQENQ_OPTIONS 57 #define DPI_OCI_DTYPE_AQDEQ_OPTIONS 58 #define DPI_OCI_DTYPE_AQMSG_PROPERTIES 59 #define DPI_OCI_DTYPE_AQAGENT 60 #define DPI_OCI_DTYPE_INTERVAL_YM 62 #define DPI_OCI_DTYPE_INTERVAL_DS 63 #define DPI_OCI_DTYPE_AQNFY_DESCRIPTOR 64 #define DPI_OCI_DTYPE_TIMESTAMP 68 #define DPI_OCI_DTYPE_TIMESTAMP_TZ 69 #define DPI_OCI_DTYPE_TIMESTAMP_LTZ 70 #define DPI_OCI_DTYPE_CHDES 77 #define DPI_OCI_DTYPE_TABLE_CHDES 78 #define DPI_OCI_DTYPE_ROW_CHDES 79 #define DPI_OCI_DTYPE_CQDES 80 #define DPI_OCI_DTYPE_SHARDING_KEY 83 #define DPI_OCI_DTYPE_JSON 85 #define DPI_OCI_DTYPE_VECTOR 87 // define values used for getting/setting OCI attributes #define DPI_OCI_ATTR_DATA_SIZE 1 #define DPI_OCI_ATTR_DATA_TYPE 2 #define DPI_OCI_ATTR_ENV 5 #define DPI_OCI_ATTR_PRECISION 5 #define DPI_OCI_ATTR_SCALE 6 #define DPI_OCI_ATTR_NAME 4 #define DPI_OCI_ATTR_SERVER 6 #define DPI_OCI_ATTR_SESSION 7 #define DPI_OCI_ATTR_IS_NULL 7 #define DPI_OCI_ATTR_TRANS 8 #define DPI_OCI_ATTR_TYPE_NAME 8 #define DPI_OCI_ATTR_SCHEMA_NAME 9 #define DPI_OCI_ATTR_ROW_COUNT 9 #define DPI_OCI_ATTR_PREFETCH_ROWS 11 #define DPI_OCI_ATTR_PACKAGE_NAME 12 #define DPI_OCI_ATTR_PARAM_COUNT 18 #define DPI_OCI_ATTR_ROWID 19 #define DPI_OCI_ATTR_USERNAME 22 #define DPI_OCI_ATTR_PASSWORD 23 #define DPI_OCI_ATTR_STMT_TYPE 24 #define DPI_OCI_ATTR_INTERNAL_NAME 25 #define DPI_OCI_ATTR_EXTERNAL_NAME 26 #define DPI_OCI_ATTR_XID 27 #define DPI_OCI_ATTR_TRANS_NAME 29 #define DPI_OCI_ATTR_CHARSET_ID 31 #define DPI_OCI_ATTR_CHARSET_FORM 32 #define DPI_OCI_ATTR_MAXDATA_SIZE 33 #define DPI_OCI_ATTR_ROWS_RETURNED 42 #define DPI_OCI_ATTR_VISIBILITY 47 #define DPI_OCI_ATTR_CONSUMER_NAME 50 #define DPI_OCI_ATTR_DEQ_MODE 51 #define DPI_OCI_ATTR_NAVIGATION 52 #define DPI_OCI_ATTR_WAIT 53 #define DPI_OCI_ATTR_DEQ_MSGID 54 #define DPI_OCI_ATTR_PRIORITY 55 #define DPI_OCI_ATTR_DELAY 56 #define DPI_OCI_ATTR_EXPIRATION 57 #define DPI_OCI_ATTR_CORRELATION 58 #define DPI_OCI_ATTR_ATTEMPTS 59 #define DPI_OCI_ATTR_RECIPIENT_LIST 60 #define DPI_OCI_ATTR_EXCEPTION_QUEUE 61 #define DPI_OCI_ATTR_ENQ_TIME 62 #define DPI_OCI_ATTR_MSG_STATE 63 #define DPI_OCI_ATTR_AGENT_NAME 64 #define DPI_OCI_ATTR_ORIGINAL_MSGID 69 #define DPI_OCI_ATTR_QUEUE_NAME 70 #define DPI_OCI_ATTR_NFY_MSGID 71 #define DPI_OCI_ATTR_NUM_DML_ERRORS 73 #define DPI_OCI_ATTR_DML_ROW_OFFSET 74 #define DPI_OCI_ATTR_SUBSCR_NAME 94 #define DPI_OCI_ATTR_SUBSCR_CALLBACK 95 #define DPI_OCI_ATTR_SUBSCR_CTX 96 #define DPI_OCI_ATTR_SUBSCR_NAMESPACE 98 #define DPI_OCI_ATTR_REF_TDO 110 #define DPI_OCI_ATTR_PARAM 124 #define DPI_OCI_ATTR_PARSE_ERROR_OFFSET 129 #define DPI_OCI_ATTR_SERVER_STATUS 143 #define DPI_OCI_ATTR_STATEMENT 144 #define DPI_OCI_ATTR_DEQCOND 146 #define DPI_OCI_ATTR_SUBSCR_RECPTPROTO 149 #define DPI_OCI_ATTR_CURRENT_POSITION 164 #define DPI_OCI_ATTR_STMTCACHESIZE 176 #define DPI_OCI_ATTR_BIND_COUNT 190 #define DPI_OCI_ATTR_TRANSFORMATION 196 #define DPI_OCI_ATTR_ROWS_FETCHED 197 #define DPI_OCI_ATTR_SPOOL_STMTCACHESIZE 208 #define DPI_OCI_ATTR_TYPECODE 216 #define DPI_OCI_ATTR_STMT_IS_RETURNING 218 #define DPI_OCI_ATTR_CURRENT_SCHEMA 224 #define DPI_OCI_ATTR_SUBSCR_QOSFLAGS 225 #define DPI_OCI_ATTR_COLLECTION_ELEMENT 227 #define DPI_OCI_ATTR_SUBSCR_TIMEOUT 227 #define DPI_OCI_ATTR_NUM_TYPE_ATTRS 228 #define DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS 229 #define DPI_OCI_ATTR_LIST_TYPE_ATTRS 229 #define DPI_OCI_ATTR_SUBSCR_CQ_REGID 230 #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS 231 #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE 232 #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE 233 #define DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT 235 #define DPI_OCI_ATTR_NCHARSET_ID 262 #define DPI_OCI_ATTR_APPCTX_SIZE 273 #define DPI_OCI_ATTR_APPCTX_LIST 274 #define DPI_OCI_ATTR_APPCTX_NAME 275 #define DPI_OCI_ATTR_APPCTX_ATTR 276 #define DPI_OCI_ATTR_APPCTX_VALUE 277 #define DPI_OCI_ATTR_CLIENT_IDENTIFIER 278 #define DPI_OCI_ATTR_CHAR_SIZE 286 #define DPI_OCI_ATTR_EDITION 288 #define DPI_OCI_ATTR_CQ_QUERYID 304 #define DPI_OCI_ATTR_SPOOL_TIMEOUT 308 #define DPI_OCI_ATTR_SPOOL_GETMODE 309 #define DPI_OCI_ATTR_SPOOL_BUSY_COUNT 310 #define DPI_OCI_ATTR_SPOOL_OPEN_COUNT 311 #define DPI_OCI_ATTR_MODULE 366 #define DPI_OCI_ATTR_ACTION 367 #define DPI_OCI_ATTR_CLIENT_INFO 368 #define DPI_OCI_ATTR_ECONTEXT_ID 371 #define DPI_OCI_ATTR_ADMIN_PFILE 389 #define DPI_OCI_ATTR_SUBSCR_PORTNO 390 #define DPI_OCI_ATTR_DBNAME 391 #define DPI_OCI_ATTR_INSTNAME 392 #define DPI_OCI_ATTR_SERVICENAME 393 #define DPI_OCI_ATTR_DBDOMAIN 399 #define DPI_OCI_ATTR_CHNF_ROWIDS 402 #define DPI_OCI_ATTR_CHNF_OPERATIONS 403 #define DPI_OCI_ATTR_CHDES_DBNAME 405 #define DPI_OCI_ATTR_CHDES_NFYTYPE 406 #define DPI_OCI_ATTR_NFY_FLAGS 406 #define DPI_OCI_ATTR_CHDES_XID 407 #define DPI_OCI_ATTR_MSG_DELIVERY_MODE 407 #define DPI_OCI_ATTR_CHDES_TABLE_CHANGES 408 #define DPI_OCI_ATTR_CHDES_TABLE_NAME 409 #define DPI_OCI_ATTR_CHDES_TABLE_OPFLAGS 410 #define DPI_OCI_ATTR_CHDES_TABLE_ROW_CHANGES 411 #define DPI_OCI_ATTR_CHDES_ROW_ROWID 412 #define DPI_OCI_ATTR_CHDES_ROW_OPFLAGS 413 #define DPI_OCI_ATTR_CHNF_REGHANDLE 414 #define DPI_OCI_ATTR_CQDES_OPERATION 422 #define DPI_OCI_ATTR_CQDES_TABLE_CHANGES 423 #define DPI_OCI_ATTR_CQDES_QUERYID 424 #define DPI_OCI_ATTR_DRIVER_NAME 424 #define DPI_OCI_ATTR_CHDES_QUERIES 425 #define DPI_OCI_ATTR_CONNECTION_CLASS 425 #define DPI_OCI_ATTR_PURITY 426 #define DPI_OCI_ATTR_RECEIVE_TIMEOUT 436 #define DPI_OCI_ATTR_LOBPREFETCH_LENGTH 440 #define DPI_OCI_ATTR_SUBSCR_IPADDR 452 #define DPI_OCI_ATTR_UB8_ROW_COUNT 457 #define DPI_OCI_ATTR_SPOOL_AUTH 460 #define DPI_OCI_ATTR_LTXID 462 #define DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY 469 #define DPI_OCI_ATTR_MAX_OPEN_CURSORS 471 #define DPI_OCI_ATTR_ERROR_IS_RECOVERABLE 472 #define DPI_OCI_ATTR_TRANSACTION_IN_PROGRESS 484 #define DPI_OCI_ATTR_DBOP 485 #define DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION 490 #define DPI_OCI_ATTR_BREAK_ON_NET_TIMEOUT 495 #define DPI_OCI_ATTR_SHARDING_KEY 496 #define DPI_OCI_ATTR_SUPER_SHARDING_KEY 497 #define DPI_OCI_ATTR_MAX_IDENTIFIER_LEN 500 #define DPI_OCI_ATTR_FIXUP_CALLBACK 501 #define DPI_OCI_ATTR_SQL_ID 504 #define DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT 506 #define DPI_OCI_ATTR_CALL_TIMEOUT 531 #define DPI_OCI_ATTR_JSON_COL 534 #define DPI_OCI_ATTR_SODA_COLL_NAME 535 #define DPI_OCI_ATTR_SODA_COLL_DESCRIPTOR 536 #define DPI_OCI_ATTR_SODA_CTNT_SQL_TYPE 549 #define DPI_OCI_ATTR_SODA_KEY 563 #define DPI_OCI_ATTR_SODA_LASTMOD_TIMESTAMP 564 #define DPI_OCI_ATTR_SODA_CREATE_TIMESTAMP 565 #define DPI_OCI_ATTR_SODA_VERSION 566 #define DPI_OCI_ATTR_SODA_CONTENT 567 #define DPI_OCI_ATTR_SODA_JSON_CHARSET_ID 568 #define DPI_OCI_ATTR_SODA_DETECT_JSON_ENC 569 #define DPI_OCI_ATTR_SODA_MEDIA_TYPE 571 #define DPI_OCI_ATTR_SODA_CTNT_FORMAT 572 #define DPI_OCI_ATTR_SODA_FETCH_ARRAY_SIZE 573 #define DPI_OCI_ATTR_SODA_FILTER 576 #define DPI_OCI_ATTR_SODA_SKIP 577 #define DPI_OCI_ATTR_SODA_LIMIT 578 #define DPI_OCI_ATTR_SODA_LOCK 579 #define DPI_OCI_ATTR_SODA_DOC_COUNT 593 #define DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD 602 #define DPI_OCI_ATTR_JSON_DOM_MUTABLE 609 #define DPI_OCI_ATTR_OSON_COL 623 #define DPI_OCI_ATTR_SODA_METADATA_CACHE 624 #define DPI_OCI_ATTR_SODA_HINT 627 #define DPI_OCI_ATTR_TOKEN 636 #define DPI_OCI_ATTR_IAM_PRIVKEY 637 #define DPI_OCI_ATTR_TOKEN_CBK 638 #define DPI_OCI_ATTR_TOKEN_CBKCTX 639 #define DPI_OCI_ATTR_PING_INTERVAL 655 #define DPI_OCI_ATTR_TOKEN_ISBEARER 657 #define DPI_OCI_ATTR_DOMAIN_SCHEMA 659 #define DPI_OCI_ATTR_DOMAIN_NAME 660 #define DPI_OCI_ATTR_SODA_JSON_DESC 675 #define DPI_OCI_ATTR_LIST_ANNOTATIONS 686 #define DPI_OCI_ATTR_NUM_ANNOTATIONS 687 #define DPI_OCI_ATTR_ANNOTATION_KEY 688 #define DPI_OCI_ATTR_ANNOTATION_VALUE 689 #define DPI_OCI_ATTR_SERVER_TYPE 694 #define DPI_OCI_ATTR_VECTOR_DIMENSION 695 #define DPI_OCI_ATTR_VECTOR_DATA_FORMAT 696 #define DPI_OCI_ATTR_VECTOR_PROPERTY 697 #define DPI_OCI_ATTR_VECTOR_SPARSE_DIMENSION 717 // define OCI object type constants #define DPI_OCI_OTYPE_NAME 1 #define DPI_OCI_OTYPE_PTR 3 // define OCI data type constants #define DPI_SQLT_CHR 1 #define DPI_SQLT_NUM 2 #define DPI_SQLT_INT 3 #define DPI_SQLT_FLT 4 #define DPI_SQLT_VNU 6 #define DPI_SQLT_PDN 7 #define DPI_SQLT_LNG 8 #define DPI_SQLT_VCS 9 #define DPI_SQLT_DAT 12 #define DPI_SQLT_BFLOAT 21 #define DPI_SQLT_BDOUBLE 22 #define DPI_SQLT_BIN 23 #define DPI_SQLT_LBI 24 #define DPI_SQLT_UIN 68 #define DPI_SQLT_LVB 95 #define DPI_SQLT_AFC 96 #define DPI_SQLT_IBFLOAT 100 #define DPI_SQLT_IBDOUBLE 101 #define DPI_SQLT_RDD 104 #define DPI_SQLT_NTY 108 #define DPI_SQLT_CLOB 112 #define DPI_SQLT_BLOB 113 #define DPI_SQLT_BFILE 114 #define DPI_SQLT_RSET 116 #define DPI_SQLT_JSON 119 #define DPI_SQLT_NCO 122 #define DPI_SQLT_VEC 127 #define DPI_SQLT_ODT 156 #define DPI_SQLT_DATE 184 #define DPI_SQLT_TIMESTAMP 187 #define DPI_SQLT_TIMESTAMP_TZ 188 #define DPI_SQLT_INTERVAL_YM 189 #define DPI_SQLT_INTERVAL_DS 190 #define DPI_SQLT_TIMESTAMP_LTZ 232 #define DPI_OCI_TYPECODE_SMALLINT 246 #define DPI_SQLT_REC 250 #define DPI_SQLT_BOL 252 #define DPI_OCI_TYPECODE_ROWID 262 #define DPI_OCI_TYPECODE_LONG 263 #define DPI_OCI_TYPECODE_LONG_RAW 264 #define DPI_OCI_TYPECODE_BINARY_INTEGER 265 #define DPI_OCI_TYPECODE_PLS_INTEGER 266 // define session pool destroy constants #define DPI_OCI_SPD_FORCE 0x0001 // define session pool creation constants #define DPI_OCI_SPC_REINITIALIZE 0x0001 #define DPI_OCI_SPC_HOMOGENEOUS 0x0002 #define DPI_OCI_SPC_STMTCACHE 0x0004 // define OCI session pool get constants #define DPI_OCI_SESSGET_SPOOL 0x0001 #define DPI_OCI_SESSGET_STMTCACHE 0x0004 #define DPI_OCI_SESSGET_CREDPROXY 0x0008 #define DPI_OCI_SESSGET_CREDEXT 0x0010 #define DPI_OCI_SESSGET_SPOOL_MATCHANY 0x0020 #define DPI_OCI_SESSGET_SYSDBA 0x0100 #define DPI_OCI_SESSGET_MULTIPROPERTY_TAG 0x0400 // define OCI authentication constants #define DPI_OCI_CPW_SYSDBA 0x00000010 #define DPI_OCI_CPW_SYSOPER 0x00000020 #define DPI_OCI_CPW_SYSASM 0x00800040 #define DPI_OCI_CPW_SYSBKP 0x00000080 #define DPI_OCI_CPW_SYSDGD 0x00000100 #define DPI_OCI_CPW_SYSKMT 0x00000200 // define NLS constants #define DPI_OCI_NLS_CS_IANA_TO_ORA 0 #define DPI_OCI_NLS_CS_ORA_TO_IANA 1 #define DPI_OCI_NLS_CHARSET_MAXBYTESZ 91 #define DPI_OCI_NLS_CHARSET_ID 93 #define DPI_OCI_NLS_NCHARSET_ID 94 #define DPI_OCI_NLS_MAXBUFSZ 100 #define DPI_SQLCS_IMPLICIT 1 #define DPI_SQLCS_NCHAR 2 // define XA constants #define DPI_XA_MAXGTRIDSIZE 64 #define DPI_XA_MAXBQUALSIZE 64 #define DPI_XA_XIDDATASIZE 128 // define Sessionless Transaction constants #define DPI_OCI_TRANS_SESSIONLESS 0x10 // Sessionless suspend flags #define DPI_OCI_SUSPEND_DEFAULT 0 #define DPI_OCI_SUSPEND_POST_CALL 0x2 // define null indicator values #define DPI_OCI_IND_NULL -1 #define DPI_OCI_IND_NOTNULL 0 // define subscription QOS values #define DPI_OCI_SUBSCR_QOS_RELIABLE 0x01 #define DPI_OCI_SUBSCR_QOS_PURGE_ON_NTFN 0x10 #define DPI_OCI_SUBSCR_CQ_QOS_QUERY 0x01 #define DPI_OCI_SUBSCR_CQ_QOS_BEST_EFFORT 0x02 // define XDK node type constants #define DPI_JZNDOM_SCALAR 1 #define DPI_JZNDOM_OBJECT 2 #define DPI_JZNDOM_ARRAY 3 // define XDK scalar type constants #define DPI_JZNVAL_NULL 2 #define DPI_JZNVAL_STRING 3 #define DPI_JZNVAL_FALSE 5 #define DPI_JZNVAL_TRUE 6 #define DPI_JZNVAL_FLOAT 11 #define DPI_JZNVAL_DOUBLE 12 #define DPI_JZNVAL_BINARY 13 #define DPI_JZNVAL_ORA_NUMBER 17 #define DPI_JZNVAL_ORA_DATE 18 #define DPI_JZNVAL_ORA_TIMESTAMP 19 #define DPI_JZNVAL_ORA_TIMESTAMPTZ 20 #define DPI_JZNVAL_ORA_YEARMONTH_DUR 21 #define DPI_JZNVAL_ORA_DAYSECOND_DUR 22 #define DPI_JZNVAL_ORA_SIGNED_INT 28 #define DPI_JZNVAL_ORA_SIGNED_LONG 29 #define DPI_JZNVAL_ORA_DECIMAL128 30 #define DPI_JZNVAL_ID 31 #define DPI_JZNVAL_OCI_NUMBER 32 #define DPI_JZNVAL_OCI_DATE 33 #define DPI_JZNVAL_OCI_DATETIME 34 #define DPI_JZNVAL_OCI_INTERVAL 40 #define DPI_JZNVAL_VECTOR 45 // define XDK miscellaneous constants #define DPI_JZN_ALLOW_SCALAR_DOCUMENTS 0x00000080 #define DPI_JZN_INPUT_UTF8 1 // define miscellaneous OCI constants #define DPI_OCI_CONTINUE -24200 #define DPI_OCI_INVALID_HANDLE -2 #define DPI_OCI_ERROR -1 #define DPI_OCI_DEFAULT 0 #define DPI_OCI_SUCCESS 0 #define DPI_OCI_ONE_PIECE 0 #define DPI_OCI_ATTR_PURITY_DEFAULT 0 #define DPI_OCI_NUMBER_UNSIGNED 0 #define DPI_OCI_SUCCESS_WITH_INFO 1 #define DPI_OCI_NTV_SYNTAX 1 #define DPI_OCI_MEMORY_CLEARED 1 #define DPI_OCI_SESSRLS_DROPSESS 1 #define DPI_OCI_SESSRLS_MULTIPROPERTY_TAG 4 #define DPI_OCI_SERVER_NORMAL 1 #define DPI_OCI_TYPEGET_ALL 1 #define DPI_OCI_LOCK_NONE 1 #define DPI_OCI_TEMP_BLOB 1 #define DPI_OCI_CRED_RDBMS 1 #define DPI_OCI_LOB_READONLY 1 #define DPI_OCI_JSON_FORMAT_OSON 1 #define DPI_OCI_TEMP_CLOB 2 #define DPI_OCI_CRED_EXT 2 #define DPI_OCI_LOB_READWRITE 2 #define DPI_OCI_DATA_AT_EXEC 2 #define DPI_OCI_DYNAMIC_FETCH 2 #define DPI_OCI_NUMBER_SIGNED 2 #define DPI_OCI_PIN_ANY 3 #define DPI_OCI_PTYPE_TYPE 6 #define DPI_OCI_AUTH 8 #define DPI_OCI_DURATION_SESSION 10 #define DPI_OCI_NUMBER_SIZE 22 #define DPI_OCI_MAX_VAL_SIZE 22 #define DPI_OCI_NEED_DATA 99 #define DPI_OCI_NO_DATA 100 #define DPI_OCI_ATTR_VECTOR_COL_PROPERTY_IS_SPARSE 0x02 #define DPI_OCI_SRVRELEASE2_CACHED 0x0001 #define DPI_OCI_STRLS_CACHE_DELETE 0x0010 #define DPI_OCI_THREADED 0x00000001 #define DPI_OCI_OBJECT 0x00000002 #define DPI_OCI_SODA_ATOMIC_COMMIT 0x00000001 #define DPI_OCI_SODA_AS_STORED 0x00000002 #define DPI_OCI_SODA_AS_AL32UTF8 0x00000004 #define DPI_OCI_STMT_SCROLLABLE_READONLY 0x00000008 #define DPI_OCI_STMT_CACHE 0x00000040 #define DPI_OCI_SODA_COLL_CREATE_MAP 0x00010000 #define DPI_OCI_SODA_INDEX_DROP_FORCE 0x00010000 #define DPI_OCI_TRANS_TWOPHASE 0x01000000 #define DPI_OCI_SECURE_NOTIFICATION 0x20000000 #define DPI_OCI_BIND_DEDICATED_REF_CURSOR 0x00000400 #define DPI_OCI_PREP2_GET_SQL_ID 0x2000 //----------------------------------------------------------------------------- // Macros //----------------------------------------------------------------------------- #define DPI_CHECK_PTR_NOT_NULL(handle, parameter) \ if (!parameter) { \ dpiError__set(&error, "check parameter " #parameter, \ DPI_ERR_NULL_POINTER_PARAMETER, #parameter); \ return dpiGen__endPublicFn(handle, DPI_FAILURE, &error); \ } #define DPI_CHECK_PTR_AND_LENGTH(handle, parameter) \ if (!parameter && parameter ## Length > 0) { \ dpiError__set(&error, "check parameter " #parameter, \ DPI_ERR_PTR_LENGTH_MISMATCH, #parameter); \ return dpiGen__endPublicFn(handle, DPI_FAILURE, &error); \ } //----------------------------------------------------------------------------- // Enumerations //----------------------------------------------------------------------------- // error numbers typedef enum { DPI_ERR_NO_ERR = 1000, DPI_ERR_NO_MEMORY, DPI_ERR_INVALID_HANDLE, DPI_ERR_ERR_NOT_INITIALIZED, DPI_ERR_GET_FAILED, DPI_ERR_CREATE_ENV, DPI_ERR_CONVERT_TEXT, DPI_ERR_QUERY_NOT_EXECUTED, DPI_ERR_UNHANDLED_DATA_TYPE, DPI_ERR_INVALID_ARRAY_POSITION, DPI_ERR_NOT_CONNECTED, DPI_ERR_CONN_NOT_IN_POOL, DPI_ERR_INVALID_PROXY, DPI_ERR_NOT_SUPPORTED, DPI_ERR_UNHANDLED_CONVERSION, DPI_ERR_ARRAY_SIZE_TOO_BIG, DPI_ERR_INVALID_DATE, DPI_ERR_VALUE_IS_NULL, DPI_ERR_ARRAY_SIZE_TOO_SMALL, DPI_ERR_BUFFER_SIZE_TOO_SMALL, DPI_ERR_VERSION_NOT_SUPPORTED, DPI_ERR_INVALID_ORACLE_TYPE, DPI_ERR_WRONG_ATTR, DPI_ERR_NOT_COLLECTION, DPI_ERR_INVALID_INDEX, DPI_ERR_NO_OBJECT_TYPE, DPI_ERR_INVALID_CHARSET, DPI_ERR_SCROLL_OUT_OF_RS, DPI_ERR_QUERY_POSITION_INVALID, DPI_ERR_NO_ROW_FETCHED, DPI_ERR_TLS_ERROR, DPI_ERR_ARRAY_SIZE_ZERO, DPI_ERR_EXT_AUTH_WITH_CREDENTIALS, DPI_ERR_CANNOT_GET_ROW_OFFSET, DPI_ERR_CONN_IS_EXTERNAL, DPI_ERR_TRANS_ID_TOO_LARGE, DPI_ERR_BRANCH_ID_TOO_LARGE, DPI_ERR_COLUMN_FETCH, DPI_ERR_STMT_CLOSED, DPI_ERR_LOB_CLOSED, DPI_ERR_INVALID_CHARSET_ID, DPI_ERR_INVALID_OCI_NUMBER, DPI_ERR_INVALID_NUMBER, DPI_ERR_NUMBER_NO_REPR, DPI_ERR_NUMBER_STRING_TOO_LONG, DPI_ERR_NULL_POINTER_PARAMETER, DPI_ERR_LOAD_LIBRARY, DPI_ERR_LOAD_SYMBOL, DPI_ERR_ORACLE_CLIENT_TOO_OLD, DPI_ERR_NLS_ENV_VAR_GET, DPI_ERR_PTR_LENGTH_MISMATCH, DPI_ERR_NAN, DPI_ERR_WRONG_TYPE, DPI_ERR_BUFFER_SIZE_TOO_LARGE, DPI_ERR_NO_EDITION_WITH_CONN_CLASS, DPI_ERR_NO_BIND_VARS_IN_DDL, DPI_ERR_SUBSCR_CLOSED, DPI_ERR_NO_EDITION_WITH_NEW_PASSWORD, DPI_ERR_UNEXPECTED_OCI_RETURN_VALUE, DPI_ERR_EXEC_MODE_ONLY_FOR_DML, DPI_ERR_ARRAY_VAR_NOT_SUPPORTED, DPI_ERR_EVENTS_MODE_REQUIRED, DPI_ERR_ORACLE_DB_TOO_OLD, DPI_ERR_CALL_TIMEOUT, DPI_ERR_SODA_CURSOR_CLOSED, DPI_ERR_EXT_AUTH_INVALID_PROXY, DPI_ERR_QUEUE_NO_PAYLOAD, DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE, DPI_ERR_ORACLE_CLIENT_UNSUPPORTED, DPI_ERR_MISSING_SHARDING_KEY, DPI_ERR_CONTEXT_NOT_CREATED, DPI_ERR_OS, DPI_ERR_UNHANDLED_JSON_NODE_TYPE, DPI_ERR_UNHANDLED_JSON_SCALAR_TYPE, DPI_ERR_UNHANDLED_CONVERSION_TO_JSON, DPI_ERR_ORACLE_CLIENT_TOO_OLD_MULTI, DPI_ERR_CONN_CLOSED, DPI_ERR_TOKEN_BASED_AUTH, DPI_ERR_POOL_TOKEN_BASED_AUTH, DPI_ERR_STANDALONE_TOKEN_BASED_AUTH, DPI_ERR_UNSUPPORTED_VECTOR_FORMAT, DPI_ERR_SODA_DOC_IS_JSON, DPI_ERR_SODA_DOC_IS_NOT_JSON, DPI_ERR_MAX } dpiErrorNum; // handle types typedef enum { DPI_HTYPE_NONE = 4000, DPI_HTYPE_CONN, DPI_HTYPE_POOL, DPI_HTYPE_STMT, DPI_HTYPE_VAR, DPI_HTYPE_LOB, DPI_HTYPE_OBJECT, DPI_HTYPE_OBJECT_TYPE, DPI_HTYPE_OBJECT_ATTR, DPI_HTYPE_SUBSCR, DPI_HTYPE_DEQ_OPTIONS, DPI_HTYPE_ENQ_OPTIONS, DPI_HTYPE_MSG_PROPS, DPI_HTYPE_ROWID, DPI_HTYPE_CONTEXT, DPI_HTYPE_SODA_COLL, DPI_HTYPE_SODA_COLL_CURSOR, DPI_HTYPE_SODA_DB, DPI_HTYPE_SODA_DOC, DPI_HTYPE_SODA_DOC_CURSOR, DPI_HTYPE_QUEUE, DPI_HTYPE_JSON, DPI_HTYPE_VECTOR, DPI_HTYPE_MAX } dpiHandleTypeNum; //----------------------------------------------------------------------------- // Mutex definitions //----------------------------------------------------------------------------- #ifdef _WIN32 typedef CRITICAL_SECTION dpiMutexType; #define dpiMutex__initialize(m) InitializeCriticalSection(&m) #define dpiMutex__destroy(m) DeleteCriticalSection(&m) #define dpiMutex__acquire(m) EnterCriticalSection(&m) #define dpiMutex__release(m) LeaveCriticalSection(&m) #else typedef pthread_mutex_t dpiMutexType; #define dpiMutex__initialize(m) pthread_mutex_init(&m, NULL) #define dpiMutex__destroy(m) pthread_mutex_destroy(&m) #define dpiMutex__acquire(m) pthread_mutex_lock(&m) #define dpiMutex__release(m) pthread_mutex_unlock(&m) #endif //----------------------------------------------------------------------------- // old type definitions (to be dropped) //----------------------------------------------------------------------------- // structure used for creating a context typedef struct { const char *defaultDriverName; const char *defaultEncoding; const char *loadErrorUrl; const char *oracleClientLibDir; const char *oracleClientConfigDir; } dpiContextCreateParams__v51; // structure used for transferring error information from ODPI-C typedef struct { int32_t code; uint16_t offset; const char *message; uint32_t messageLength; const char *encoding; const char *fnName; const char *action; const char *sqlState; int isRecoverable; } dpiErrorInfo__v33; // structure used for providing metadata about data types typedef struct { dpiOracleTypeNum oracleTypeNum; dpiNativeTypeNum defaultNativeTypeNum; uint16_t ociTypeCode; uint32_t dbSizeInBytes; uint32_t clientSizeInBytes; uint32_t sizeInChars; int16_t precision; int8_t scale; uint8_t fsPrecision; dpiObjectType *objectType; int isJson; } dpiDataTypeInfo__v50; typedef struct { dpiOracleTypeNum oracleTypeNum; dpiNativeTypeNum defaultNativeTypeNum; uint16_t ociTypeCode; uint32_t dbSizeInBytes; uint32_t clientSizeInBytes; uint32_t sizeInChars; int16_t precision; int8_t scale; uint8_t fsPrecision; dpiObjectType *objectType; int isJson; const char *domainSchema; uint32_t domainSchemaLength; const char *domainName; uint32_t domainNameLength; uint32_t numAnnotations; dpiAnnotation *annotations; } dpiDataTypeInfo__v51; // structure used for transferring query metadata from ODPI-C typedef struct { const char *name; uint32_t nameLength; dpiDataTypeInfo__v50 typeInfo; int nullOk; } dpiQueryInfo__v50; typedef struct { const char *name; uint32_t nameLength; dpiDataTypeInfo__v51 typeInfo; int nullOk; } dpiQueryInfo__v51; //----------------------------------------------------------------------------- // forward declarations for recursive OCI JSON type definitions //----------------------------------------------------------------------------- typedef union dpiJsonOciVal dpiJsonOciVal; typedef struct dpiJznDomDoc dpiJznDomDoc; typedef struct dpiJznDomNameValuePair dpiJznDomNameValuePair; typedef struct dpiJznDomScalar dpiJznDomScalar; //----------------------------------------------------------------------------- // OCI JSON function definitions //----------------------------------------------------------------------------- typedef void* (*dpiJznDom__loadFromInputEventSrc)(dpiJznDomDoc *jdoc, void *evtsrc); typedef void* (*dpiJznDom__loadFromInputOSON)(dpiJznDomDoc *jdoc, void *octbsrc); typedef int (*dpiJznDom__getNodeType)(dpiJznDomDoc *jdoc, void *node); typedef void (*dpiJznDom__getScalarInfo)(dpiJznDomDoc *jdoc, void *nd, dpiJznDomScalar *val); typedef void* (*dpiJznDom__getRootNode)(dpiJznDomDoc *jdoc); typedef uint32_t (*dpiJznDom__getNumObjField)(dpiJznDomDoc *jdoc, void *obj); typedef void* (*dpiJznDom__getFieldVal)(dpiJznDomDoc *jdoc, void *obj, void *nmkey); typedef void* (*dpiJznDom__getFieldByName)(dpiJznDomDoc *jdoc, void *obj, const char *nm, uint16_t nmlen); typedef void (*dpiJznDom__getAllFieldNamesAndVals)(dpiJznDomDoc *jdoc, void *obj, void **nvps); typedef uint32_t (*dpiJznDom__getFieldNamesAndValsBatch)(dpiJznDomDoc *jdoc, void *obj, uint32_t startPos, uint32_t fetchSz, dpiJznDomNameValuePair *nvps); typedef uint32_t (*dpiJznDom__getArraySize)(dpiJznDomDoc *jdoc, void *ary); typedef void* (*dpiJznDom__getArrayElem)(dpiJznDomDoc *jdoc, void *ary, uint32_t index); typedef uint32_t (*dpiJznDom__getArrayElemBatch)(dpiJznDomDoc *jdoc, void *ary, uint32_t startPos, uint32_t fetchSz, void **ndary); typedef void (*dpiJznDom__setRootNode)(dpiJznDomDoc *jdoc, void *root); typedef void (*dpiJznDom__putFieldValue)(dpiJznDomDoc *jdoc, void *obj, const char *name, uint16_t namelen, void *node); typedef int (*dpiJznDom__putItem)(dpiJznDomDoc *jdoc, void *arr, void *node, uint32_t pos); typedef int (*dpiJznDom__appendItem)(dpiJznDomDoc *jdoc, void *arr, void *node); typedef int (*dpiJznDom__replaceItem)(dpiJznDomDoc *jdoc, void *arr, void *node, uint32_t pos); typedef void (*dpiJznDom__deleteField)(dpiJznDomDoc *jdoc, void *obj, void *nmkey); typedef void* (*dpiJznDom__unlinkField)(dpiJznDomDoc *jdoc, void *obj, void *nmkey); typedef int (*dpiJznDom__renameField)(dpiJznDomDoc *jdoc, void *obj, const char *oldName, uint16_t oldNameLen, const char *newName, uint16_t newNameLen); typedef int (*dpiJznDom__deleteItem)(dpiJznDomDoc *jdoc, void *arr, uint32_t idx); typedef void* (*dpiJznDom__unlinkItem)(dpiJznDomDoc *jdoc, void *arr, uint32_t idx); typedef uint32_t (*dpiJznDom__deleteItemBatch)(dpiJznDomDoc *jdoc, void *arr, uint32_t start, uint32_t deleteSz); typedef void* (*dpiJznDom__newObject)(dpiJznDomDoc *jdoc, uint32_t sz); typedef void* (*dpiJznDom__newArray)(dpiJznDomDoc *jdoc, uint32_t sz); typedef void* (*dpiJznDom__newScalar)(dpiJznDomDoc *jdoc, dpiJznDomScalar *val); typedef void (*dpiJznDom__reset)(dpiJznDomDoc *jdoc); typedef void (*dpiJznDom__free)(dpiJznDomDoc *jdoc); typedef void* (*dpiJznDom__getOutputEventSrc)(dpiJznDomDoc *jdoc); typedef int (*dpiJznDom__equals)(dpiJznDomDoc *jdoc1, void *nd1, dpiJznDomDoc *jdoc2, void *nd2); typedef void* (*dpiJznDom__copy)(dpiJznDomDoc *srcdoc, void *srcnode, dpiJznDomDoc *destdoc); typedef void (*dpiJznDom__validFid)(dpiJznDomDoc *jdoc, void *fnms, uint16_t fnmsn); typedef int (*dpiJznDom__storeField)(dpiJznDomDoc *jdoc, const char *fname, uint32_t fnlen, void *name); typedef int (*dpiJznDom__printNode)(dpiJznDomDoc *jdoc, void *node, void *writer); typedef void (*dpiJznDom__visitorFunc)(void *vinfo, void *appctx); typedef void (*dpiJznDom__nodeVisitor)(dpiJznDomDoc *jdoc, void *node, dpiJznDom__visitorFunc func, void *ctx); typedef void* (*dpiJznDom__newScalarVal)(dpiJznDomDoc *jdoc, int typ, ...); typedef void (*dpiJznDom__deleteFieldByName)(dpiJznDomDoc *jdoc, void *obj, const char *name, uint16_t namelen); typedef void *(*dpiJznDom__unlinkFieldByName)(dpiJznDomDoc *jdoc, void *obj, const char *name, uint16_t namelen); typedef int (*dpiJznDom__freeNode)(dpiJznDomDoc *jdoc, void *node); typedef void (*dpiJznDom__getScalarInfoOci)(dpiJznDomDoc *jdoc, void *nd, dpiJznDomScalar *val, dpiJsonOciVal *aux); //----------------------------------------------------------------------------- // OCI type definitions //----------------------------------------------------------------------------- // representation of OCI Number type typedef struct { unsigned char value[DPI_OCI_NUMBER_SIZE]; } dpiOciNumber; // representation of OCI Date type typedef struct { int16_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; } dpiOciDate; // alternative representation of OCI Date type used for sharding typedef struct { uint8_t century; uint8_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; } dpiShardingOciDate; // representation of OCI XID type (two-phase commit) typedef struct { long formatID; long gtrid_length; long bqual_length; char data[DPI_XA_XIDDATASIZE]; } dpiOciXID; // representation of JSON OCI values union dpiJsonOciVal { struct { int16_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; uint32_t fsecond; int8_t tzHourOffset; int8_t tzMinuteOffset; } asJsonDateTime; struct { int32_t days; int32_t hours; int32_t minutes; int32_t seconds; int32_t fseconds; } asJsonDayInterval; struct { int32_t years; int32_t months; } asJsonYearInterval; uint8_t asJsonNumber[DPI_OCI_NUMBER_SIZE]; }; // representation of JSON DOM API typedef struct { dpiJznDom__loadFromInputEventSrc fnLoadFromInputEventSrc; dpiJznDom__loadFromInputOSON fnLoadFromInputOSON; dpiJznDom__getNodeType fnGetNodeType; dpiJznDom__getScalarInfo fnGetScalarInfo; dpiJznDom__getRootNode fnGetRootNode; dpiJznDom__getNumObjField fnGetNumObjField; dpiJznDom__getFieldVal fnGetFieldVal; dpiJznDom__getFieldByName fnGetFieldByName; dpiJznDom__getAllFieldNamesAndVals fnGetAllFieldNamesAndVals; dpiJznDom__getFieldNamesAndValsBatch fnGetFieldNamesAndValsBatch; dpiJznDom__getArraySize fnGetArraySize; dpiJznDom__getArrayElem fnGetArrayElem; dpiJznDom__getArrayElemBatch fnGetArrayElemBatch; dpiJznDom__setRootNode fnSetRootNode; dpiJznDom__putFieldValue fnPutFieldValue; dpiJznDom__putItem fnPutItem; dpiJznDom__appendItem fnAppendItem; dpiJznDom__replaceItem fnReplaceItem; dpiJznDom__deleteField fnDeleteField; dpiJznDom__unlinkField fnUnlinkField; dpiJznDom__renameField fnRenameField; dpiJznDom__deleteItem fnDeleteItem; dpiJznDom__unlinkItem fnUnlinkItem; dpiJznDom__deleteItemBatch fnDeleteItemBatch; dpiJznDom__newObject fnNewObject; dpiJznDom__newArray fnNewArray; dpiJznDom__newScalar fnNewScalar; dpiJznDom__reset fnReset; dpiJznDom__free fnFree; dpiJznDom__getOutputEventSrc fnGetOutputEventSrc; dpiJznDom__equals fnEquals; dpiJznDom__copy fnCopy; dpiJznDom__validFid fnValidFid; dpiJznDom__storeField fnStoreField; dpiJznDom__printNode fnPrintNode; dpiJznDom__nodeVisitor fnNodeVisitor; dpiJznDom__newScalarVal fnNewScalarVal; dpiJznDom__deleteFieldByName fnDeleteFieldByName; dpiJznDom__unlinkFieldByName fnUnlinkFieldByName; dpiJznDom__freeNode fnFreeNode; dpiJznDom__getScalarInfoOci fnGetScalarInfoOci; } dpiJznDomMethods; // representation of JSON DOM struct dpiJznDomDoc { dpiJznDomMethods *methods; void *xmlContext; int errCode; uint32_t modCount; }; // representation of JSON name/value pair struct dpiJznDomNameValuePair { struct { char *ptr; uint32_t length; uint32_t hashId; uint16_t shortId; uint16_t osonId; uint8_t flags; uint8_t hash; uint32_t id; } name; void *value; }; // representation of JSON DOM Scalar Node struct dpiJznDomScalar { int valueType; union { struct { char *value; uint32_t valueLength; } asBytes; struct { float value; } asFloat; struct { double value; } asDouble; struct { uint8_t *value; uint32_t valueLength; } asOciVal; } value; }; //----------------------------------------------------------------------------- // Internal implementation type definitions //----------------------------------------------------------------------------- // used to manage a list of shared handles in a thread-safe manner; currently // used for managing the list of open statements, LOBs and created objects for // a connection (so that they can be closed before the connection itself is // closed); the functions for managing this structure can be found in the file // dpiHandleList.c; empty slots in the array are represented by a NULL handle typedef struct { void **handles; // array of handles managed by list uint32_t numSlots; // length of handles array uint32_t numUsedSlots; // actual number of managed handles uint32_t currentPos; // next position to search dpiMutexType mutex; // enables thread safety } dpiHandleList; // used to manage a pool of shared handles in a thread-safe manner; currently // used for managing the pool of error handles in the dpiEnv structure; the // functions for managing this structure are found in the file dpiHandlePool.c typedef struct { void **handles; // array of handles managed by pool uint32_t numSlots; // length of handles array uint32_t numUsedSlots; // actual number of managed handles uint32_t acquirePos; // position from which to acquire uint32_t releasePos; // position to place released handles dpiMutexType mutex; // enables thread safety } dpiHandlePool; // used to save error information internally; one of these is stored for each // thread using OCIThreadKeyGet() and OCIThreadKeySet() with a globally created // OCI environment handle; it is also used when getting batch error information // with the function dpiStmt_getBatchErrors() typedef struct { int32_t code; // Oracle error code or 0 uint32_t offset; // parse error offset or row offset dpiErrorNum errorNum; // OCPI-C error number const char *fnName; // ODPI-C function name const char *action; // internal action char encoding[DPI_OCI_NLS_MAXBUFSZ]; // encoding (IANA name) char message[DPI_MAX_ERROR_SIZE]; // buffer for storing messages uint32_t messageLength; // length of message in buffer int isRecoverable; // is recoverable? int isWarning; // is a warning? } dpiErrorBuffer; // represents an OCI environment; a pointer to this structure is stored on each // handle exposed publicly but it is created only when a pool is created or // when a standalone connection is created; connections acquired from a pool // shared the same environment as the pool; the functions for manipulating the // environment are found in the file dpiEnv.c; all values are read-only after // initialization of environment is complete typedef struct { const dpiContext *context; // context used to create environment void *handle; // OCI environment handle dpiMutexType mutex; // for reference count (threaded mode) char encoding[DPI_OCI_NLS_MAXBUFSZ]; // CHAR encoding (IANA name) int32_t maxBytesPerCharacter; // max bytes per CHAR character uint16_t charsetId; // CHAR encoding (Oracle charset ID) char nencoding[DPI_OCI_NLS_MAXBUFSZ]; // NCHAR encoding (IANA name) int32_t nmaxBytesPerCharacter; // max bytes per NCHAR character uint16_t ncharsetId; // NCHAR encoding (Oracle charset ID) dpiHandlePool *errorHandles; // pool of OCI error handles dpiVersionInfo *versionInfo; // OCI client version info void *baseDate; // timestamp void *baseDateTZ; // timestamp with time zone void *baseDateLTZ; // timestamp with local time zone int threaded; // threaded mode enabled? int events; // events mode enabled? int externalHandle; // external handle? } dpiEnv; // used to manage all errors that take place in the library; the implementation // for the functions that use this structure are found in dpiError.c; a pointer // to this structure is passed to all internal functions and the first thing // that takes place in every public function is a call to this this error // structure typedef struct { dpiErrorBuffer *buffer; // buffer to store error information void *handle; // OCI error handle or NULL dpiEnv *env; // env which created OCI error handle } dpiError; // function signature for all methods that free publicly exposed handles typedef void (*dpiTypeFreeProc)(void*, dpiError*); // strcture used to provide metadata for the different types of handles exposed // publicly; a list of these structures (defined as constants) can be found in // the file dpiGen.c; the enumeration dpiHandleTypeNum is used to identify the // structures instead of being used directly typedef struct { const char *name; // name (used in error messages) size_t size; // size of structure, in bytes uint32_t checkInt; // check integer (unique) dpiTypeFreeProc freeProc; // procedure to call to free handle } dpiTypeDef; // all structures exposed publicly by handle have these members #define dpiType_HEAD \ const dpiTypeDef *typeDef; \ uint32_t checkInt; \ unsigned refCount; \ dpiEnv *env; // contains the base attributes that all handles exposed publicly have; generic // functions for checking and manipulating handles are found in the file // dpiGen.c; the check integer is used to verify the validity of the handle and // is reset to zero when the handle is freed; the reference count is used to // manage how many references (either publicly or internally) are held; when // the reference count reaches zero the handle is freed typedef struct { dpiType_HEAD } dpiBaseType; // represents the different types of Oracle data that the library supports; an // array of these structures (defined as constants) can be found in the file // dpiOracleType.c; the enumeration dpiOracleTypeNum is used to identify the // structures typedef struct dpiOracleType { dpiOracleTypeNum oracleTypeNum; // enumeration value identifying type dpiNativeTypeNum defaultNativeTypeNum; // default native (C) type uint16_t oracleType; // OCI type code uint8_t charsetForm; // specifies CHAR or NCHAR encoding uint32_t sizeInBytes; // buffer size (fixed) or 0 (variable) int isCharacterData; // is type character data? int canBeInArray; // can type be in an index-by table? int requiresPreFetch; // prefetch processing required? } dpiOracleType; // represents a chunk of data that has been allocated dynamically for use in // dynamic fetching of LONG or LONG RAW columns, or when the calling // application wishes to use strings or raw byte strings instead of LOBs; an // array of these chunks is found in the structure dpiDynamicBytes typedef struct { char *ptr; // pointer to buffer uint32_t length; // actual length of buffer uint32_t allocatedLength; // allocated length of buffer } dpiDynamicBytesChunk; // represents a set of chunks allocated dynamically for use in dynamic fetching // of LONG or LONG RAW columns, or when the calling application wishes to use // strings or raw byte strings instead of LOBS typedef struct { uint32_t numChunks; // actual number of chunks uint32_t allocatedChunks; // allocated number of chunks dpiDynamicBytesChunk *chunks; // array of chunks } dpiDynamicBytes; // represents a single bound variable; an array of these is retained in the // dpiStmt structure in order to retain references to the variables that were // bound to the statement, which ensures that the values remain valid while the // statement is executed; the position is populated for bind by position // (otherwise it is 0) and the name/nameLength are populated for bind by name // (otherwise they are NULL/0) typedef struct { dpiVar *var; uint32_t pos; const char *name; uint32_t nameLength; } dpiBindVar; // intended to avoid the need for casts; contains references to LOBs, objects // and statements (as part of dpiVar) typedef union { void *asHandle; dpiObject *asObject; dpiStmt *asStmt; dpiLob *asLOB; dpiRowid *asRowid; dpiJson *asJson; dpiVector *asVector; } dpiReferenceBuffer; // intended to avoid the need for casts; contains the actual values that are // bound or fetched (as part of dpiVar); it is also used for getting data into // and out of Oracle object instances typedef union { void *asRaw; char *asBytes; float *asFloat; double *asDouble; int32_t *asInt32; int64_t *asInt64; uint64_t *asUint64; dpiOciNumber *asNumber; dpiOciDate *asDate; void **asTimestamp; void **asInterval; void **asJsonDescriptor; void **asLobLocator; void **asString; void **asRawData; void **asStmt; void **asRowid; int *asBoolean; void **asObject; void **asCollection; void **asJson; void **asVectorDescriptor; } dpiOracleData; // intended to avoid the need for casts; contains the memory needed to supply // buffers to Oracle when values are being transferred to or from the Oracle // database typedef union { int32_t asInt32; int64_t asInt64; uint64_t asUint64; float asFloat; double asDouble; uint8_t asOciVal[DPI_OCI_MAX_VAL_SIZE]; dpiOciNumber asNumber; dpiOciDate asDate; int asBoolean; void *asString; void *asRawData; void *asTimestamp; void *asJsonDescriptor; void *asLobLocator; void *asJson; void *asVectorDescriptor; void *asRaw; } dpiOracleDataBuffer; // represents memory areas used for transferring data to and from the database // and is used by the dpiVar structure; most statements only use one buffer, // but DML returning statements can use multiple buffers since multiple rows // can be returned for each execution of the statement typedef struct { uint32_t maxArraySize; // max number of rows in arrays uint32_t actualArraySize; // actual number of rows in arrays int16_t *indicator; // array of indicator values uint16_t *returnCode; // array of return code values uint16_t *actualLength16; // array of actual lengths (11.2 only) uint32_t *actualLength32; // array of actual lengths (12.1+) void **objectIndicator; // array of object indicator values dpiReferenceBuffer *references; // array of references (specific types) dpiDynamicBytes *dynamicBytes; // array of dynamically alloced chunks char *tempBuffer; // buffer for numeric conversion dpiData *externalData; // array of buffers (externally used) dpiOracleData data; // Oracle data buffers (internal only) } dpiVarBuffer; // represents memory areas used for enqueuing and dequeuing messages from // queues typedef struct { uint32_t numElements; // number of elements in next arrays dpiMsgProps **props; // array of dpiMsgProps handles void **handles; // array of OCI msg prop handles void **instances; // array of instances void **indicators; // array of indicator pointers int16_t *scalarIndicators; // array of scalar indicator buffers void **msgIds; // array of OCI message ids } dpiQueueBuffer; //----------------------------------------------------------------------------- // External implementation type definitions //----------------------------------------------------------------------------- // represents session pools and is exposed publicly as a handle of type // DPI_HTYPE_POOL; the implementation for this is found in the file // dpiPool.c struct dpiPool { dpiType_HEAD void *handle; // OCI session pool handle const char *name; // pool name (CHAR encoding) uint32_t nameLength; // length of pool name uint32_t stmtCacheSize; // statement cache size int pingInterval; // interval (seconds) between pings int pingTimeout; // timeout (milliseconds) for ping int homogeneous; // homogeneous pool? int externalAuth; // use external authentication? dpiAccessTokenCallback accessTokenCallback; // access token callback void *accessTokenCallbackContext; // context pointer for callback }; // represents connections to the database and is exposed publicly as a handle // of type DPI_HTYPE_CONN; the implementation for this is found in the file // dpiConn.c; the list of statement, LOB and object handles created by this // connection is maintained and all of these are automatically closed when the // connection itself is closed (in order to avoid memory leaks and segfaults if // the correct order is not observed) struct dpiConn { dpiType_HEAD dpiPool *pool; // pool acquired from or NULL void *handle; // OCI service context handle void *serverHandle; // OCI server handle void *sessionHandle; // OCI session handle void *shardingKey; // OCI sharding key descriptor void *superShardingKey; // OCI supper sharding key descriptor void *transactionHandle; // OCI transaction handle const char *releaseString; // cached release string or NULL uint32_t releaseStringLength; // cached release string length or 0 void *rawTDO; // cached RAW TDO void *jsonTDO; // cached JSON TDO dpiVersionInfo versionInfo; // Oracle database version info dpiConnInfo *info; // cached info about connection uint32_t commitMode; // commit mode (for two-phase commits) uint16_t charsetId; // database character set ID dpiHandleList *openStmts; // list of statements created dpiHandleList *openLobs; // list of LOBs created dpiHandleList *objects; // list of objects created int externalHandle; // OCI handle provided directly? int deadSession; // dead session (drop from pool)? int standalone; // standalone connection (not pooled)? int creating; // connection is being created? int closing; // connection is being closed? }; // represents the context in which all activity in the library takes place; the // implementation for this is found in the file dpiContext.c; the minor // version of the calling application is retained in order to adjust as needed // for differing sizes of public structures struct dpiContext { dpiType_HEAD char *defaultEncoding; // default encoding (nencoding) to use char *defaultDriverName; // default driver name to use dpiVersionInfo *versionInfo; // OCI client version info uint8_t dpiMinorVersion; // ODPI-C minor version of application int sodaUseJsonDesc; // use JSON descriptors in SODA? int useJsonId; // use DPI_ORACLE_TYPE_JSON_ID? }; // represents statements of all types (queries, DML, DDL, PL/SQL) and is // exposed publicly as a handle of type DPI_HTYPE_STMT; the implementation for // this is found in the file dpiStmt.c struct dpiStmt { dpiType_HEAD dpiConn *conn; // connection which created this uint32_t openSlotNum; // slot in connection handle list void *handle; // OCI statement handle dpiStmt *parentStmt; // parent statement (implicit results) uint32_t fetchArraySize; // rows to fetch each time uint32_t bufferRowCount; // number of rows in fetch buffers uint32_t bufferRowIndex; // index into buffers for current row uint32_t numQueryVars; // number of query variables dpiVar **queryVars; // array of query variables dpiQueryInfo *queryInfo; // array of query metadata uint32_t allocatedBindVars; // number of allocated bind variables uint32_t numBindVars; // actual nubmer of bind variables dpiBindVar *bindVars; // array of bind variables uint32_t numBatchErrors; // number of batch errors dpiErrorBuffer *batchErrors; // array of batch errors uint64_t rowCount; // rows affected or rows fetched so far uint64_t bufferMinRow; // row num of first row in buffers uint16_t statementType; // type of statement uint32_t prefetchRows; // rows to prefetch on query execute dpiRowid *lastRowid; // rowid of last affected row int isOwned; // owned by structure? int hasRowsToFetch; // potentially more rows to fetch? int scrollable; // scrollable cursor? int isReturning; // statement has RETURNING clause? int deleteFromCache; // drop from statement cache on close? int closing; // statement is being closed? char sqlId[13]; // SQL_ID (from v$SQL) uint32_t sqlIdLength; // length of the sqlId }; // represents memory areas used for transferring data to and from the database // and is exposed publicly as a handle of type DPI_HTYPE_VAR; the // implementation for this is found in the file dpiVar.c; variables can be // bound to a statement or fetched into by a statement struct dpiVar { dpiType_HEAD dpiConn *conn; // connection which created this const dpiOracleType *type; // type of data contained in variable dpiNativeTypeNum nativeTypeNum; // native (C) type of data int requiresPreFetch; // requires prefetch processing? int isArray; // is an index-by table (array)? uint32_t sizeInBytes; // size in bytes of each row int isDynamic; // dynamically bound or defined? dpiObjectType *objectType; // object type (or NULL) dpiVarBuffer buffer; // main buffer for data dpiVarBuffer *dynBindBuffers; // array of buffers (DML returning) dpiError *error; // error (only for dynamic bind/define) }; // represents JSON values and is exposed publicly as a handle of type // DPI_HTYPE_JSON; the implementation for this is found in the file dpiJson.c struct dpiJson { dpiType_HEAD dpiConn *conn; // connection which created this void *handle; // OCI JSON descriptor dpiJsonNode topNode; // top level node dpiDataBuffer topNodeBuffer; // top level node data buffer char **tempBuffers; // array of temp buffers uint32_t allocatedTempBuffers; // allocated number of temp buffers uint32_t numTempBuffers; // used number of temp buffers uint32_t tempBufferUsed; // used size of current temp buffer void *convTimestamp; // timestamp (for conversions) void *convIntervalDS; // interval DS (for conversions) void *convIntervalYM; // interval YM (for conversions) int handleIsOwned; // handle is owned? }; // represents large objects (CLOB, BLOB, NCLOB and BFILE) and is exposed // publicly as a handle of type DPI_HTYPE_LOB; the implementation for this is // found in the file dpiLob.c struct dpiLob { dpiType_HEAD dpiConn *conn; // connection which created this uint32_t openSlotNum; // slot in connection handle list const dpiOracleType *type; // type of LOB void *locator; // OCI LOB locator descriptor char *buffer; // stores dir alias/name for BFILE int closing; // is LOB being closed? }; // represents object attributes of the types created by the SQL command CREATE // OR REPLACE TYPE and is exposed publicly as a handle of type // DPI_HTYPE_OBJECT_ATTR; the implementation for this is found in the file // dpiObjectAttr.c struct dpiObjectAttr { dpiType_HEAD dpiObjectType *belongsToType; // type attribute belongs to const char *name; // name of attribute (CHAR encoding) uint32_t nameLength; // length of name of attribute dpiDataTypeInfo typeInfo; // attribute data type info }; // represents types created by the SQL command CREATE OR REPLACE TYPE and is // exposed publicly as a handle of type DPI_HTYPE_OBJECT_TYPE; the // implementation for this is found in the file dpiObjectType.c struct dpiObjectType { dpiType_HEAD dpiConn *conn; // connection which created this void *tdo; // OCI type descriptor object uint16_t typeCode; // OCI type code const char *schema; // schema owning type (CHAR encoding) uint32_t schemaLength; // length of schema owning type const char *name; // name of type (CHAR encoding) uint32_t packageNameLength; // length of package name const char *packageName; // package name of type (CHAR ENCODING) uint32_t nameLength; // length of name of type dpiDataTypeInfo elementTypeInfo; // type info of elements of collection int isCollection; // is type a collection? uint16_t numAttributes; // number of attributes type has }; // represents objects of the types created by the SQL command CREATE OR REPLACE // TYPE and is exposed publicly as a handle of type DPI_HTYPE_OBJECT; the // implementation for this is found in the file dpiObject.c struct dpiObject { dpiType_HEAD dpiObjectType *type; // type of object uint32_t openSlotNum; // slot in connection handle list void *instance; // OCI instance void *indicator; // OCI indicator dpiObject *dependsOnObj; // extracted from parent obj, or NULL int freeIndicator; // should indicator be freed? int closing; // is object being closed? }; // represents the unique identifier of a row in Oracle Database and is exposed // publicly as a handle of type DPI_HTYPE_ROWID; the implementation for this is // found in the file dpiRowid.c struct dpiRowid { dpiType_HEAD void *handle; // OCI rowid descriptor char *buffer; // cached string rep (or NULL) uint16_t bufferLength; // length of string rep (or 0) }; // represents a subscription to events such as continuous query notification // (CQN) and object change notification and is exposed publicly as a handle of // type DPI_HTYPE_SUBSCR; the implementation for this is found in the file // dpiSubscr.c struct dpiSubscr { dpiType_HEAD dpiConn *conn; // connection which created this void *handle; // OCI subscription handle dpiMutexType mutex; // enables thread safety dpiSubscrNamespace subscrNamespace; // OCI namespace dpiSubscrQOS qos; // quality of service flags dpiSubscrCallback callback; // callback when event is propagated void *callbackContext; // context pointer for callback int clientInitiated; // client initiated? int registered; // registered with database? }; // represents the available options for dequeueing messages when using advanced // queueing and is exposed publicly as a handle of type DPI_HTYPE_DEQ_OPTIONS; // the implementation for this is found in dpiDeqOptions.c struct dpiDeqOptions { dpiType_HEAD dpiConn *conn; // connection which created this void *handle; // OCI dequeue options handle void *msgIdRaw; // Message ID to be dequeued }; // represents the available options for enqueueing messages when using advanced // queueing and is exposed publicly as a handle of type DPI_HTYPE_ENQ_OPTIONS; // the implementation for this is found in dpiEnqOptions.c struct dpiEnqOptions { dpiType_HEAD dpiConn *conn; // connection which created this void *handle; // OCI enqueue options handle }; // represents the available properties for messages when using advanced queuing // and is exposed publicly as a handle of type DPI_HTYPE_MSG_PROPS; the // implementation for this is found in the file dpiMsgProps.c struct dpiMsgProps { dpiType_HEAD dpiConn *conn; // connection which created this void *handle; // OCI message properties handle dpiObject *payloadObj; // payload (object) void *payloadRaw; // payload (RAW) dpiJson *payloadJson; // payload (JSON) void *msgIdRaw; // message ID (RAW) }; // represents SODA collections and is exposed publicly as a handle of type // DPI_HTYPE_SODA_COLL; the implementation for this is found in the file // dpiSodaColl.c struct dpiSodaColl { dpiType_HEAD dpiSodaDb *db; // database which created this void *handle; // OCI SODA collection handle int binaryContent; // content stored in BLOB? }; // represents cursors that iterate over SODA collections and is exposed // publicly as a handle of type DPI_HTYPE_SODA_COLL_CURSOR; the implementation // for this is found in the file dpiSodaCollCursor.c struct dpiSodaCollCursor { dpiType_HEAD dpiSodaDb *db; // database which created this void *handle; // OCI SODA collection cursor handle }; // represents a SODA database (contains SODA collections) and is exposed // publicly as a handle of type DPI_HTYPE_SODA_DB; the implementation for this // is found in the file dpiSodaDb.c struct dpiSodaDb { dpiType_HEAD dpiConn *conn; // connection which created this }; // represents a SODA document and is exposed publicly as a handle of type // DPI_HTYPE_SODA_DOC; the implementation for this is found in the file // dpiSodaDoc.c struct dpiSodaDoc { dpiType_HEAD dpiSodaDb *db; // database which created this void *handle; // OCI SODA document handle int binaryContent; // binary content? dpiJson *json; // JSON content (only in 23ai+) }; // represents a SODA document cursor and is exposed publicly as a handle of // type DPI_HTYPE_SODA_DOC_CURSOR; the implementation for this is found in the // file dpiSodaDocCursor.c struct dpiSodaDocCursor { dpiType_HEAD dpiSodaColl *coll; // collection which created this void *handle; // OCI SODA document cursor handle }; // represents a queue used in AQ (advanced queuing) and is exposed publicly as // a handle of type DPI_HTYPE_QUEUE; the implementation for this is found in // the file dpiQueue.c struct dpiQueue { dpiType_HEAD dpiConn *conn; // connection which created this const char *name; // name of the queue (NULL-terminated) dpiObjectType *payloadType; // object type (for object payloads) dpiDeqOptions *deqOptions; // dequeue options dpiEnqOptions *enqOptions; // enqueue options dpiQueueBuffer buffer; // buffer area int isJson; // is JSON payload? }; // represents vector values and is exposed publicly as a handle of type // DPI_HTYPE_VECTOR; the implementation for this is found in the file // dpiVector.c struct dpiVector { dpiType_HEAD dpiConn *conn; // connection which created this void *handle; // OCI Vector descriptor uint8_t format; // vector format uint32_t numDimensions; // number of vector dimensions uint32_t numSparseValues; // number of sparse vector values uint8_t dimensionSize; // size of each dimension, in bytes uint32_t *sparseIndices; // array of sparse vector indices void *dimensions; // array of vector dimensions }; //----------------------------------------------------------------------------- // definition of internal dpiContext methods //----------------------------------------------------------------------------- void dpiContext__initCommonCreateParams(const dpiContext *context, dpiCommonCreateParams *params); void dpiContext__initConnCreateParams(dpiConnCreateParams *params); void dpiContext__initPoolCreateParams(dpiPoolCreateParams *params); void dpiContext__initSodaOperOptions(dpiSodaOperOptions *options); void dpiContext__initSubscrCreateParams(dpiSubscrCreateParams *params); //----------------------------------------------------------------------------- // definition of internal dpiDataBuffer methods //----------------------------------------------------------------------------- int dpiDataBuffer__fromOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue); int dpiDataBuffer__fromOracleDateAsDouble(dpiDataBuffer *data, dpiEnv *env, dpiError *error, dpiOciDate *oracleValue); int dpiDataBuffer__fromOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__fromOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__fromOracleNumberAsDouble(dpiDataBuffer *data, dpiError *error, void *oracleValue); int dpiDataBuffer__fromOracleNumberAsInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue); int dpiDataBuffer__fromOracleNumberAsText(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__fromOracleNumberAsUnsignedInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue); int dpiDataBuffer__fromOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue, int withTZ); int dpiDataBuffer__fromOracleTimestampAsDouble(dpiDataBuffer *data, uint32_t dataType, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleDate(dpiDataBuffer *data, dpiOciDate *oracleValue); int dpiDataBuffer__toOracleDateFromDouble(dpiDataBuffer *data, dpiEnv *env, dpiError *error, dpiOciDate *oracleValue); int dpiDataBuffer__toOracleIntervalDS(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleIntervalYM(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleNumberFromDouble(dpiDataBuffer *data, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleNumberFromInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleNumberFromText(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleNumberFromUnsignedInteger(dpiDataBuffer *data, dpiError *error, void *oracleValue); int dpiDataBuffer__toOracleTimestamp(dpiDataBuffer *data, dpiEnv *env, dpiError *error, void *oracleValue, int withTZ); int dpiDataBuffer__toOracleTimestampFromDouble(dpiDataBuffer *data, uint32_t dataType, dpiEnv *env, dpiError *error, void *oracleValue); //----------------------------------------------------------------------------- // definition of internal dpiEnv methods //----------------------------------------------------------------------------- void dpiEnv__free(dpiEnv *env, dpiError *error); int dpiEnv__init(dpiEnv *env, const dpiContext *context, const dpiCommonCreateParams *params, void *externalHandle, dpiCreateMode createMode, dpiError *error); int dpiEnv__getBaseDate(dpiEnv *env, uint32_t dataType, void **baseDate, dpiError *error); int dpiEnv__getEncodingInfo(dpiEnv *env, dpiEncodingInfo *info); //----------------------------------------------------------------------------- // definition of internal dpiError methods //----------------------------------------------------------------------------- int dpiError__getInfo(dpiError *error, dpiErrorInfo *info); int dpiError__initHandle(dpiError *error); int dpiError__set(dpiError *error, const char *context, dpiErrorNum errorNum, ...); int dpiError__setFromOCI(dpiError *error, int status, dpiConn *conn, const char *action); int dpiError__setFromOS(dpiError *error, const char *action); int dpiError__wrap(dpiError *error, dpiErrorNum errorNum, ...); //----------------------------------------------------------------------------- // definition of internal dpiGen methods //----------------------------------------------------------------------------- int dpiGen__addRef(void *ptr, dpiHandleTypeNum typeNum, const char *fnName); int dpiGen__allocate(dpiHandleTypeNum typeNum, dpiEnv *env, void **handle, dpiError *error); int dpiGen__checkHandle(const void *ptr, dpiHandleTypeNum typeNum, const char *context, dpiError *error); int dpiGen__endPublicFn(const void *ptr, int returnValue, dpiError *error); int dpiGen__release(void *ptr, dpiHandleTypeNum typeNum, const char *fnName); void dpiGen__setRefCount(void *ptr, dpiError *error, int increment); int dpiGen__startPublicFn(const void *ptr, dpiHandleTypeNum typeNum, const char *fnName, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiGlobal methods //----------------------------------------------------------------------------- int dpiGlobal__ensureInitialized(const char *fnName, dpiContextCreateParams *params, dpiVersionInfo **clientVersionInfo, dpiError *error); int dpiGlobal__initError(const char *fnName, dpiError *error); int dpiGlobal__lookupCharSet(const char *name, uint16_t *charsetId, dpiError *error); int dpiGlobal__lookupEncoding(uint16_t charsetId, char *encoding, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiOracleType methods //----------------------------------------------------------------------------- const dpiOracleType *dpiOracleType__getFromNum(dpiOracleTypeNum oracleTypeNum, dpiError *error); int dpiOracleType__populateTypeInfo(dpiConn *conn, void *handle, uint32_t handleType, dpiDataTypeInfo *info, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiConn methods //----------------------------------------------------------------------------- int dpiConn__checkConnected(dpiConn *conn, dpiError *error); int dpiConn__create(dpiConn *conn, const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, dpiPool *pool, const dpiCommonCreateParams *commonParams, dpiConnCreateParams *createParams, dpiError *error); int dpiConn__clearTransaction(dpiConn *conn, dpiError *error); void dpiConn__free(dpiConn *conn, dpiError *error); int dpiConn__getJsonTDO(dpiConn *conn, dpiError *error); int dpiConn__getRawTDO(dpiConn *conn, dpiError *error); int dpiConn__getServerVersion(dpiConn *conn, int wantReleaseString, dpiError *error); int dpiConn__suspendSessionlessTransaction(dpiConn *conn, uint32_t flag, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiPool methods //----------------------------------------------------------------------------- int dpiPool__acquireConnection(dpiPool *pool, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, dpiConnCreateParams *params, dpiConn **conn, dpiError *error); void dpiPool__free(dpiPool *pool, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiStmt methods //----------------------------------------------------------------------------- int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt, dpiError *error); int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength, int propagateErrors, dpiError *error); void dpiStmt__free(dpiStmt *stmt, dpiError *error); int dpiStmt__init(dpiStmt *stmt, dpiError *error); int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength, const char *tag, uint32_t tagLength, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiVar methods //----------------------------------------------------------------------------- int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, dpiData **data, dpiError *error); int dpiVar__convertToLob(dpiVar *var, dpiError *error); int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData, dpiError *error); int32_t dpiVar__defineCallback(dpiVar *var, void *defnp, uint32_t iter, void **bufpp, uint32_t **alenpp, uint8_t *piecep, void **indpp, uint16_t **rcodepp); int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer, dpiError *error); void dpiVar__free(dpiVar *var, dpiError *error); int32_t dpiVar__inBindCallback(dpiVar *var, void *bindp, uint32_t iter, uint32_t index, void **bufpp, uint32_t *alenp, uint8_t *piecep, void **indpp); int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, int inFetch, dpiError *error); int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, dpiData *data, dpiError *error); int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, uint32_t iter, uint32_t index, void **bufpp, uint32_t **alenpp, uint8_t *piecep, void **indpp, uint16_t **rcodepp); //----------------------------------------------------------------------------- // definition of internal dpiJson methods //----------------------------------------------------------------------------- int dpiJson__allocate(dpiConn *conn, void *handle, dpiJson **json, dpiError *error); void dpiJson__free(dpiJson *json, dpiError *error); int dpiJson__setValue(dpiJson *json, const dpiJsonNode *topNode, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiLob methods //----------------------------------------------------------------------------- int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob, dpiError *error); int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error); void dpiLob__free(dpiLob *lob, dpiError *error); int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, char *value, uint64_t *valueLength, dpiError *error); int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiObject methods //----------------------------------------------------------------------------- int dpiObject__allocate(dpiObjectType *objType, void *instance, void *indicator, dpiObject *dependsOnObj, dpiObject **obj, dpiError *error); int dpiObject__close(dpiObject *obj, int propagateErrors, dpiError *error); void dpiObject__free(dpiObject *obj, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiObjectType methods //----------------------------------------------------------------------------- int dpiObjectType__allocate(dpiConn *conn, void *handle, uint32_t handleType, dpiObjectType **objType, dpiError *error); void dpiObjectType__free(dpiObjectType *objType, dpiError *error); int dpiObjectType__isXmlType(dpiObjectType *objType); //----------------------------------------------------------------------------- // definition of internal dpiObjectAttr methods //----------------------------------------------------------------------------- int dpiObjectAttr__allocate(dpiObjectType *objType, void *param, dpiObjectAttr **attr, dpiError *error); int dpiObjectAttr__check(dpiObjectAttr *attr, dpiError *error); void dpiObjectAttr__free(dpiObjectAttr *attr, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiRowid methods //----------------------------------------------------------------------------- int dpiRowid__allocate(dpiConn *conn, dpiRowid **rowid, dpiError *error); void dpiRowid__free(dpiRowid *rowid, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiSubscr methods //----------------------------------------------------------------------------- void dpiSubscr__free(dpiSubscr *subscr, dpiError *error); int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn, dpiSubscrCreateParams *params, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiDeqOptions methods //----------------------------------------------------------------------------- int dpiDeqOptions__create(dpiDeqOptions *options, dpiConn *conn, dpiError *error); void dpiDeqOptions__free(dpiDeqOptions *options, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiEnqOptions methods //----------------------------------------------------------------------------- int dpiEnqOptions__create(dpiEnqOptions *options, dpiConn *conn, dpiError *error); void dpiEnqOptions__free(dpiEnqOptions *options, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiSodaColl methods //----------------------------------------------------------------------------- int dpiSodaColl__allocate(dpiSodaDb *db, void *handle, dpiSodaColl **coll, dpiError *error); void dpiSodaColl__free(dpiSodaColl *coll, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiSodaCollCursor methods //----------------------------------------------------------------------------- int dpiSodaCollCursor__allocate(dpiSodaDb *db, void *handle, dpiSodaCollCursor **cursor, dpiError *error); void dpiSodaCollCursor__free(dpiSodaCollCursor *cursor, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiSodaDb methods //----------------------------------------------------------------------------- void dpiSodaDb__free(dpiSodaDb *db, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiSodaDoc methods //----------------------------------------------------------------------------- int dpiSodaDoc__allocate(dpiSodaDb *db, void *handle, dpiSodaDoc **doc, dpiError *error); void dpiSodaDoc__free(dpiSodaDoc *doc, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiSodaDocCursor methods //----------------------------------------------------------------------------- int dpiSodaDocCursor__allocate(dpiSodaColl *coll, void *handle, dpiSodaDocCursor **cursor, dpiError *error); void dpiSodaDocCursor__free(dpiSodaDocCursor *cursor, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiQueue methods //----------------------------------------------------------------------------- int dpiQueue__allocate(dpiConn *conn, const char *name, uint32_t nameLength, dpiObjectType *payloadType, dpiQueue **queue, int isJson, dpiError *error); void dpiQueue__free(dpiQueue *queue, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiVector methods //----------------------------------------------------------------------------- int dpiVector__allocate(dpiConn *conn, dpiVector **vector, dpiError *error); void dpiVector__free(dpiVector *vector, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiOci methods //----------------------------------------------------------------------------- int dpiOci__aqDeq(dpiConn *conn, const char *queueName, void *options, void *msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error); int dpiOci__aqDeqArray(dpiConn *conn, const char *queueName, void *options, uint32_t *numIters, void **msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error); int dpiOci__aqEnq(dpiConn *conn, const char *queueName, void *options, void *msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error); int dpiOci__aqEnqArray(dpiConn *conn, const char *queueName, void *options, uint32_t *numIters, void **msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error); int dpiOci__arrayDescriptorAlloc(void *envHandle, void **handle, uint32_t handleType, uint32_t arraySize, dpiError *error); int dpiOci__arrayDescriptorFree(void **handle, uint32_t handleType); int dpiOci__attrGet(const void *handle, uint32_t handleType, void *ptr, uint32_t *size, uint32_t attribute, const char *action, dpiError *error); int dpiOci__attrSet(void *handle, uint32_t handleType, void *ptr, uint32_t size, uint32_t attribute, const char *action, dpiError *error); int dpiOci__bindByName(dpiStmt *stmt, void **bindHandle, const char *name, int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error); int dpiOci__bindByName2(dpiStmt *stmt, void **bindHandle, const char *name, int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error); int dpiOci__bindByPos(dpiStmt *stmt, void **bindHandle, uint32_t pos, int dynamicBind, dpiVar *var, dpiError *error); int dpiOci__bindByPos2(dpiStmt *stmt, void **bindHandle, uint32_t pos, int dynamicBind, dpiVar *var, dpiError *error); int dpiOci__bindDynamic(dpiVar *var, void *bindHandle, dpiError *error); int dpiOci__bindObject(dpiVar *var, void *bindHandle, dpiError *error); int dpiOci__break(dpiConn *conn, dpiError *error); int dpiOci__collAppend(dpiConn *conn, const void *elem, const void *elemInd, void *coll, dpiError *error); int dpiOci__collAssignElem(dpiConn *conn, int32_t index, const void *elem, const void *elemInd, void *coll, dpiError *error); int dpiOci__collGetElem(dpiConn *conn, void *coll, int32_t index, int *exists, void **elem, void **elemInd, dpiError *error); int dpiOci__collSize(dpiConn *conn, void *coll, int32_t *size, dpiError *error); int dpiOci__collTrim(dpiConn *conn, uint32_t numToTrim, void *coll, dpiError *error); int dpiOci__contextGetValue(dpiConn *conn, const char *key, uint32_t keyLength, void **value, int checkError, dpiError *error); int dpiOci__contextSetValue(dpiConn *conn, const char *key, uint32_t keyLength, void *value, int checkError, dpiError *error); int dpiOci__dateTimeConstruct(void *envHandle, void *handle, int16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t fsecond, const char *tz, size_t tzLength, dpiError *error); int dpiOci__dateTimeConvert(void *envHandle, void *inDate, void *outDate, dpiError *error); int dpiOci__dateTimeGetDate(void *envHandle, void *handle, int16_t *year, uint8_t *month, uint8_t *day, dpiError *error); int dpiOci__dateTimeGetTime(void *envHandle, void *handle, uint8_t *hour, uint8_t *minute, uint8_t *second, uint32_t *fsecond, dpiError *error); int dpiOci__dateTimeGetTimeZoneOffset(void *envHandle, void *handle, int8_t *tzHourOffset, int8_t *tzMinuteOffset, dpiError *error); int dpiOci__dateTimeIntervalAdd(void *envHandle, void *handle, void *interval, void *outHandle, dpiError *error); int dpiOci__dateTimeSubtract(void *envHandle, void *handle1, void *handle2, void *interval, dpiError *error); int dpiOci__dbShutdown(dpiConn *conn, uint32_t mode, dpiError *error); int dpiOci__dbStartup(dpiConn *conn, void *adminHandle, uint32_t mode, dpiError *error); int dpiOci__defineByPos(dpiStmt *stmt, void **defineHandle, uint32_t pos, dpiVar *var, dpiError *error); int dpiOci__defineByPos2(dpiStmt *stmt, void **defineHandle, uint32_t pos, dpiVar *var, dpiError *error); int dpiOci__defineDynamic(dpiVar *var, void *defineHandle, dpiError *error); int dpiOci__defineObject(dpiVar *var, void *defineHandle, dpiError *error); int dpiOci__describeAny(dpiConn *conn, void *obj, uint32_t objLength, uint8_t objType, void *describeHandle, dpiError *error); int dpiOci__descriptorAlloc(void *envHandle, void **handle, const uint32_t handleType, const char *action, dpiError *error); int dpiOci__descriptorFree(void *handle, uint32_t handleType); int dpiOci__envNlsCreate(void **envHandle, uint32_t mode, uint16_t charsetId, uint16_t ncharsetId, dpiError *error); int dpiOci__errorGet(void *handle, uint32_t handleType, uint16_t charsetId, const char *action, dpiError *error); int dpiOci__handleAlloc(void *envHandle, void **handle, uint32_t handleType, const char *action, dpiError *error); int dpiOci__handleFree(void *handle, uint32_t handleType); int dpiOci__intervalGetDaySecond(void *envHandle, int32_t *day, int32_t *hour, int32_t *minute, int32_t *second, int32_t *fsecond, const void *interval, dpiError *error); int dpiOci__intervalGetYearMonth(void *envHandle, int32_t *year, int32_t *month, const void *interval, dpiError *error); int dpiOci__intervalSetDaySecond(void *envHandle, int32_t day, int32_t hour, int32_t minute, int32_t second, int32_t fsecond, void *interval, dpiError *error); int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month, void *interval, dpiError *error); int dpiOci__jsonDomDocGet(dpiJson *json, dpiJznDomDoc **domDoc, dpiError *error); int dpiOci__jsonTextBufferParse(dpiJson *json, const char *value, uint64_t valueLength, uint32_t flags, dpiError *error); int dpiOci__loadLib(dpiContextCreateParams *params, dpiVersionInfo *clientVersionInfo, char **configDir, dpiError *error); int dpiOci__lobClose(dpiLob *lob, dpiError *error); int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error); int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error); int dpiOci__lobFileGetName(dpiLob *lob, char *dirAlias, uint16_t *dirAliasLength, char *name, uint16_t *nameLength, dpiError *error); int dpiOci__lobFileSetName(dpiLob *lob, const char *dirAlias, uint16_t dirAliasLength, const char *name, uint16_t nameLength, dpiError *error); int dpiOci__lobFreeTemporary(dpiConn *conn, void *lobLocator, int checkError, dpiError *error); int dpiOci__lobGetChunkSize(dpiLob *lob, uint32_t *size, dpiError *error); int dpiOci__lobGetLength2(dpiLob *lob, uint64_t *size, dpiError *error); int dpiOci__lobIsOpen(dpiLob *lob, int *isOpen, dpiError *error); int dpiOci__lobIsTemporary(dpiLob *lob, int *isTemporary, int checkError, dpiError *error); int dpiOci__lobLocatorAssign(dpiLob *lob, void **copiedHandle, dpiError *error); int dpiOci__lobOpen(dpiLob *lob, dpiError *error); int dpiOci__lobRead2(dpiLob *lob, uint64_t offset, uint64_t *amountInBytes, uint64_t *amountInChars, char *buffer, uint64_t bufferLength, dpiError *error); int dpiOci__lobTrim2(dpiLob *lob, uint64_t newLength, dpiError *error); int dpiOci__lobWrite2(dpiLob *lob, uint64_t offset, const char *value, uint64_t valueLength, dpiError *error); int dpiOci__memoryAlloc(dpiConn *conn, void **ptr, uint32_t size, int checkError, dpiError *error); int dpiOci__memoryFree(dpiConn *conn, void *ptr, dpiError *error); int dpiOci__nlsCharSetConvert(void *envHandle, uint16_t destCharsetId, char *dest, size_t destLength, uint16_t sourceCharsetId, const char *source, size_t sourceLength, size_t *resultSize, dpiError *error); int dpiOci__nlsCharSetIdToName(void *envHandle, char *buf, size_t bufLength, uint16_t charsetId, dpiError *error); int dpiOci__nlsCharSetNameToId(void *envHandle, const char *name, uint16_t *charsetId, dpiError *error); int dpiOci__nlsEnvironmentVariableGet(uint16_t item, void *value, dpiError *error); int dpiOci__nlsNameMap(void *envHandle, char *buf, size_t bufLength, const char *source, uint32_t flag, dpiError *error); int dpiOci__nlsNumericInfoGet(void *envHandle, int32_t *value, uint16_t item, dpiError *error); int dpiOci__numberFromInt(const void *value, unsigned int valueLength, unsigned int flags, void *number, dpiError *error); int dpiOci__numberFromReal(const double value, void *number, dpiError *error); int dpiOci__numberToInt(void *number, void *value, unsigned int valueLength, unsigned int flags, dpiError *error); int dpiOci__numberToReal(double *value, void *number, dpiError *error); int dpiOci__objectCopy(dpiObject *obj, void *sourceInstance, void *sourceIndicator, dpiError *error); int dpiOci__objectFree(void *envHandle, void *data, int checkError, dpiError *error); int dpiOci__objectGetAttr(dpiObject *obj, dpiObjectAttr *attr, int16_t *scalarValueIndicator, void **valueIndicator, void **value, void **tdo, dpiError *error); int dpiOci__objectGetInd(dpiObject *obj, dpiError *error); int dpiOci__objectNew(dpiObject *obj, dpiError *error); int dpiOci__objectPin(void *envHandle, void *objRef, void **obj, dpiError *error); int dpiOci__objectSetAttr(dpiObject *obj, dpiObjectAttr *attr, int16_t scalarValueIndicator, void *valueIndicator, const void *value, dpiError *error); int dpiOci__paramGet(const void *handle, uint32_t handleType, void **parameter, uint32_t pos, const char *action, dpiError *error); int dpiOci__passwordChange(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *oldPassword, uint32_t oldPasswordLength, const char *newPassword, uint32_t newPasswordLength, uint32_t mode, dpiError *error); int dpiOci__ping(dpiConn *conn, dpiError *error); int dpiOci__rawAssignBytes(void *envHandle, const char *value, uint32_t valueLength, void **handle, dpiError *error); int dpiOci__rawPtr(void *envHandle, void *handle, void **ptr); int dpiOci__rawResize(void *envHandle, void **handle, uint32_t newSize, dpiError *error); int dpiOci__rawSize(void *envHandle, void *handle, uint32_t *size); int dpiOci__rowidToChar(dpiRowid *rowid, char *buffer, uint16_t *bufferSize, dpiError *error); int dpiOci__serverAttach(dpiConn *conn, const char *connectString, uint32_t connectStringLength, dpiError *error); int dpiOci__serverDetach(dpiConn *conn, int checkError, dpiError *error); int dpiOci__serverRelease(dpiConn *conn, char *buffer, uint32_t bufferSize, uint32_t *version, uint32_t mode, dpiError *error); int dpiOci__sessionBegin(dpiConn *conn, uint32_t credentialType, uint32_t mode, dpiError *error); int dpiOci__sessionEnd(dpiConn *conn, int checkError, dpiError *error); int dpiOci__sessionGet(void *envHandle, void **handle, void *authInfo, const char *connectString, uint32_t connectStringLength, const char *tag, uint32_t tagLength, const char **outTag, uint32_t *outTagLength, int *found, uint32_t mode, dpiError *error); int dpiOci__sessionPoolCreate(dpiPool *pool, const char *connectString, uint32_t connectStringLength, uint32_t minSessions, uint32_t maxSessions, uint32_t sessionIncrement, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, uint32_t mode, dpiError *error); int dpiOci__sessionPoolDestroy(dpiPool *pool, uint32_t mode, int checkError, dpiError *error); int dpiOci__sessionRelease(dpiConn *conn, const char *tag, uint32_t tagLength, uint32_t mode, int checkError, dpiError *error); int dpiOci__shardingKeyColumnAdd(void *shardingKey, void *col, uint32_t colLen, uint16_t colType, dpiError *error); int dpiOci__sodaBulkInsert(dpiSodaColl *coll, void **documents, uint32_t numDocuments, void *outputOptions, uint32_t mode, dpiError *error); int dpiOci__sodaBulkInsertAndGet(dpiSodaColl *coll, void **documents, uint32_t numDocuments, void *outputOptions, uint32_t mode, dpiError *error); int dpiOci__sodaBulkInsertAndGetWithOpts(dpiSodaColl *coll, void **documents, uint32_t numDocuments, void *operOptions, void *outputOptions, uint32_t mode, dpiError *error); int dpiOci__sodaCollCreateWithMetadata(dpiSodaDb *db, const char *name, uint32_t nameLength, const char *metadata, uint32_t metadataLength, uint32_t mode, void **handle, dpiError *error); int dpiOci__sodaCollDrop(dpiSodaColl *coll, int *isDropped, uint32_t mode, dpiError *error); int dpiOci__sodaCollGetNext(dpiConn *conn, void *cursorHandle, void **collectionHandle, dpiError *error); int dpiOci__sodaCollList(dpiSodaDb *db, const char *startingName, uint32_t startingNameLength, void **handle, uint32_t mode, dpiError *error); int dpiOci__sodaCollOpen(dpiSodaDb *db, const char *name, uint32_t nameLength, uint32_t mode, void **handle, dpiError *error); int dpiOci__sodaCollTruncate(dpiSodaColl *coll, dpiError *error); int dpiOci__sodaDataGuideGet(dpiSodaColl *coll, void **handle, uint32_t mode, dpiError *error); int dpiOci__sodaDocCount(dpiSodaColl *coll, void *options, uint32_t mode, uint64_t *count, dpiError *error); int dpiOci__sodaDocGetNext(dpiSodaDocCursor *cursor, void **handle, dpiError *error); int dpiOci__sodaFind(dpiSodaColl *coll, const void *options, uint32_t flags, uint32_t mode, void **handle, dpiError *error); int dpiOci__sodaFindOne(dpiSodaColl *coll, const void *options, uint32_t flags, uint32_t mode, void **handle, dpiError *error); int dpiOci__sodaIndexCreate(dpiSodaColl *coll, const char *indexSpec, uint32_t indexSpecLength, uint32_t mode, dpiError *error); int dpiOci__sodaIndexDrop(dpiSodaColl *coll, const char *name, uint32_t nameLength, uint32_t mode, int *isDropped, dpiError *error); int dpiOci__sodaIndexList(dpiSodaColl *coll, uint32_t flags, void **handle, dpiError *error); int dpiOci__sodaInsert(dpiSodaColl *coll, void *handle, uint32_t mode, dpiError *error); int dpiOci__sodaInsertAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, dpiError *error); int dpiOci__sodaInsertAndGetWithOpts(dpiSodaColl *coll, void **handle, void *operOptions, uint32_t mode, dpiError *error); int dpiOci__sodaOperKeysSet(const dpiSodaOperOptions *options, void *handle, dpiError *error); int dpiOci__sodaRemove(dpiSodaColl *coll, void *options, uint32_t mode, uint64_t *count, dpiError *error); int dpiOci__sodaReplOne(dpiSodaColl *coll, const void *options, void *handle, uint32_t mode, int *isReplaced, dpiError *error); int dpiOci__sodaReplOneAndGet(dpiSodaColl *coll, const void *options, void **handle, uint32_t mode, int *isReplaced, dpiError *error); int dpiOci__sodaSave(dpiSodaColl *coll, void *handle, uint32_t mode, dpiError *error); int dpiOci__sodaSaveAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, dpiError *error); int dpiOci__sodaSaveAndGetWithOpts(dpiSodaColl *coll, void **handle, void *operOptions, uint32_t mode, dpiError *error); int dpiOci__stmtExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, dpiError *error); int dpiOci__stmtFetch2(dpiStmt *stmt, uint32_t numRows, uint16_t fetchMode, int32_t offset, dpiError *error); int dpiOci__stmtGetBindInfo(dpiStmt *stmt, uint32_t size, uint32_t startLoc, int32_t *numFound, char *names[], uint8_t nameLengths[], char *indNames[], uint8_t indNameLengths[], uint8_t isDuplicate[], void *bindHandles[], dpiError *error); int dpiOci__stmtGetNextResult(dpiStmt *stmt, void **handle, dpiError *error); int dpiOci__stmtPrepare2(dpiStmt *stmt, const char *sql, uint32_t sqlLength, const char *tag, uint32_t tagLength, dpiError *error); int dpiOci__stmtRelease(dpiStmt *stmt, const char *tag, uint32_t tagLength, int checkError, dpiError *error); int dpiOci__stringAssignText(void *envHandle, const char *value, uint32_t valueLength, void **handle, dpiError *error); int dpiOci__stringPtr(void *envHandle, void *handle, char **ptr); int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize, dpiError *error); int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size); int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, uint32_t mode, dpiError *error); int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr, dpiError *error); int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error); int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists, dpiError *error); int dpiOci__tableFirst(dpiObject *obj, int32_t *index, dpiError *error); int dpiOci__tableLast(dpiObject *obj, int32_t *index, dpiError *error); int dpiOci__tableNext(dpiObject *obj, int32_t index, int32_t *nextIndex, int *exists, dpiError *error); int dpiOci__tablePrev(dpiObject *obj, int32_t index, int32_t *prevIndex, int *exists, dpiError *error); int dpiOci__tableSize(dpiObject *obj, int32_t *size, dpiError *error); int dpiOci__threadKeyDestroy(void *envHandle, void *errorHandle, void **key, dpiError *error); int dpiOci__threadKeyGet(void *envHandle, void *errorHandle, void *key, void **value, dpiError *error); int dpiOci__threadKeyInit(void *envHandle, void *errorHandle, void **key, void *destroyFunc, dpiError *error); int dpiOci__threadKeySet(void *envHandle, void *errorHandle, void *key, void *value, dpiError *error); int dpiOci__transCommit(dpiConn *conn, uint32_t flags, dpiError *error); int dpiOci__transDetach(dpiConn *conn, uint32_t flags, dpiError *error); int dpiOci__transForget(dpiConn *conn, dpiError *error); int dpiOci__transPrepare(dpiConn *conn, int *commitNeeded, dpiError *error); int dpiOci__transRollback(dpiConn *conn, int checkError, dpiError *error); int dpiOci__transStart(dpiConn *conn, uint32_t transactionTimeout, uint32_t flags, dpiError *error); int dpiOci__typeByFullName(dpiConn *conn, const char *name, uint32_t nameLength, void **tdo, dpiError *error); int dpiOci__typeByName(dpiConn *conn, const char *schema, uint32_t schemaLength, const char *name, uint32_t nameLength, void **tdo, dpiError *error); int dpiOci__vectorFromArray(dpiVector *vector, dpiVectorInfo *info, dpiError *error); int dpiOci__vectorFromSparseArray(dpiVector *vector, dpiVectorInfo *info, dpiError *error); int dpiOci__vectorToArray(dpiVector *vector, dpiError *error); int dpiOci__vectorToSparseArray(dpiVector *vector, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiMsgProps methods //----------------------------------------------------------------------------- int dpiMsgProps__allocate(dpiConn *conn, dpiMsgProps **props, dpiError *error); void dpiMsgProps__extractMsgId(dpiMsgProps *props, const char **msgId, uint32_t *msgIdLength); void dpiMsgProps__free(dpiMsgProps *props, dpiError *error); int dpiMsgProps__setRecipients(dpiMsgProps *props, dpiMsgRecipient *recipients, uint32_t numRecipients, void **aqAgents, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiHandlePool methods //----------------------------------------------------------------------------- int dpiHandlePool__acquire(dpiHandlePool *pool, void **handle, dpiError *error); int dpiHandlePool__create(dpiHandlePool **pool, dpiError *error); void dpiHandlePool__free(dpiHandlePool *pool); void dpiHandlePool__release(dpiHandlePool *pool, void **handle); //----------------------------------------------------------------------------- // definition of internal dpiHandleList methods //----------------------------------------------------------------------------- int dpiHandleList__addHandle(dpiHandleList *list, void *handle, uint32_t *slotNum, dpiError *error); int dpiHandleList__create(dpiHandleList **list, dpiError *error); void dpiHandleList__free(dpiHandleList *list); void dpiHandleList__removeHandle(dpiHandleList *list, uint32_t slotNum); //----------------------------------------------------------------------------- // definition of internal dpiStringList methods //----------------------------------------------------------------------------- void dpiStringList__free(dpiStringList *list); int dpiStringList__addElement(dpiStringList *list, const char *value, uint32_t valueLength, uint32_t *numStringsAllocated, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiUtils methods //----------------------------------------------------------------------------- int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize, int clearMemory, const char *action, void **ptr, dpiError *error); int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo, int minVersionNum, int minReleaseNum, dpiError *error); int dpiUtils__checkClientVersionMulti(dpiVersionInfo *versionInfo, int minVersionNum1, int minReleaseNum1, int minVersionNum2, int minReleaseNum2, dpiError *error); int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum, int minReleaseNum, dpiError *error); void dpiUtils__clearMemory(void *ptr, size_t length); int dpiUtils__ensureBuffer(size_t desiredSize, const char *action, void **ptr, size_t *currentSize, dpiError *error); int dpiUtils__getTransactionHandle(dpiConn *conn, void **transactionHandle, dpiError *error); void dpiUtils__freeMemory(void *ptr); int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle, uint32_t ociHandleType, uint32_t ociAttribute, const char **value, uint32_t *valueLength, dpiError *error); #ifdef _WIN32 int dpiUtils__getWindowsError(DWORD errorNum, char **buffer, size_t *bufferLength, dpiError *error); #endif int dpiUtils__parseNumberString(const char *value, uint32_t valueLength, uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, dpiError *error); int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative, int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, dpiError *error); int dpiUtils__setAttributesFromCommonCreateParams(void *handle, uint32_t handleType, const dpiCommonCreateParams *params, dpiError *error); int dpiUtils__setAccessTokenAttributes(void *handle, dpiAccessToken *accessToken, dpiVersionInfo *versionInfo, dpiError *error); //----------------------------------------------------------------------------- // definition of internal dpiDebug methods //----------------------------------------------------------------------------- void dpiDebug__initialize(void); void dpiDebug__print(const char *format, ...); #endif odpi-5.6.4/src/dpiJson.c000066400000000000000000001105341510466437300150370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2020, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiJson.c // Implementation of JSON manipulation routines. //----------------------------------------------------------------------------- #include "dpiImpl.h" // define number of nodes which are processed in each batch #define DPI_JSON_BATCH_NODES 64 // define batch size of space allocated for temporary buffers used for // converting numbers to text #define DPI_JSON_TEMP_BUFFER_SIZE 1024 // forward declarations of internal functions only used in this file static int dpiJsonNode__fromOracleArrayToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error); static int dpiJsonNode__fromOracleObjectToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error); static int dpiJsonNode__fromOracleScalarToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error); static int dpiJsonNode__fromOracleToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error); static int dpiJsonNode__toOracleFromNative(dpiJson *json, const dpiJsonNode *node, dpiJznDomDoc *domDoc, void **oracleNode, dpiError *error); //----------------------------------------------------------------------------- // dpiJson__allocate() [INTERNAL] // Allocate and initialize a JSON object. //----------------------------------------------------------------------------- int dpiJson__allocate(dpiConn *conn, void *handle, dpiJson **json, dpiError *error) { dpiJson *tempJson; if (dpiUtils__checkClientVersion(conn->env->versionInfo, 21, 0, error) < 0) return DPI_FAILURE; if (dpiGen__allocate(DPI_HTYPE_JSON, conn->env, (void**) &tempJson, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempJson->conn = conn; if (handle) { tempJson->handle = handle; } else { if (dpiOci__descriptorAlloc(conn->env->handle, &tempJson->handle, DPI_OCI_DTYPE_JSON, "allocate JSON descriptor", error) < 0) { dpiJson__free(tempJson, error); return DPI_FAILURE; } tempJson->handleIsOwned = 1; } tempJson->topNode.value = &tempJson->topNodeBuffer; tempJson->topNode.oracleTypeNum = DPI_ORACLE_TYPE_NONE; tempJson->topNode.nativeTypeNum = DPI_NATIVE_TYPE_NULL; *json = tempJson; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiJsonNode__fromOracleArrayToNative() [INTERNAL] // Populate an array node from the Oracle JSON node. //----------------------------------------------------------------------------- static int dpiJsonNode__fromOracleArrayToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error) { void *oracleElementNodes[DPI_JSON_BATCH_NODES]; uint32_t pos, i, numInBatch; dpiJsonNode *elementNode; dpiJsonArray *array; // define node types node->oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; node->nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; // determine number of elements in the array; if no elements exist in the // array, nothing further needs to be done at this point array = &node->value->asJsonArray; array->numElements = (*domDoc->methods->fnGetArraySize)(domDoc, oracleNode); if (array->numElements == 0) return DPI_SUCCESS; // allocate memory if (dpiUtils__allocateMemory(array->numElements, sizeof(dpiJsonNode), 1, "allocate JSON array element nodes", (void**) &array->elements, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(array->numElements, sizeof(dpiDataBuffer), 1, "allocate JSON array element values", (void**) &array->elementValues, error) < 0) return DPI_FAILURE; // process all of the nodes in the array in batches pos = 0; while (pos < array->numElements) { numInBatch = (*domDoc->methods->fnGetArrayElemBatch)(domDoc, oracleNode, pos, DPI_JSON_BATCH_NODES, oracleElementNodes); for (i = 0; i < numInBatch; i++) { elementNode = &array->elements[pos + i]; elementNode->value = &array->elementValues[pos + i]; if (dpiJsonNode__fromOracleToNative(json, elementNode, domDoc, oracleElementNodes[i], options, error) < 0) return DPI_FAILURE; } pos += numInBatch; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiJsonNode__fromOracleObjectToNative() [INTERNAL] // Populate an object node from the Oracle JSON node. //----------------------------------------------------------------------------- static int dpiJsonNode__fromOracleObjectToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error) { dpiJznDomNameValuePair nameValuePairs[DPI_JSON_BATCH_NODES]; uint32_t pos, i, numInBatch; dpiJsonNode *fieldNode; dpiJsonObject *obj; // define node types node->oracleTypeNum = DPI_ORACLE_TYPE_JSON_OBJECT; node->nativeTypeNum = DPI_NATIVE_TYPE_JSON_OBJECT; // determine number of fields in the object; if no fields exist in the // object, nothing further needs to be done at this point obj = &node->value->asJsonObject; obj->numFields = (*domDoc->methods->fnGetNumObjField)(domDoc, oracleNode); if (obj->numFields == 0) return DPI_SUCCESS; // allocate memory if (dpiUtils__allocateMemory(obj->numFields, sizeof(char*), 1, "allocate JSON object field names", (void**) &obj->fieldNames, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(obj->numFields, sizeof(uint32_t), 1, "allocate JSON object field name lengths", (void**) &obj->fieldNameLengths, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(obj->numFields, sizeof(dpiJsonNode), 1, "allocate JSON object field nodes", (void**) &obj->fields, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(obj->numFields, sizeof(dpiDataBuffer), 1, "allocate JSON object field values", (void**) &obj->fieldValues, error) < 0) return DPI_FAILURE; // process all of the nodes in the object in batches pos = 0; while (pos < obj->numFields) { numInBatch = (*domDoc->methods->fnGetFieldNamesAndValsBatch)(domDoc, oracleNode, pos, DPI_JSON_BATCH_NODES, nameValuePairs); for (i = 0; i < numInBatch; i++) { obj->fieldNames[pos + i] = nameValuePairs[i].name.ptr; obj->fieldNameLengths[pos + i] = nameValuePairs[i].name.length; fieldNode = &obj->fields[pos + i]; fieldNode->value = &obj->fieldValues[pos + i]; if (dpiJsonNode__fromOracleToNative(json, fieldNode, domDoc, nameValuePairs[i].value, options, error) < 0) return DPI_FAILURE; } pos += numInBatch; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiJsonNode__fromOracleNumberAsText() [INTERNAL] // Populate a scalar number as a text buffer. Temporary buffers are allocated // as needed and an array of these are stored in the JSON object. Each // temporary buffer contains as many numbers as can be fit before a new // temporary buffer is allocated. //----------------------------------------------------------------------------- static int dpiJsonNode__fromOracleNumberAsText(dpiJson *json, dpiJsonNode *node, uint8_t *numBuffer, dpiError *error) { char **tempBuffers; // if there is no room in the current temporary buffer, allocate a new one if (json->tempBufferUsed + DPI_NUMBER_AS_TEXT_CHARS < DPI_JSON_TEMP_BUFFER_SIZE) { // if no room is available in the temp buffer array, increase the size // of the array if (json->numTempBuffers == json->allocatedTempBuffers) { json->allocatedTempBuffers += 16; if (dpiUtils__allocateMemory(json->allocatedTempBuffers, sizeof(char*), 0, "allocate JSON temp buffer array", (void**) &tempBuffers, error) < 0) return DPI_FAILURE; if (json->numTempBuffers > 0) { memcpy(tempBuffers, json->tempBuffers, json->numTempBuffers * sizeof(char*)); dpiUtils__freeMemory(json->tempBuffers); } json->tempBuffers = tempBuffers; } // allocate a new temporary buffer if (dpiUtils__allocateMemory(1, DPI_JSON_TEMP_BUFFER_SIZE, 0, "allocate JSON temp buffer", (void**) &json->tempBuffers[json->numTempBuffers], error) < 0) return DPI_FAILURE; json->numTempBuffers++; json->tempBufferUsed = 0; } // perform the conversion node->value->asBytes.ptr = json->tempBuffers[json->numTempBuffers - 1] + json->tempBufferUsed; node->value->asBytes.length = DPI_NUMBER_AS_TEXT_CHARS; return dpiDataBuffer__fromOracleNumberAsText(node->value, json->env, error, numBuffer); } //----------------------------------------------------------------------------- // dpiJsonNode__fromOracleScalarToNative() [INTERNAL] // Populate a scalar node from the Oracle JSON node. //----------------------------------------------------------------------------- static int dpiJsonNode__fromOracleScalarToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error) { dpiJznDomScalar scalar; dpiJsonOciVal ociVal; (*domDoc->methods->fnGetScalarInfoOci)(domDoc, oracleNode, &scalar, &ociVal); switch (scalar.valueType) { case DPI_JZNVAL_STRING: node->oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; node->nativeTypeNum = DPI_NATIVE_TYPE_BYTES; node->value->asBytes.ptr = scalar.value.asBytes.value; node->value->asBytes.length = scalar.value.asBytes.valueLength; return DPI_SUCCESS; case DPI_JZNVAL_BINARY: node->oracleTypeNum = DPI_ORACLE_TYPE_RAW; node->nativeTypeNum = DPI_NATIVE_TYPE_BYTES; node->value->asBytes.ptr = scalar.value.asBytes.value; node->value->asBytes.length = scalar.value.asBytes.valueLength; return DPI_SUCCESS; case DPI_JZNVAL_ID: node->oracleTypeNum = (json->env->context->useJsonId) ? DPI_ORACLE_TYPE_JSON_ID : DPI_ORACLE_TYPE_RAW; node->nativeTypeNum = DPI_NATIVE_TYPE_BYTES; node->value->asBytes.ptr = scalar.value.asBytes.value; node->value->asBytes.length = scalar.value.asBytes.valueLength; return DPI_SUCCESS; case DPI_JZNVAL_FLOAT: node->oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; node->nativeTypeNum = DPI_NATIVE_TYPE_FLOAT; node->value->asFloat = scalar.value.asFloat.value; return DPI_SUCCESS; case DPI_JZNVAL_DOUBLE: node->oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; node->nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; node->value->asDouble = scalar.value.asDouble.value; return DPI_SUCCESS; case DPI_JZNVAL_ORA_SIGNED_INT: case DPI_JZNVAL_ORA_SIGNED_LONG: case DPI_JZNVAL_ORA_DECIMAL128: case DPI_JZNVAL_ORA_NUMBER: if (scalar.valueType != DPI_JZNVAL_ORA_NUMBER) { ociVal.asJsonNumber[0] = (uint8_t) scalar.value.asOciVal.valueLength; memcpy(&ociVal.asJsonNumber[1], scalar.value.asOciVal.value, scalar.value.asOciVal.valueLength); } node->oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; if (options & DPI_JSON_OPT_NUMBER_AS_STRING) { node->nativeTypeNum = DPI_NATIVE_TYPE_BYTES; return dpiJsonNode__fromOracleNumberAsText(json, node, ociVal.asJsonNumber, error); } node->nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; return dpiDataBuffer__fromOracleNumberAsDouble(node->value, error, ociVal.asJsonNumber); case DPI_JZNVAL_ORA_DATE: case DPI_JZNVAL_ORA_TIMESTAMP: case DPI_JZNVAL_ORA_TIMESTAMPTZ: node->oracleTypeNum = (scalar.valueType == DPI_JZNVAL_ORA_DATE) ? DPI_ORACLE_TYPE_DATE : DPI_ORACLE_TYPE_TIMESTAMP; if (options & DPI_JSON_OPT_DATE_AS_DOUBLE) { node->nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; if (dpiDataBuffer__fromOracleDateAsDouble(node->value, json->env, error, (dpiOciDate*) &ociVal.asJsonDateTime) < 0) return DPI_FAILURE; node->value->asDouble += (ociVal.asJsonDateTime.fsecond / 1000000); return DPI_SUCCESS; } node->nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; node->value->asTimestamp.year = ociVal.asJsonDateTime.year; node->value->asTimestamp.month = ociVal.asJsonDateTime.month; node->value->asTimestamp.day = ociVal.asJsonDateTime.day; node->value->asTimestamp.hour = ociVal.asJsonDateTime.hour; node->value->asTimestamp.minute = ociVal.asJsonDateTime.minute; node->value->asTimestamp.second = ociVal.asJsonDateTime.second; node->value->asTimestamp.fsecond = ociVal.asJsonDateTime.fsecond; node->value->asTimestamp.tzHourOffset = ociVal.asJsonDateTime.tzHourOffset; node->value->asTimestamp.tzMinuteOffset = ociVal.asJsonDateTime.tzMinuteOffset; return DPI_SUCCESS; case DPI_JZNVAL_ORA_DAYSECOND_DUR: node->oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_DS; node->nativeTypeNum = DPI_NATIVE_TYPE_INTERVAL_DS; node->value->asIntervalDS.days = ociVal.asJsonDayInterval.days; node->value->asIntervalDS.hours = ociVal.asJsonDayInterval.hours; node->value->asIntervalDS.minutes = ociVal.asJsonDayInterval.minutes; node->value->asIntervalDS.seconds = ociVal.asJsonDayInterval.seconds; node->value->asIntervalDS.fseconds = ociVal.asJsonDayInterval.fseconds; return DPI_SUCCESS; case DPI_JZNVAL_ORA_YEARMONTH_DUR: node->oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_YM; node->nativeTypeNum = DPI_NATIVE_TYPE_INTERVAL_YM; node->value->asIntervalYM.years = ociVal.asJsonYearInterval.years; node->value->asIntervalYM.months = ociVal.asJsonYearInterval.months; return DPI_SUCCESS; case DPI_JZNVAL_FALSE: case DPI_JZNVAL_TRUE: node->oracleTypeNum = DPI_ORACLE_TYPE_BOOLEAN; node->nativeTypeNum = DPI_NATIVE_TYPE_BOOLEAN; node->value->asBoolean = (scalar.valueType == DPI_JZNVAL_TRUE); return DPI_SUCCESS; case DPI_JZNVAL_NULL: node->oracleTypeNum = DPI_ORACLE_TYPE_NONE; node->nativeTypeNum = DPI_NATIVE_TYPE_NULL; return DPI_SUCCESS; case DPI_JZNVAL_VECTOR: node->oracleTypeNum = DPI_ORACLE_TYPE_VECTOR; node->nativeTypeNum = DPI_NATIVE_TYPE_BYTES; node->value->asBytes.ptr = scalar.value.asBytes.value; node->value->asBytes.length = scalar.value.asBytes.valueLength; return DPI_SUCCESS; default: break; } return dpiError__set(error, "populate scalar node from Oracle", DPI_ERR_UNHANDLED_JSON_SCALAR_TYPE, scalar.valueType); } //----------------------------------------------------------------------------- // dpiJsonNode__fromOracleToNative() [INTERNAL] // Populate the JSON node structure from the Oracle JSON node. //----------------------------------------------------------------------------- static int dpiJsonNode__fromOracleToNative(dpiJson *json, dpiJsonNode *node, dpiJznDomDoc *domDoc, void *oracleNode, uint32_t options, dpiError *error) { int nodeType; nodeType = (*domDoc->methods->fnGetNodeType)(domDoc, oracleNode); switch (nodeType) { case DPI_JZNDOM_ARRAY: return dpiJsonNode__fromOracleArrayToNative(json, node, domDoc, oracleNode, options, error); case DPI_JZNDOM_OBJECT: return dpiJsonNode__fromOracleObjectToNative(json, node, domDoc, oracleNode, options, error); case DPI_JZNDOM_SCALAR: return dpiJsonNode__fromOracleScalarToNative(json, node, domDoc, oracleNode, options, error); default: break; } return dpiError__set(error, "from Oracle to native node", DPI_ERR_UNHANDLED_JSON_NODE_TYPE, nodeType); } //----------------------------------------------------------------------------- // dpiJsonNode__toOracleArrayFromNative() [INTERNAL] // Populate an Oracle array node from the JSON array node. //----------------------------------------------------------------------------- static int dpiJsonNode__toOracleArrayFromNative(dpiJson *json, dpiJsonArray *array, dpiJznDomDoc *domDoc, void **oracleNode, dpiError *error) { dpiJsonNode *childNode; void *oracleChildNode; uint32_t i; *oracleNode = domDoc->methods->fnNewArray(domDoc, array->numElements); for (i = 0; i < array->numElements; i++) { childNode = &array->elements[i]; if (dpiJsonNode__toOracleFromNative(json, childNode, domDoc, &oracleChildNode, error) < 0) { domDoc->methods->fnFreeNode(domDoc, *oracleNode); return DPI_FAILURE; } domDoc->methods->fnAppendItem(domDoc, *oracleNode, oracleChildNode); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiJsonNode__toOracleObjectFromNative() [INTERNAL] // Populate an Oracle object node from the JSON object node. //----------------------------------------------------------------------------- static int dpiJsonNode__toOracleObjectFromNative(dpiJson *json, dpiJsonObject *obj, dpiJznDomDoc *domDoc, void **oracleNode, dpiError *error) { dpiJsonNode *childNode; void *oracleChildNode; uint32_t i; *oracleNode = domDoc->methods->fnNewObject(domDoc, obj->numFields); for (i = 0; i < obj->numFields; i++) { childNode = &obj->fields[i]; if (dpiJsonNode__toOracleFromNative(json, childNode, domDoc, &oracleChildNode, error) < 0) { domDoc->methods->fnFreeNode(domDoc, *oracleNode); return DPI_FAILURE; } domDoc->methods->fnPutFieldValue(domDoc, *oracleNode, obj->fieldNames[i], (uint16_t) obj->fieldNameLengths[i], oracleChildNode); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiJsonNode__toOracleFromNative() [INTERNAL] // Create an Oracle node from the native node. //----------------------------------------------------------------------------- static int dpiJsonNode__toOracleFromNative(dpiJson *json, const dpiJsonNode *node, dpiJznDomDoc *domDoc, void **oracleNode, dpiError *error) { dpiOracleDataBuffer dataBuffer; int scalarType; switch (node->oracleTypeNum) { case DPI_ORACLE_TYPE_JSON_ARRAY: if (node->nativeTypeNum == DPI_NATIVE_TYPE_JSON_ARRAY) { return dpiJsonNode__toOracleArrayFromNative(json, &node->value->asJsonArray, domDoc, oracleNode, error); } break; case DPI_ORACLE_TYPE_JSON_OBJECT: if (node->nativeTypeNum == DPI_NATIVE_TYPE_JSON_OBJECT) { return dpiJsonNode__toOracleObjectFromNative(json, &node->value->asJsonObject, domDoc, oracleNode, error); } break; case DPI_ORACLE_TYPE_NUMBER: if (node->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { if (dpiDataBuffer__toOracleNumberFromDouble(node->value, error, &dataBuffer.asNumber) < 0) return DPI_FAILURE; } else if (node->nativeTypeNum == DPI_NATIVE_TYPE_INT64) { if (dpiDataBuffer__toOracleNumberFromInteger(node->value, error, &dataBuffer.asNumber) < 0) return DPI_FAILURE; } else if (node->nativeTypeNum == DPI_NATIVE_TYPE_UINT64) { if (dpiDataBuffer__toOracleNumberFromUnsignedInteger( node->value, error, &dataBuffer.asNumber) < 0) return DPI_FAILURE; } else if (node->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { if (dpiDataBuffer__toOracleNumberFromText(node->value, json->env, error, &dataBuffer.asNumber) < 0) return DPI_FAILURE; } else { break; } *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_OCI_NUMBER, &dataBuffer.asNumber); return DPI_SUCCESS; case DPI_ORACLE_TYPE_NATIVE_DOUBLE: if (node->nativeTypeNum != DPI_NATIVE_TYPE_DOUBLE) break; *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_DOUBLE, node->value->asDouble); return DPI_SUCCESS; case DPI_ORACLE_TYPE_NATIVE_FLOAT: if (node->nativeTypeNum != DPI_NATIVE_TYPE_FLOAT) break; *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_FLOAT, node->value->asFloat); return DPI_SUCCESS; case DPI_ORACLE_TYPE_RAW: if (node->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_BINARY, node->value->asBytes.ptr, node->value->asBytes.length); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_JSON_ID: if (node->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_ID, node->value->asBytes.ptr, node->value->asBytes.length); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_VARCHAR: if (node->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_STRING, node->value->asBytes.ptr, node->value->asBytes.length); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_DATE: if (node->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { if (dpiDataBuffer__toOracleDate(node->value, &dataBuffer.asDate) < 0) return DPI_FAILURE; } else if (node->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { if (dpiDataBuffer__toOracleDateFromDouble(node->value, json->env, error, &dataBuffer.asDate) < 0) return DPI_FAILURE; } else { break; } *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_OCI_DATE, &dataBuffer.asDate); return DPI_SUCCESS; case DPI_ORACLE_TYPE_TIMESTAMP: if (!json->convTimestamp) { if (dpiOci__descriptorAlloc(json->env->handle, &json->convTimestamp, DPI_OCI_DTYPE_TIMESTAMP, "alloc timestamp for JSON", error) < 0) return DPI_FAILURE; } if (node->nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) { if (dpiDataBuffer__toOracleTimestamp(node->value, json->env, error, json->convTimestamp, 0) < 0) return DPI_FAILURE; } else if (node->nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { if (dpiDataBuffer__toOracleTimestampFromDouble(node->value, node->oracleTypeNum, json->env, error, json->convTimestamp) < 0) return DPI_FAILURE; } else { break; } *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_OCI_DATETIME, json->convTimestamp); return DPI_SUCCESS; case DPI_ORACLE_TYPE_INTERVAL_DS: if (!json->convIntervalDS) { if (dpiOci__descriptorAlloc(json->env->handle, &json->convIntervalDS, DPI_OCI_DTYPE_INTERVAL_DS, "alloc interval DS for JSON", error) < 0) return DPI_FAILURE; } if (node->nativeTypeNum == DPI_NATIVE_TYPE_INTERVAL_DS) { if (dpiDataBuffer__toOracleIntervalDS(node->value, json->env, error, json->convIntervalDS) < 0) return DPI_FAILURE; *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_OCI_INTERVAL, json->convIntervalDS); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_INTERVAL_YM: if (!json->convIntervalYM) { if (dpiOci__descriptorAlloc(json->env->handle, &json->convIntervalYM, DPI_OCI_DTYPE_INTERVAL_YM, "alloc interval YM for JSON", error) < 0) return DPI_FAILURE; } if (node->nativeTypeNum == DPI_NATIVE_TYPE_INTERVAL_YM) { if (dpiDataBuffer__toOracleIntervalYM(node->value, json->env, error, json->convIntervalYM) < 0) return DPI_FAILURE; *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_OCI_INTERVAL, json->convIntervalYM); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_BOOLEAN: if (node->nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { scalarType = (node->value->asBoolean) ? DPI_JZNVAL_TRUE: DPI_JZNVAL_FALSE; *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, scalarType, NULL); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_VECTOR: if (node->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_VECTOR, node->value->asBytes.ptr, node->value->asBytes.length); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NONE: if (node->nativeTypeNum == DPI_NATIVE_TYPE_NULL) { *oracleNode = domDoc->methods->fnNewScalarVal(domDoc, DPI_JZNVAL_NULL, NULL); return DPI_SUCCESS; } break; } *oracleNode = NULL; return dpiError__set(error, "from native to Oracle node", DPI_ERR_UNHANDLED_CONVERSION_TO_JSON, node->nativeTypeNum, node->oracleTypeNum); } //----------------------------------------------------------------------------- // dpiJson__setValue() [INTERNAL] // Sets the value of the JSON object, given a hierarchy of nodes. //----------------------------------------------------------------------------- int dpiJson__setValue(dpiJson *json, const dpiJsonNode *topNode, dpiError *error) { const char *dummyValue = "0"; dpiJznDomDoc *domDoc; void *oracleTopNode; int mutable = 1; // first, set the JSON descriptor as mutable if (dpiOci__attrSet(json->handle, DPI_OCI_DTYPE_JSON, (void*) &mutable, 0, DPI_OCI_ATTR_JSON_DOM_MUTABLE, "set JSON descriptor mutable", error) < 0) return DPI_FAILURE; // write a dummy value to the JSON descriptor if (dpiOci__jsonTextBufferParse(json, dummyValue, strlen(dummyValue), 0, error) < 0) return DPI_FAILURE; // acquire the DOM doc which will be used to create the Oracle nodes if (dpiOci__jsonDomDocGet(json, &domDoc, error) < 0) return DPI_FAILURE; // convert the top node (and all of the child nodes to Oracle nodes) if (dpiJsonNode__toOracleFromNative(json, topNode, domDoc, &oracleTopNode, error) < 0) return DPI_FAILURE; // set the top node domDoc->methods->fnSetRootNode(domDoc, oracleTopNode); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiJsonNode__free() [INTERNAL] // Free the buffers allocated for the JSON node. //----------------------------------------------------------------------------- static void dpiJsonNode__free(dpiJsonNode *node) { dpiJsonArray *array; dpiJsonObject *obj; uint32_t i; if (node->oracleTypeNum == DPI_ORACLE_TYPE_JSON_ARRAY) { array = &node->value->asJsonArray; if (array->elements) { for (i = 0; i < array->numElements; i++) { if (array->elements[i].value) dpiJsonNode__free(&array->elements[i]); } dpiUtils__freeMemory(array->elements); array->elements = NULL; } if (array->elementValues) { dpiUtils__freeMemory(array->elementValues); array->elementValues = NULL; } } else if (node->oracleTypeNum == DPI_ORACLE_TYPE_JSON_OBJECT) { obj = &node->value->asJsonObject; if (obj->fields) { for (i = 0; i < obj->numFields; i++) { if (obj->fields[i].value) dpiJsonNode__free(&obj->fields[i]); } dpiUtils__freeMemory(obj->fields); obj->fields = NULL; } if (obj->fieldNames) { dpiUtils__freeMemory(obj->fieldNames); obj->fieldNames = NULL; } if (obj->fieldNameLengths) { dpiUtils__freeMemory(obj->fieldNameLengths); obj->fieldNameLengths = NULL; } if (obj->fieldValues) { dpiUtils__freeMemory(obj->fieldValues); obj->fieldValues = NULL; } } } //----------------------------------------------------------------------------- // dpiJson__free() [INTERNAL] // Free the buffers allocated for the JSON value and all of its nodes, if // applicable. //----------------------------------------------------------------------------- void dpiJson__free(dpiJson *json, dpiError *error) { uint32_t i; if (json->handle && json->handleIsOwned) { dpiOci__descriptorFree(json->handle, DPI_OCI_DTYPE_JSON); json->handle = NULL; } if (json->conn) { dpiGen__setRefCount(json->conn, error, -1); json->conn = NULL; } if (json->tempBuffers) { for (i = 0; i < json->numTempBuffers; i++) dpiUtils__freeMemory(json->tempBuffers[i]); dpiUtils__freeMemory(json->tempBuffers); json->tempBuffers = NULL; } if (json->convTimestamp) { dpiOci__descriptorFree(json->convTimestamp, DPI_OCI_DTYPE_TIMESTAMP); json->convTimestamp = NULL; } if (json->convIntervalDS) { dpiOci__descriptorFree(json->convIntervalDS, DPI_OCI_DTYPE_INTERVAL_DS); json->convIntervalDS = NULL; } if (json->convIntervalYM) { dpiOci__descriptorFree(json->convIntervalYM, DPI_OCI_DTYPE_INTERVAL_YM); json->convIntervalYM = NULL; } dpiJsonNode__free(&json->topNode); dpiUtils__freeMemory(json); } //----------------------------------------------------------------------------- // dpiJson_addRef() [PUBLIC] // Add a reference to the JSON object. //----------------------------------------------------------------------------- int dpiJson_addRef(dpiJson *json) { return dpiGen__addRef(json, DPI_HTYPE_JSON, __func__); } //----------------------------------------------------------------------------- // dpiJson_getValue() [PUBLIC] // Gets the value of the JSON object as a hierarchy of nodes. //----------------------------------------------------------------------------- int dpiJson_getValue(dpiJson *json, uint32_t options, dpiJsonNode **topNode) { dpiJznDomDoc *domDoc; void *oracleNode; dpiError error; if (dpiGen__startPublicFn(json, DPI_HTYPE_JSON, __func__, &error) < 0) return dpiGen__endPublicFn(json, DPI_FAILURE, &error); dpiJsonNode__free(&json->topNode); json->topNode.value = &json->topNodeBuffer; json->topNode.oracleTypeNum = DPI_ORACLE_TYPE_NONE; json->topNode.nativeTypeNum = DPI_NATIVE_TYPE_NULL; if (dpiOci__jsonDomDocGet(json, &domDoc, &error) < 0) return dpiGen__endPublicFn(json, DPI_FAILURE, &error); if (domDoc) { oracleNode = (*domDoc->methods->fnGetRootNode)(domDoc); if (dpiJsonNode__fromOracleToNative(json, &json->topNode, domDoc, oracleNode, options, &error) < 0) return dpiGen__endPublicFn(json, DPI_FAILURE, &error); } *topNode = &json->topNode; return dpiGen__endPublicFn(json, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiJson_release() [PUBLIC] // Release a reference to the JSON object. //----------------------------------------------------------------------------- int dpiJson_release(dpiJson *json) { return dpiGen__release(json, DPI_HTYPE_JSON, __func__); } //----------------------------------------------------------------------------- // dpiJson_setFromText() [PUBLIC] // Sets the value of the JSON handle, given a JSON string. //----------------------------------------------------------------------------- int dpiJson_setFromText(dpiJson *json, const char *value, uint64_t valueLength, uint32_t flags) { dpiError error; int status; if (dpiGen__startPublicFn(json, DPI_HTYPE_JSON, __func__, &error) < 0) return dpiGen__endPublicFn(json, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(json, value) status = dpiOci__jsonTextBufferParse(json, value, valueLength, flags, &error); return dpiGen__endPublicFn(json, status, &error); } //----------------------------------------------------------------------------- // dpiJson_setValue() [PUBLIC] // Sets the value of the JSON object, given a hierarchy of nodes. //----------------------------------------------------------------------------- int dpiJson_setValue(dpiJson *json, dpiJsonNode *topNode) { dpiError error; int status; if (dpiGen__startPublicFn(json, DPI_HTYPE_JSON, __func__, &error) < 0) return dpiGen__endPublicFn(json, DPI_FAILURE, &error); status = dpiJson__setValue(json, topNode, &error); return dpiGen__endPublicFn(json, status, &error); } odpi-5.6.4/src/dpiLob.c000066400000000000000000000464211510466437300146450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiLob.c // Implementation of LOB data. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiLob__allocate() [INTERNAL] // Allocate and initialize LOB object. //----------------------------------------------------------------------------- int dpiLob__allocate(dpiConn *conn, const dpiOracleType *type, dpiLob **lob, dpiError *error) { dpiLob *tempLob; if (dpiGen__allocate(DPI_HTYPE_LOB, conn->env, (void**) &tempLob, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempLob->conn = conn; tempLob->type = type; if (dpiOci__descriptorAlloc(conn->env->handle, &tempLob->locator, DPI_OCI_DTYPE_LOB, "allocate descriptor", error) < 0) { dpiLob__free(tempLob, error); return DPI_FAILURE; } if (dpiHandleList__addHandle(conn->openLobs, tempLob, &tempLob->openSlotNum, error) < 0) { dpiLob__free(tempLob, error); return DPI_FAILURE; } *lob = tempLob; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiLob__check() [INTERNAL] // Check that the LOB is valid and get an error handle for subsequent calls. //----------------------------------------------------------------------------- static int dpiLob__check(dpiLob *lob, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(lob, DPI_HTYPE_LOB, fnName, error) < 0) return DPI_FAILURE; if (!lob->conn || !lob->conn->handle) return dpiError__set(error, "conn closed?", DPI_ERR_NOT_CONNECTED); if (!lob->locator) return dpiError__set(error, "LOB closed?", DPI_ERR_LOB_CLOSED); return dpiConn__checkConnected(lob->conn, error); } //----------------------------------------------------------------------------- // dpiLob__close() [INTERNAL] // Internal method used for closing the LOB. //----------------------------------------------------------------------------- int dpiLob__close(dpiLob *lob, int propagateErrors, dpiError *error) { int isTemporary, closing, status = DPI_SUCCESS; // determine whether LOB is already being closed and if not, mark LOB as // being closed; this MUST be done while holding the lock (if in threaded // mode) to avoid race conditions! if (lob->env->threaded) dpiMutex__acquire(lob->env->mutex); closing = lob->closing; lob->closing = 1; if (lob->env->threaded) dpiMutex__release(lob->env->mutex); // if LOB is already being closed, nothing needs to be done if (closing) return DPI_SUCCESS; // perform actual work of closing LOB if (lob->locator) { if (!lob->conn->deadSession && lob->conn->handle) { status = dpiOci__lobIsTemporary(lob, &isTemporary, propagateErrors, error); if (isTemporary && status == DPI_SUCCESS) status = dpiOci__lobFreeTemporary(lob->conn, lob->locator, propagateErrors, error); } dpiOci__descriptorFree(lob->locator, DPI_OCI_DTYPE_LOB); lob->locator = NULL; } if (lob->buffer) { dpiUtils__freeMemory(lob->buffer); lob->buffer = NULL; } // if actual close fails, reset closing flag; again, this must be done // while holding the lock (if in threaded mode) in order to avoid race // conditions! if (status < 0) { if (lob->env->threaded) dpiMutex__acquire(lob->env->mutex); lob->closing = 0; if (lob->env->threaded) dpiMutex__release(lob->env->mutex); } return status; } //----------------------------------------------------------------------------- // dpiLob__free() [INTERNAL] // Free the memory for a LOB. //----------------------------------------------------------------------------- void dpiLob__free(dpiLob *lob, dpiError *error) { dpiLob__close(lob, 0, error); if (lob->conn) { dpiHandleList__removeHandle(lob->conn->openLobs, lob->openSlotNum); dpiGen__setRefCount(lob->conn, error, -1); lob->conn = NULL; } dpiUtils__freeMemory(lob); } //----------------------------------------------------------------------------- // dpiLob__readBytes() [INTERNAL] // Return a portion (or all) of the data in the LOB. //----------------------------------------------------------------------------- int dpiLob__readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, char *value, uint64_t *valueLength, dpiError *error) { uint64_t lengthInBytes = 0, lengthInChars = 0; int isOpen = 0; // amount is in characters for character LOBs and bytes for binary LOBs if (lob->type->isCharacterData) lengthInChars = amount; else lengthInBytes = amount; // for files, open the file if needed if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) { if (dpiOci__lobIsOpen(lob, &isOpen, error) < 0) return DPI_FAILURE; if (!isOpen) { if (dpiOci__lobOpen(lob, error) < 0) return DPI_FAILURE; } } // read the bytes from the LOB if (dpiOci__lobRead2(lob, offset, &lengthInBytes, &lengthInChars, value, *valueLength, error) < 0) return DPI_FAILURE; *valueLength = lengthInBytes; // if file was opened in this routine, close it again if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE && !isOpen) { if (dpiOci__lobClose(lob, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiLob__setFromBytes() [INTERNAL] // Clear the LOB completely and then write the specified bytes to it. //----------------------------------------------------------------------------- int dpiLob__setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength, dpiError *error) { if (dpiOci__lobTrim2(lob, 0, error) < 0) return DPI_FAILURE; if (valueLength == 0) return DPI_SUCCESS; return dpiOci__lobWrite2(lob, 1, value, valueLength, error); } //----------------------------------------------------------------------------- // dpiLob_addRef() [PUBLIC] // Add a reference to the LOB. //----------------------------------------------------------------------------- int dpiLob_addRef(dpiLob *lob) { return dpiGen__addRef(lob, DPI_HTYPE_LOB, __func__); } //----------------------------------------------------------------------------- // dpiLob_close() [PUBLIC] // Close the LOB and make it unusable for further operations. //----------------------------------------------------------------------------- int dpiLob_close(dpiLob *lob) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); status = dpiLob__close(lob, 1, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_closeResource() [PUBLIC] // Close the LOB's resources. //----------------------------------------------------------------------------- int dpiLob_closeResource(dpiLob *lob) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); status = dpiOci__lobClose(lob, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_copy() [PUBLIC] // Create a copy of the LOB and return it. //----------------------------------------------------------------------------- int dpiLob_copy(dpiLob *lob, dpiLob **copiedLob) { dpiLob *tempLob; dpiError error; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, copiedLob) if (dpiLob__allocate(lob->conn, lob->type, &tempLob, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); if (dpiOci__lobLocatorAssign(lob, &tempLob->locator, &error) < 0) { dpiLob__free(tempLob, &error); return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); } *copiedLob = tempLob; return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiLob_getBufferSize() [PUBLIC] // Get the required size of a buffer given the number of characters. If the // LOB does not refer to a character LOB the value is returned unchanged. //----------------------------------------------------------------------------- int dpiLob_getBufferSize(dpiLob *lob, uint64_t sizeInChars, uint64_t *sizeInBytes) { dpiError error; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, sizeInBytes) if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB) *sizeInBytes = sizeInChars * lob->env->maxBytesPerCharacter; else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB) *sizeInBytes = sizeInChars * lob->env->nmaxBytesPerCharacter; else *sizeInBytes = sizeInChars; return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiLob_getChunkSize() [PUBLIC] // Return the chunk size associated with the LOB. //----------------------------------------------------------------------------- int dpiLob_getChunkSize(dpiLob *lob, uint32_t *size) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, size) status = dpiOci__lobGetChunkSize(lob, size, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_getDirectoryAndFileName() [PUBLIC] // Return the directory alias and file name for the BFILE lob. //----------------------------------------------------------------------------- int dpiLob_getDirectoryAndFileName(dpiLob *lob, const char **directoryAlias, uint32_t *directoryAliasLength, const char **fileName, uint32_t *fileNameLength) { uint16_t ociDirectoryAliasLength, ociFileNameLength; dpiError error; // validate parameters if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias) DPI_CHECK_PTR_NOT_NULL(lob, directoryAliasLength) DPI_CHECK_PTR_NOT_NULL(lob, fileName) DPI_CHECK_PTR_NOT_NULL(lob, fileNameLength) // get directory and file name ociDirectoryAliasLength = 30; ociFileNameLength = 255; if (!lob->buffer) { if (dpiUtils__allocateMemory(1, ociDirectoryAliasLength + ociFileNameLength, 0, "allocate name buffer", (void**) &lob->buffer, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); } *directoryAlias = lob->buffer; *fileName = lob->buffer + ociDirectoryAliasLength; if (dpiOci__lobFileGetName(lob, (char*) *directoryAlias, &ociDirectoryAliasLength, (char*) *fileName, &ociFileNameLength, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); *directoryAliasLength = ociDirectoryAliasLength; *fileNameLength = ociFileNameLength; return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiLob_getFileExists() [PUBLIC] // Return whether or not the file pointed to by the locator exists. //----------------------------------------------------------------------------- int dpiLob_getFileExists(dpiLob *lob, int *exists) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, exists) status = dpiOci__lobFileExists(lob, exists, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_getIsResourceOpen() [PUBLIC] // Return whether or not the LOB' resources are open. //----------------------------------------------------------------------------- int dpiLob_getIsResourceOpen(dpiLob *lob, int *isOpen) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, isOpen) status = dpiOci__lobIsOpen(lob, isOpen, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_getSize() [PUBLIC] // Returns the size of the LOB. //----------------------------------------------------------------------------- int dpiLob_getSize(dpiLob *lob, uint64_t *size) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, size) status = dpiOci__lobGetLength2(lob, size, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_getType() [PUBLIC] // Returns the type of the LOB. //----------------------------------------------------------------------------- int dpiLob_getType(dpiLob *lob, dpiOracleTypeNum *type) { dpiError error; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, type) *type = lob->type->oracleTypeNum; return dpiGen__endPublicFn(lob, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiLob_openResource() [PUBLIC] // Open the LOB's resources to speed further accesses. //----------------------------------------------------------------------------- int dpiLob_openResource(dpiLob *lob) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); status = dpiOci__lobOpen(lob, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_readBytes() [PUBLIC] // Return a portion (or all) of the data in the LOB. //----------------------------------------------------------------------------- int dpiLob_readBytes(dpiLob *lob, uint64_t offset, uint64_t amount, char *value, uint64_t *valueLength) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, value) DPI_CHECK_PTR_NOT_NULL(lob, valueLength) status = dpiLob__readBytes(lob, offset, amount, value, valueLength, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_release() [PUBLIC] // Release a reference to the LOB. //----------------------------------------------------------------------------- int dpiLob_release(dpiLob *lob) { return dpiGen__release(lob, DPI_HTYPE_LOB, __func__); } //----------------------------------------------------------------------------- // dpiLob_setDirectoryAndFileName() [PUBLIC] // Set the directory alias and file name for the BFILE LOB. //----------------------------------------------------------------------------- int dpiLob_setDirectoryAndFileName(dpiLob *lob, const char *directoryAlias, uint32_t directoryAliasLength, const char *fileName, uint32_t fileNameLength) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, directoryAlias) DPI_CHECK_PTR_NOT_NULL(lob, fileName) status = dpiOci__lobFileSetName(lob, directoryAlias, (uint16_t) directoryAliasLength, fileName, (uint16_t) fileNameLength, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_setFromBytes() [PUBLIC] // Clear the LOB completely and then write the specified bytes to it. //----------------------------------------------------------------------------- int dpiLob_setFromBytes(dpiLob *lob, const char *value, uint64_t valueLength) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(lob, value) status = dpiLob__setFromBytes(lob, value, valueLength, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_trim() [PUBLIC] // Trim the LOB to the specified length. //----------------------------------------------------------------------------- int dpiLob_trim(dpiLob *lob, uint64_t newSize) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); status = dpiOci__lobTrim2(lob, newSize, &error); return dpiGen__endPublicFn(lob, status, &error); } //----------------------------------------------------------------------------- // dpiLob_writeBytes() [PUBLIC] // Write the data to the LOB at the offset specified. //----------------------------------------------------------------------------- int dpiLob_writeBytes(dpiLob *lob, uint64_t offset, const char *value, uint64_t valueLength) { dpiError error; int status; if (dpiLob__check(lob, __func__, &error) < 0) return dpiGen__endPublicFn(lob, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(lob, value) status = dpiOci__lobWrite2(lob, offset, value, valueLength, &error); return dpiGen__endPublicFn(lob, status, &error); } odpi-5.6.4/src/dpiMsgProps.c000066400000000000000000000555031510466437300157040ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiMsgProps.c // Implementation of AQ message properties. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiMsgProps__allocate() [INTERNAL] // Create a new message properties structure and return it. In case of error // NULL is returned. //----------------------------------------------------------------------------- int dpiMsgProps__allocate(dpiConn *conn, dpiMsgProps **props, dpiError *error) { dpiMsgProps *tempProps; if (dpiGen__allocate(DPI_HTYPE_MSG_PROPS, conn->env, (void**) &tempProps, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempProps->conn = conn; if (dpiOci__descriptorAlloc(conn->env->handle, &tempProps->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, "allocate descriptor", error) < 0) { dpiMsgProps__free(tempProps, error); return DPI_FAILURE; } *props = tempProps; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiMsgProps__extractMsgId() [INTERNAL] // Extract bytes from the OCIRaw value containing the message id. //----------------------------------------------------------------------------- void dpiMsgProps__extractMsgId(dpiMsgProps *props, const char **msgId, uint32_t *msgIdLength) { dpiOci__rawPtr(props->env->handle, props->msgIdRaw, (void**) msgId); dpiOci__rawSize(props->env->handle, props->msgIdRaw, msgIdLength); } //----------------------------------------------------------------------------- // dpiMsgProps__free() [INTERNAL] // Free the memory for a message properties structure. //----------------------------------------------------------------------------- void dpiMsgProps__free(dpiMsgProps *props, dpiError *error) { if (props->handle) { dpiOci__descriptorFree(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES); props->handle = NULL; } if (props->payloadObj) { dpiGen__setRefCount(props->payloadObj, error, -1); props->payloadObj = NULL; } if (props->payloadJson) { dpiGen__setRefCount(props->payloadJson, error, -1); props->payloadJson = NULL; } if (props->payloadRaw) { dpiOci__rawResize(props->env->handle, &props->payloadRaw, 0, error); props->payloadRaw = NULL; } if (props->msgIdRaw) { dpiOci__rawResize(props->env->handle, &props->msgIdRaw, 0, error); props->msgIdRaw = NULL; } if (props->conn) { dpiGen__setRefCount(props->conn, error, -1); props->conn = NULL; } dpiUtils__freeMemory(props); } //----------------------------------------------------------------------------- // dpiMsgProps__getAttrValue() [INTERNAL] // Get the attribute value in OCI. //----------------------------------------------------------------------------- static int dpiMsgProps__getAttrValue(dpiMsgProps *props, uint32_t attribute, const char *fnName, void *value, uint32_t *valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, fnName, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) DPI_CHECK_PTR_NOT_NULL(props, valueLength) status = dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, value, valueLength, attribute, "get attribute value", &error); return dpiGen__endPublicFn(props, status, &error); } //----------------------------------------------------------------------------- // dpiMsgProps__setAttrValue() [INTERNAL] // Set the attribute value in OCI. //----------------------------------------------------------------------------- static int dpiMsgProps__setAttrValue(dpiMsgProps *props, uint32_t attribute, const char *fnName, const void *value, uint32_t valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, fnName, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) status = dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, (void*) value, valueLength, attribute, "set attribute value", &error); return dpiGen__endPublicFn(props, status, &error); } //----------------------------------------------------------------------------- // dpiMsgProps__setRecipients() [INTERNAL] // Set the recipients value in OCI. //----------------------------------------------------------------------------- int dpiMsgProps__setRecipients(dpiMsgProps *props, dpiMsgRecipient *recipients, uint32_t numRecipients, void **aqAgents, dpiError *error) { uint32_t i; for (i = 0; i < numRecipients; i++) { if (dpiOci__descriptorAlloc(props->env->handle, &aqAgents[i], DPI_OCI_DTYPE_AQAGENT, "allocate agent descriptor", error) < 0) return DPI_FAILURE; if (recipients[i].name && recipients[i].nameLength > 0) { if (dpiOci__attrSet(aqAgents[i], DPI_OCI_DTYPE_AQAGENT, (void*) recipients[i].name, recipients[i].nameLength, DPI_OCI_ATTR_AGENT_NAME, "set agent name", error) < 0) return DPI_FAILURE; } } if (dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, aqAgents, numRecipients, DPI_OCI_ATTR_RECIPIENT_LIST, "set recipient list", error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiMsgProps_addRef() [PUBLIC] // Add a reference to the message properties. //----------------------------------------------------------------------------- int dpiMsgProps_addRef(dpiMsgProps *props) { return dpiGen__addRef(props, DPI_HTYPE_MSG_PROPS, __func__); } //----------------------------------------------------------------------------- // dpiMsgProps_getCorrelation() [PUBLIC] // Return correlation associated with the message. //----------------------------------------------------------------------------- int dpiMsgProps_getCorrelation(dpiMsgProps *props, const char **value, uint32_t *valueLength) { return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_CORRELATION, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getDelay() [PUBLIC] // Return the number of seconds the message was delayed. //----------------------------------------------------------------------------- int dpiMsgProps_getDelay(dpiMsgProps *props, int32_t *value) { uint32_t valueLength = sizeof(uint32_t); return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_DELAY, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getDeliveryMode() [PUBLIC] // Return the mode used for delivering the message. //----------------------------------------------------------------------------- int dpiMsgProps_getDeliveryMode(dpiMsgProps *props, dpiMessageDeliveryMode *value) { uint32_t valueLength = sizeof(uint16_t); return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_MSG_DELIVERY_MODE, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getEnqTime() [PUBLIC] // Return the time the message was enqueued. //----------------------------------------------------------------------------- int dpiMsgProps_getEnqTime(dpiMsgProps *props, dpiTimestamp *value) { dpiOciDate ociValue; dpiError error; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) if (dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, &ociValue, NULL, DPI_OCI_ATTR_ENQ_TIME, "get attribute value", &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); value->year = ociValue.year; value->month = ociValue.month; value->day = ociValue.day; value->hour = ociValue.hour; value->minute = ociValue.minute; value->second = ociValue.second; value->fsecond = 0; value->tzHourOffset = 0; value->tzMinuteOffset = 0; return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_getExceptionQ() [PUBLIC] // Return the name of the exception queue associated with the message. //----------------------------------------------------------------------------- int dpiMsgProps_getExceptionQ(dpiMsgProps *props, const char **value, uint32_t *valueLength) { return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_EXCEPTION_QUEUE, __func__, (void*) value, valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getExpiration() [PUBLIC] // Return the number of seconds until the message expires. //----------------------------------------------------------------------------- int dpiMsgProps_getExpiration(dpiMsgProps *props, int32_t *value) { uint32_t valueLength = sizeof(uint32_t); return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_EXPIRATION, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getNumAttempts() [PUBLIC] // Return the number of attempts made to deliver the message. //----------------------------------------------------------------------------- int dpiMsgProps_getNumAttempts(dpiMsgProps *props, int32_t *value) { uint32_t valueLength = sizeof(uint32_t); return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_ATTEMPTS, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getMsgId() [PUBLIC] // Return the message id for the message (available after enqueuing or // dequeuing a message). //----------------------------------------------------------------------------- int dpiMsgProps_getMsgId(dpiMsgProps *props, const char **value, uint32_t *valueLength) { dpiError error; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) DPI_CHECK_PTR_NOT_NULL(props, valueLength) dpiMsgProps__extractMsgId(props, value, valueLength); return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_getOriginalMsgId() [PUBLIC] // Return the original message id for the message. //----------------------------------------------------------------------------- int dpiMsgProps_getOriginalMsgId(dpiMsgProps *props, const char **value, uint32_t *valueLength) { dpiError error; void *rawValue; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) DPI_CHECK_PTR_NOT_NULL(props, valueLength) if (dpiOci__attrGet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, &rawValue, NULL, DPI_OCI_ATTR_ORIGINAL_MSGID, "get attribute value", &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); dpiOci__rawPtr(props->env->handle, rawValue, (void**) value); dpiOci__rawSize(props->env->handle, rawValue, valueLength); return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_getPayload() [PUBLIC] // Get the payload for the message (as an object or a series of bytes). //----------------------------------------------------------------------------- int dpiMsgProps_getPayload(dpiMsgProps *props, dpiObject **obj, const char **value, uint32_t *valueLength) { dpiError error; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); if (obj) *obj = props->payloadObj; if (value && valueLength) { if (props->payloadRaw) { dpiOci__rawPtr(props->env->handle, props->payloadRaw, (void**) value); dpiOci__rawSize(props->env->handle, props->payloadRaw, valueLength); } else { *value = NULL; *valueLength = 0; } } return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_getPayloadJson() [PUBLIC] // Get the JSON payload for the message (as a dpiJson). //----------------------------------------------------------------------------- int dpiMsgProps_getPayloadJson(dpiMsgProps *props, dpiJson **json) { dpiError error; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, json) *json = props->payloadJson; return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_getPriority() [PUBLIC] // Return the priority of the message. //----------------------------------------------------------------------------- int dpiMsgProps_getPriority(dpiMsgProps *props, int32_t *value) { uint32_t valueLength = sizeof(uint32_t); return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_PRIORITY, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_getState() [PUBLIC] // Return the state of the message. //----------------------------------------------------------------------------- int dpiMsgProps_getState(dpiMsgProps *props, dpiMessageState *value) { uint32_t valueLength = sizeof(uint32_t); return dpiMsgProps__getAttrValue(props, DPI_OCI_ATTR_MSG_STATE, __func__, value, &valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_release() [PUBLIC] // Release a reference to the message properties. //----------------------------------------------------------------------------- int dpiMsgProps_release(dpiMsgProps *props) { return dpiGen__release(props, DPI_HTYPE_MSG_PROPS, __func__); } //----------------------------------------------------------------------------- // dpiMsgProps_setCorrelation() [PUBLIC] // Set correlation associated with the message. //----------------------------------------------------------------------------- int dpiMsgProps_setCorrelation(dpiMsgProps *props, const char *value, uint32_t valueLength) { return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_CORRELATION, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_setDelay() [PUBLIC] // Set the number of seconds to delay the message. //----------------------------------------------------------------------------- int dpiMsgProps_setDelay(dpiMsgProps *props, int32_t value) { return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_DELAY, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiMsgProps_setExceptionQ() [PUBLIC] // Set the name of the exception queue associated with the message. //----------------------------------------------------------------------------- int dpiMsgProps_setExceptionQ(dpiMsgProps *props, const char *value, uint32_t valueLength) { return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_EXCEPTION_QUEUE, __func__, value, valueLength); } //----------------------------------------------------------------------------- // dpiMsgProps_setExpiration() [PUBLIC] // Set the number of seconds until the message expires. //----------------------------------------------------------------------------- int dpiMsgProps_setExpiration(dpiMsgProps *props, int32_t value) { return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_EXPIRATION, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiMsgProps_setOriginalMsgId() [PUBLIC] // Set the original message id for the message. //----------------------------------------------------------------------------- int dpiMsgProps_setOriginalMsgId(dpiMsgProps *props, const char *value, uint32_t valueLength) { void *rawValue = NULL; dpiError error; int status; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) if (dpiOci__rawAssignBytes(props->env->handle, value, valueLength, &rawValue, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); status = dpiOci__attrSet(props->handle, DPI_OCI_DTYPE_AQMSG_PROPERTIES, (void*) rawValue, 0, DPI_OCI_ATTR_ORIGINAL_MSGID, "set value", &error); dpiOci__rawResize(props->env->handle, &rawValue, 0, &error); return dpiGen__endPublicFn(props, status, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_setPayloadBytes() [PUBLIC] // Set the payload for the message (as a series of bytes). //----------------------------------------------------------------------------- int dpiMsgProps_setPayloadBytes(dpiMsgProps *props, const char *value, uint32_t valueLength) { dpiError error; int status; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, value) if (props->payloadRaw) { dpiOci__rawResize(props->env->handle, &props->payloadRaw, 0, &error); props->payloadRaw = NULL; } status = dpiOci__rawAssignBytes(props->env->handle, value, valueLength, &props->payloadRaw, &error); return dpiGen__endPublicFn(props, status, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_setPayloadJson() [PUBLIC] // Set the payload for the message (as a JSON object). //----------------------------------------------------------------------------- int dpiMsgProps_setPayloadJson(dpiMsgProps *props, dpiJson *json) { dpiError error; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); if (dpiGen__checkHandle(json, DPI_HTYPE_JSON, "check json object", &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); if (props->payloadJson) dpiGen__setRefCount(props->payloadJson, &error, -1); dpiGen__setRefCount(json, &error, 1); props->payloadJson = json; return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_setPayloadObject() [PUBLIC] // Set the payload for the message (as an object). //----------------------------------------------------------------------------- int dpiMsgProps_setPayloadObject(dpiMsgProps *props, dpiObject *obj) { dpiError error; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); if (dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, "check object", &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); if (props->payloadObj) dpiGen__setRefCount(props->payloadObj, &error, -1); dpiGen__setRefCount(obj, &error, 1); props->payloadObj = obj; return dpiGen__endPublicFn(props, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiMsgProps_setPriority() [PUBLIC] // Set the priority of the message. //----------------------------------------------------------------------------- int dpiMsgProps_setPriority(dpiMsgProps *props, int32_t value) { return dpiMsgProps__setAttrValue(props, DPI_OCI_ATTR_PRIORITY, __func__, &value, 0); } //----------------------------------------------------------------------------- // dpiMsgProps_setRecipients() [PUBLIC] // Set recipients associated with the message. //----------------------------------------------------------------------------- int dpiMsgProps_setRecipients(dpiMsgProps *props, dpiMsgRecipient *recipients, uint32_t numRecipients) { void **aqAgents; dpiError error; uint32_t i; int status; if (dpiGen__startPublicFn(props, DPI_HTYPE_MSG_PROPS, __func__, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(props, recipients) if (dpiUtils__allocateMemory(numRecipients, sizeof(void*), 1, "allocate memory for agents", (void**) &aqAgents, &error) < 0) return dpiGen__endPublicFn(props, DPI_FAILURE, &error); status = dpiMsgProps__setRecipients(props, recipients, numRecipients, aqAgents, &error); for (i = 0; i < numRecipients; i++) { if (aqAgents[i]) dpiOci__descriptorFree(aqAgents[i], DPI_OCI_DTYPE_AQAGENT); } dpiUtils__freeMemory(aqAgents); return dpiGen__endPublicFn(props, status, &error); } odpi-5.6.4/src/dpiObject.c000066400000000000000000001162161510466437300153370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiObject.c // Implementation of objects. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file int dpiObject__closeHelper(dpiObject *obj, int checkError, dpiError *error); //----------------------------------------------------------------------------- // dpiObject__allocate() [INTERNAL] // Allocate and initialize an object structure. //----------------------------------------------------------------------------- int dpiObject__allocate(dpiObjectType *objType, void *instance, void *indicator, dpiObject *dependsOnObj, dpiObject **obj, dpiError *error) { dpiObject *tempObj; if (dpiGen__allocate(DPI_HTYPE_OBJECT, objType->env, (void**) &tempObj, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(objType, error, 1); tempObj->type = objType; tempObj->instance = instance; tempObj->indicator = indicator; if (dependsOnObj) { dpiGen__setRefCount(dependsOnObj, error, 1); tempObj->dependsOnObj = dependsOnObj; } if (!instance) { if (dpiOci__objectNew(tempObj, error) < 0) { dpiObject__free(tempObj, error); return DPI_FAILURE; } if (dpiOci__objectGetInd(tempObj, error) < 0) { dpiObject__free(tempObj, error); return DPI_FAILURE; } } if (tempObj->instance && !dependsOnObj) { if (dpiHandleList__addHandle(objType->conn->objects, tempObj, &tempObj->openSlotNum, error) < 0) { dpiObject__free(tempObj, error); return DPI_FAILURE; } } *obj = tempObj; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObject__check() [INTERNAL] // Determine if the object handle provided is available for use. //----------------------------------------------------------------------------- static int dpiObject__check(dpiObject *obj, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(obj, DPI_HTYPE_OBJECT, fnName, error) < 0) return DPI_FAILURE; return dpiConn__checkConnected(obj->type->conn, error); } //----------------------------------------------------------------------------- // dpiObject__checkIsCollection() [INTERNAL] // Check if the object is a collection, and if not, raise an exception. //----------------------------------------------------------------------------- static int dpiObject__checkIsCollection(dpiObject *obj, const char *fnName, dpiError *error) { if (dpiObject__check(obj, fnName, error) < 0) return DPI_FAILURE; if (!obj->type->isCollection) return dpiError__set(error, "check collection", DPI_ERR_NOT_COLLECTION, obj->type->schemaLength, obj->type->schema, obj->type->nameLength, obj->type->name); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObject__clearOracleValue() [INTERNAL] // Clear the Oracle value after use. //----------------------------------------------------------------------------- static void dpiObject__clearOracleValue(dpiObject *obj, dpiError *error, dpiOracleDataBuffer *buffer, dpiLob *lob, dpiOracleTypeNum oracleTypeNum) { switch (oracleTypeNum) { case DPI_ORACLE_TYPE_CHAR: case DPI_ORACLE_TYPE_NCHAR: case DPI_ORACLE_TYPE_VARCHAR: case DPI_ORACLE_TYPE_NVARCHAR: if (buffer->asString) dpiOci__stringResize(obj->env->handle, &buffer->asString, 0, error); break; case DPI_ORACLE_TYPE_RAW: if (buffer->asRawData) dpiOci__rawResize(obj->env->handle, &buffer->asRawData, 0, error); break; case DPI_ORACLE_TYPE_TIMESTAMP: if (buffer->asTimestamp) dpiOci__descriptorFree(buffer->asTimestamp, DPI_OCI_DTYPE_TIMESTAMP); break; case DPI_ORACLE_TYPE_TIMESTAMP_TZ: if (buffer->asTimestamp) dpiOci__descriptorFree(buffer->asTimestamp, DPI_OCI_DTYPE_TIMESTAMP_TZ); break; case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: if (buffer->asTimestamp) dpiOci__descriptorFree(buffer->asTimestamp, DPI_OCI_DTYPE_TIMESTAMP_LTZ); break; case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_BFILE: if (lob) dpiGen__setRefCount(lob, error, -1); break; default: break; }; } //----------------------------------------------------------------------------- // dpiObject__close() [INTERNAL] // Close the object (frees the memory for the instance). This is needed to // avoid trying to do so after the connection which created the object is // closed. In some future release of the Oracle Client libraries this may not // be needed, at which point this code and all of the code for managing the // list of objects created by a collection can be removed. //----------------------------------------------------------------------------- int dpiObject__close(dpiObject *obj, int checkError, dpiError *error) { int closing; // determine whether object is already being closed and if not, mark // object as being closed; this MUST be done while holding the lock (if // in threaded mode) to avoid race conditions! if (obj->env->threaded) dpiMutex__acquire(obj->env->mutex); closing = obj->closing; obj->closing = 1; if (obj->env->threaded) dpiMutex__release(obj->env->mutex); // if object is already being closed, nothing needs to be done if (closing) return DPI_SUCCESS; // perform actual work of closing object; if this fails, reset closing // flag; again, this must be done while holding the lock (if in threaded // mode) in order to avoid race conditions! if (obj->instance && !obj->dependsOnObj) { if (dpiObject__closeHelper(obj, checkError, error) < 0) { if (obj->env->threaded) dpiMutex__acquire(obj->env->mutex); obj->closing = 0; if (obj->env->threaded) dpiMutex__release(obj->env->mutex); return DPI_FAILURE; } } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObject__closeHelper() [INTERNAL] // Helper function for closing an object. //----------------------------------------------------------------------------- int dpiObject__closeHelper(dpiObject *obj, int checkError, dpiError *error) { if (dpiOci__objectFree(obj->env->handle, obj->instance, checkError, error) < 0) return DPI_FAILURE; obj->instance = NULL; if (obj->freeIndicator && dpiOci__objectFree(obj->env->handle, obj->indicator, checkError, error) < 0) return DPI_FAILURE; obj->indicator = NULL; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObject__free() [INTERNAL] // Free the memory for an object. //----------------------------------------------------------------------------- void dpiObject__free(dpiObject *obj, dpiError *error) { dpiObject__close(obj, 0, error); if (obj->type) { dpiHandleList__removeHandle(obj->type->conn->objects, obj->openSlotNum); dpiGen__setRefCount(obj->type, error, -1); obj->type = NULL; } if (obj->dependsOnObj) { dpiGen__setRefCount(obj->dependsOnObj, error, -1); obj->dependsOnObj = NULL; } dpiUtils__freeMemory(obj); } //----------------------------------------------------------------------------- // dpiObject__fromOracleValue() [INTERNAL] // Populate data from the Oracle value or return an error if this is not // possible. //----------------------------------------------------------------------------- static int dpiObject__fromOracleValue(dpiObject *obj, dpiError *error, const dpiDataTypeInfo *typeInfo, dpiOracleData *value, int16_t *indicator, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiOracleTypeNum valueOracleTypeNum; dpiBytes *asBytes; // null values are immediately returned (type is irrelevant) if (*indicator == DPI_OCI_IND_NULL) { data->isNull = 1; return DPI_SUCCESS; } // convert all other values data->isNull = 0; valueOracleTypeNum = typeInfo->oracleTypeNum; switch (valueOracleTypeNum) { case DPI_ORACLE_TYPE_CHAR: case DPI_ORACLE_TYPE_NCHAR: case DPI_ORACLE_TYPE_VARCHAR: case DPI_ORACLE_TYPE_NVARCHAR: if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { asBytes = &data->value.asBytes; dpiOci__stringPtr(obj->env->handle, *value->asString, &asBytes->ptr); dpiOci__stringSize(obj->env->handle, *value->asString, &asBytes->length); if (valueOracleTypeNum == DPI_ORACLE_TYPE_NCHAR || valueOracleTypeNum == DPI_ORACLE_TYPE_NVARCHAR) asBytes->encoding = obj->env->nencoding; else asBytes->encoding = obj->env->encoding; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_RAW: if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { asBytes = &data->value.asBytes; dpiOci__rawPtr(obj->env->handle, *value->asRawData, (void**) &asBytes->ptr); dpiOci__rawSize(obj->env->handle, *value->asRawData, &asBytes->length); asBytes->encoding = NULL; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NATIVE_INT: if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { data->value.asInt64 = *value->asInt32; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NATIVE_FLOAT: if (nativeTypeNum == DPI_NATIVE_TYPE_FLOAT) { data->value.asFloat = *value->asFloat; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NATIVE_DOUBLE: if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { data->value.asDouble = *value->asDouble; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NUMBER: if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return dpiDataBuffer__fromOracleNumberAsDouble(&data->value, error, value->asNumber); else if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) return dpiDataBuffer__fromOracleNumberAsInteger(&data->value, error, value->asNumber); else if (nativeTypeNum == DPI_NATIVE_TYPE_UINT64) return dpiDataBuffer__fromOracleNumberAsUnsignedInteger( &data->value, error, value->asNumber); else if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) return dpiDataBuffer__fromOracleNumberAsText(&data->value, obj->env, error, value->asNumber); break; case DPI_ORACLE_TYPE_DATE: if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) return dpiDataBuffer__fromOracleDate(&data->value, value->asDate); if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return dpiDataBuffer__fromOracleDateAsDouble(&data->value, obj->env, error, value->asDate); break; case DPI_ORACLE_TYPE_TIMESTAMP: if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) return dpiDataBuffer__fromOracleTimestamp(&data->value, obj->env, error, *value->asTimestamp, 0); if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return dpiDataBuffer__fromOracleTimestampAsDouble(&data->value, valueOracleTypeNum, obj->env, error, *value->asTimestamp); break; case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) return dpiDataBuffer__fromOracleTimestamp(&data->value, obj->env, error, *value->asTimestamp, 1); if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return dpiDataBuffer__fromOracleTimestampAsDouble(&data->value, valueOracleTypeNum, obj->env, error, *value->asTimestamp); break; case DPI_ORACLE_TYPE_OBJECT: if (typeInfo->objectType && nativeTypeNum == DPI_NATIVE_TYPE_OBJECT) { void *instance = (typeInfo->objectType->isCollection && !obj->type->isCollection) ? *value->asCollection : value->asRaw; dpiObject *tempObj; if (dpiObject__allocate(typeInfo->objectType, instance, indicator, obj, &tempObj, error) < 0) return DPI_FAILURE; data->value.asObject = tempObj; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_BOOLEAN: if (nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { data->value.asBoolean = *(value->asBoolean); return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_BFILE: if (nativeTypeNum == DPI_NATIVE_TYPE_LOB) { const dpiOracleType *lobType; void *tempLocator; dpiLob *tempLob; lobType = dpiOracleType__getFromNum(typeInfo->oracleTypeNum, error); if (dpiLob__allocate(obj->type->conn, lobType, &tempLob, error) < 0) return DPI_FAILURE; tempLocator = tempLob->locator; tempLob->locator = *(value->asLobLocator); if (dpiOci__lobLocatorAssign(tempLob, &tempLocator, error) < 0) { tempLob->locator = tempLocator; dpiLob__free(tempLob, error); return DPI_FAILURE; } tempLob->locator = tempLocator; data->value.asLOB = tempLob; return DPI_SUCCESS; } break; default: break; }; return dpiError__set(error, "from Oracle value", DPI_ERR_UNHANDLED_CONVERSION, valueOracleTypeNum, nativeTypeNum); } //----------------------------------------------------------------------------- // dpiObject__toOracleValue() [INTERNAL] // Convert value from external type to the OCI data type required. //----------------------------------------------------------------------------- static int dpiObject__toOracleValue(dpiObject *obj, dpiError *error, const dpiDataTypeInfo *dataTypeInfo, dpiOracleDataBuffer *buffer, dpiLob **lob, void **ociValue, int16_t *valueIndicator, void **objectIndicator, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiOracleTypeNum valueOracleTypeNum; uint32_t handleType; dpiObject *otherObj; dpiBytes *bytes; // nulls are handled easily *objectIndicator = NULL; if (data->isNull) { *ociValue = NULL; *valueIndicator = DPI_OCI_IND_NULL; buffer->asRaw = NULL; return DPI_SUCCESS; } // convert all other values *valueIndicator = DPI_OCI_IND_NOTNULL; valueOracleTypeNum = dataTypeInfo->oracleTypeNum; switch (valueOracleTypeNum) { case DPI_ORACLE_TYPE_CHAR: case DPI_ORACLE_TYPE_NCHAR: case DPI_ORACLE_TYPE_VARCHAR: case DPI_ORACLE_TYPE_NVARCHAR: buffer->asString = NULL; if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { bytes = &data->value.asBytes; if (dpiOci__stringAssignText(obj->env->handle, bytes->ptr, bytes->length, &buffer->asString, error) < 0) return DPI_FAILURE; *ociValue = buffer->asString; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_RAW: buffer->asRawData = NULL; if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { bytes = &data->value.asBytes; if (dpiOci__rawAssignBytes(obj->env->handle, bytes->ptr, bytes->length, &buffer->asRawData, error) < 0) return DPI_FAILURE; *ociValue = buffer->asRawData; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NATIVE_INT: if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { buffer->asInt32 = (int32_t) data->value.asInt64; *ociValue = &buffer->asInt32; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NUMBER: *ociValue = &buffer->asNumber; if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) return dpiDataBuffer__toOracleNumberFromInteger(&data->value, error, &buffer->asNumber); if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return dpiDataBuffer__toOracleNumberFromDouble(&data->value, error, &buffer->asNumber); if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) return dpiDataBuffer__toOracleNumberFromText(&data->value, obj->env, error, &buffer->asNumber); break; case DPI_ORACLE_TYPE_NATIVE_FLOAT: if (nativeTypeNum == DPI_NATIVE_TYPE_FLOAT) { buffer->asFloat = data->value.asFloat; *ociValue = &buffer->asFloat; return DPI_SUCCESS; } else if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { buffer->asFloat = (float) data->value.asDouble; *ociValue = &buffer->asFloat; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_NATIVE_DOUBLE: if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { buffer->asDouble = data->value.asDouble; *ociValue = &buffer->asDouble; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_DATE: *ociValue = &buffer->asDate; if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) return dpiDataBuffer__toOracleDate(&data->value, &buffer->asDate); if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return dpiDataBuffer__toOracleDateFromDouble(&data->value, obj->env, error, &buffer->asDate); break; case DPI_ORACLE_TYPE_TIMESTAMP: case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: buffer->asTimestamp = NULL; if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP || nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) { if (valueOracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ) { handleType = DPI_OCI_DTYPE_TIMESTAMP_LTZ; } else if (valueOracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP) { handleType = DPI_OCI_DTYPE_TIMESTAMP; } else { handleType = DPI_OCI_DTYPE_TIMESTAMP_TZ; } if (dpiOci__descriptorAlloc(obj->env->handle, &buffer->asTimestamp, handleType, "allocate timestamp", error) < 0) return DPI_FAILURE; *ociValue = buffer->asTimestamp; if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP) return dpiDataBuffer__toOracleTimestamp(&data->value, obj->env, error, buffer->asTimestamp, (valueOracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP)); return dpiDataBuffer__toOracleTimestampFromDouble(&data->value, valueOracleTypeNum, obj->env, error, buffer->asTimestamp); } break; case DPI_ORACLE_TYPE_OBJECT: otherObj = data->value.asObject; if (nativeTypeNum == DPI_NATIVE_TYPE_OBJECT) { if (otherObj->type->tdo != dataTypeInfo->objectType->tdo) return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, otherObj->type->schemaLength, otherObj->type->schema, otherObj->type->nameLength, otherObj->type->name, dataTypeInfo->objectType->schemaLength, dataTypeInfo->objectType->schema, dataTypeInfo->objectType->nameLength, dataTypeInfo->objectType->name); *ociValue = otherObj->instance; *objectIndicator = otherObj->indicator; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_BOOLEAN: if (nativeTypeNum == DPI_NATIVE_TYPE_BOOLEAN) { buffer->asBoolean = data->value.asBoolean; *ociValue = &buffer->asBoolean; return DPI_SUCCESS; } break; case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_BFILE: buffer->asLobLocator = NULL; if (nativeTypeNum == DPI_NATIVE_TYPE_LOB) { *ociValue = data->value.asLOB->locator; return DPI_SUCCESS; } else if (nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { const dpiOracleType *lobType; lobType = dpiOracleType__getFromNum(valueOracleTypeNum, error); if (dpiLob__allocate(obj->type->conn, lobType, lob, error) < 0) return DPI_FAILURE; bytes = &data->value.asBytes; if (dpiLob__setFromBytes(*lob, bytes->ptr, bytes->length, error) < 0) return DPI_FAILURE; buffer->asLobLocator = (*lob)->locator; *ociValue = (*lob)->locator; return DPI_SUCCESS; } break; default: break; } return dpiError__set(error, "to Oracle value", DPI_ERR_UNHANDLED_CONVERSION, valueOracleTypeNum, nativeTypeNum); } //----------------------------------------------------------------------------- // dpiObject_addRef() [PUBLIC] // Add a reference to the object. //----------------------------------------------------------------------------- int dpiObject_addRef(dpiObject *obj) { return dpiGen__addRef(obj, DPI_HTYPE_OBJECT, __func__); } //----------------------------------------------------------------------------- // dpiObject_appendElement() [PUBLIC] // Append an element to the collection. //----------------------------------------------------------------------------- int dpiObject_appendElement(dpiObject *obj, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiOracleDataBuffer valueBuffer; int16_t scalarValueIndicator; dpiLob *lob = NULL; void *indicator; dpiError error; void *ociValue; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, data) status = dpiObject__toOracleValue(obj, &error, &obj->type->elementTypeInfo, &valueBuffer, &lob, &ociValue, &scalarValueIndicator, (void**) &indicator, nativeTypeNum, data); if (status == DPI_SUCCESS) { if (!indicator) indicator = &scalarValueIndicator; status = dpiOci__collAppend(obj->type->conn, ociValue, indicator, obj->instance, &error); } dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, obj->type->elementTypeInfo.oracleTypeNum); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_copy() [PUBLIC] // Create a copy of the object and return it. Return NULL upon error. //----------------------------------------------------------------------------- int dpiObject_copy(dpiObject *obj, dpiObject **copiedObj) { dpiObject *tempObj; dpiError error; if (dpiObject__check(obj, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(obj, copiedObj) if (dpiObject__allocate(obj->type, NULL, NULL, NULL, &tempObj, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); if (dpiOci__objectCopy(tempObj, obj->instance, obj->indicator, &error) < 0) { dpiObject__free(tempObj, &error); return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); } *copiedObj = tempObj; return dpiGen__endPublicFn(obj, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiObject_deleteElementByIndex() [PUBLIC] // Delete the element at the specified index in the collection. //----------------------------------------------------------------------------- int dpiObject_deleteElementByIndex(dpiObject *obj, int32_t index) { dpiError error; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); status = dpiOci__tableDelete(obj, index, &error); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getAttributeValue() [PUBLIC] // Get the value of the given attribute from the object. //----------------------------------------------------------------------------- int dpiObject_getAttributeValue(dpiObject *obj, dpiObjectAttr *attr, dpiNativeTypeNum nativeTypeNum, dpiData *data) { int16_t scalarValueIndicator; void *valueIndicator, *tdo; dpiOracleData value; dpiError error; int status; // validate parameters if (dpiObject__check(obj, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(obj, data) if (dpiGen__checkHandle(attr, DPI_HTYPE_OBJECT_ATTR, "get attribute value", &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); if (attr->belongsToType->tdo != obj->type->tdo) { dpiError__set(&error, "get attribute value", DPI_ERR_WRONG_ATTR, attr->nameLength, attr->name, obj->type->schemaLength, obj->type->schema, obj->type->nameLength, obj->type->name); return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); } // get attribute value if (dpiOci__objectGetAttr(obj, attr, &scalarValueIndicator, &valueIndicator, &value.asRaw, &tdo, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); // determine the proper null indicator if (!valueIndicator) valueIndicator = &scalarValueIndicator; // check to see if type is supported if (!attr->typeInfo.oracleTypeNum) { dpiError__set(&error, "get attribute value", DPI_ERR_UNHANDLED_DATA_TYPE, attr->typeInfo.ociTypeCode); return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); } // convert to output data format status = dpiObject__fromOracleValue(obj, &error, &attr->typeInfo, &value, (int16_t*) valueIndicator, nativeTypeNum, data); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getElementExistsByIndex() [PUBLIC] // Return boolean indicating if an element exists in the collection at the // specified index. //----------------------------------------------------------------------------- int dpiObject_getElementExistsByIndex(dpiObject *obj, int32_t index, int *exists) { dpiError error; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, exists) status = dpiOci__tableExists(obj, index, exists, &error); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getElementValueByIndex() [PUBLIC] // Return the element at the given index in the collection. //----------------------------------------------------------------------------- int dpiObject_getElementValueByIndex(dpiObject *obj, int32_t index, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiOracleData value; int exists, status; void *indicator; dpiError error; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, data) if (dpiOci__collGetElem(obj->type->conn, obj->instance, index, &exists, &value.asRaw, &indicator, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); if (!exists) { dpiError__set(&error, "get element value", DPI_ERR_INVALID_INDEX, index); return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); } status = dpiObject__fromOracleValue(obj, &error, &obj->type->elementTypeInfo, &value, (int16_t*) indicator, nativeTypeNum, data); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getFirstIndex() [PUBLIC] // Return the index of the first entry in the collection. //----------------------------------------------------------------------------- int dpiObject_getFirstIndex(dpiObject *obj, int32_t *index, int *exists) { dpiError error; int32_t size; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, index) DPI_CHECK_PTR_NOT_NULL(obj, exists) if (dpiOci__tableSize(obj, &size, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); *exists = (size != 0); if (*exists) status = dpiOci__tableFirst(obj, index, &error); else status = DPI_SUCCESS; return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getLastIndex() [PUBLIC] // Return the index of the last entry in the collection. //----------------------------------------------------------------------------- int dpiObject_getLastIndex(dpiObject *obj, int32_t *index, int *exists) { dpiError error; int32_t size; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, index) DPI_CHECK_PTR_NOT_NULL(obj, exists) if (dpiOci__tableSize(obj, &size, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); *exists = (size != 0); if (*exists) status = dpiOci__tableLast(obj, index, &error); else status = DPI_SUCCESS; return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getNextIndex() [PUBLIC] // Return the index of the next entry in the collection following the index // specified. If there is no next entry, exists is set to 0. //----------------------------------------------------------------------------- int dpiObject_getNextIndex(dpiObject *obj, int32_t index, int32_t *nextIndex, int *exists) { dpiError error; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, nextIndex) DPI_CHECK_PTR_NOT_NULL(obj, exists) status = dpiOci__tableNext(obj, index, nextIndex, exists, &error); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getPrevIndex() [PUBLIC] // Return the index of the previous entry in the collection preceding the // index specified. If there is no previous entry, exists is set to 0. //----------------------------------------------------------------------------- int dpiObject_getPrevIndex(dpiObject *obj, int32_t index, int32_t *prevIndex, int *exists) { dpiError error; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, prevIndex) DPI_CHECK_PTR_NOT_NULL(obj, exists) status = dpiOci__tablePrev(obj, index, prevIndex, exists, &error); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_getSize() [PUBLIC] // Return the size of the collection. //----------------------------------------------------------------------------- int dpiObject_getSize(dpiObject *obj, int32_t *size) { dpiError error; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, size) status = dpiOci__collSize(obj->type->conn, obj->instance, size, &error); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_release() [PUBLIC] // Release a reference to the object. //----------------------------------------------------------------------------- int dpiObject_release(dpiObject *obj) { return dpiGen__release(obj, DPI_HTYPE_OBJECT, __func__); } //----------------------------------------------------------------------------- // dpiObject_setAttributeValue() [PUBLIC] // Create a copy of the object and return it. Return NULL upon error. //----------------------------------------------------------------------------- int dpiObject_setAttributeValue(dpiObject *obj, dpiObjectAttr *attr, dpiNativeTypeNum nativeTypeNum, dpiData *data) { void *valueIndicator, *ociValue; dpiOracleDataBuffer valueBuffer; int16_t scalarValueIndicator; dpiLob *lob = NULL; dpiError error; int status; // validate parameters if (dpiObject__check(obj, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(obj, data) if (dpiGen__checkHandle(attr, DPI_HTYPE_OBJECT_ATTR, "set attribute value", &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); if (attr->belongsToType->tdo != obj->type->tdo) { dpiError__set(&error, "set attribute value", DPI_ERR_WRONG_ATTR, attr->nameLength, attr->name, obj->type->schemaLength, obj->type->schema, obj->type->nameLength, obj->type->name); return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); } // check to see if type is supported if (!attr->typeInfo.oracleTypeNum) { dpiError__set(&error, "get attribute value", DPI_ERR_UNHANDLED_DATA_TYPE, attr->typeInfo.ociTypeCode); return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); } // convert to input data format status = dpiObject__toOracleValue(obj, &error, &attr->typeInfo, &valueBuffer, &lob, &ociValue, &scalarValueIndicator, &valueIndicator, nativeTypeNum, data); // set attribute value if (status == DPI_SUCCESS) status = dpiOci__objectSetAttr(obj, attr, scalarValueIndicator, valueIndicator, ociValue, &error); dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, attr->typeInfo.oracleTypeNum); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_setElementValueByIndex() [PUBLIC] // Set the element at the specified index to the given value. //----------------------------------------------------------------------------- int dpiObject_setElementValueByIndex(dpiObject *obj, int32_t index, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiOracleDataBuffer valueBuffer; int16_t scalarValueIndicator; dpiLob *lob = NULL; void *indicator; dpiError error; void *ociValue; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(obj, data) status = dpiObject__toOracleValue(obj, &error, &obj->type->elementTypeInfo, &valueBuffer, &lob, &ociValue, &scalarValueIndicator, (void**) &indicator, nativeTypeNum, data); if (status == DPI_SUCCESS) { if (!indicator) indicator = &scalarValueIndicator; status = dpiOci__collAssignElem(obj->type->conn, index, ociValue, indicator, obj->instance, &error); } dpiObject__clearOracleValue(obj, &error, &valueBuffer, lob, obj->type->elementTypeInfo.oracleTypeNum); return dpiGen__endPublicFn(obj, status, &error); } //----------------------------------------------------------------------------- // dpiObject_trim() [PUBLIC] // Trim a number of elements from the end of the collection. //----------------------------------------------------------------------------- int dpiObject_trim(dpiObject *obj, uint32_t numToTrim) { dpiError error; int status; if (dpiObject__checkIsCollection(obj, __func__, &error) < 0) return dpiGen__endPublicFn(obj, DPI_FAILURE, &error); status = dpiOci__collTrim(obj->type->conn, numToTrim, obj->instance, &error); return dpiGen__endPublicFn(obj, status, &error); } odpi-5.6.4/src/dpiObjectAttr.c000066400000000000000000000123741510466437300161720ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiObjectAttr.c // Implementation of object attributes. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiObjectAttr__allocate() [INTERNAL] // Allocate and initialize an object attribute structure. //----------------------------------------------------------------------------- int dpiObjectAttr__allocate(dpiObjectType *objType, void *param, dpiObjectAttr **attr, dpiError *error) { dpiObjectAttr *tempAttr; // allocate and assign main reference to the type this attribute belongs to *attr = NULL; if (dpiGen__allocate(DPI_HTYPE_OBJECT_ATTR, objType->env, (void**) &tempAttr, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(objType, error, 1); tempAttr->belongsToType = objType; // determine the name of the attribute if (dpiUtils__getAttrStringWithDup("get name", param, DPI_OCI_DTYPE_PARAM, DPI_OCI_ATTR_NAME, &tempAttr->name, &tempAttr->nameLength, error) < 0) { dpiObjectAttr__free(tempAttr, error); return DPI_FAILURE; } // determine type information of the attribute if (dpiOracleType__populateTypeInfo(objType->conn, param, DPI_OCI_DTYPE_PARAM, &tempAttr->typeInfo, error) < 0) { dpiObjectAttr__free(tempAttr, error); return DPI_FAILURE; } *attr = tempAttr; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObjectAttr__free() [INTERNAL] // Free the memory for an object attribute. //----------------------------------------------------------------------------- void dpiObjectAttr__free(dpiObjectAttr *attr, dpiError *error) { if (attr->belongsToType) { dpiGen__setRefCount(attr->belongsToType, error, -1); attr->belongsToType = NULL; } if (attr->typeInfo.objectType) { dpiGen__setRefCount(attr->typeInfo.objectType, error, -1); attr->typeInfo.objectType = NULL; } if (attr->name) { dpiUtils__freeMemory((void*) attr->name); attr->name = NULL; } dpiUtils__freeMemory(attr); } //----------------------------------------------------------------------------- // dpiObjectAttr_addRef() [PUBLIC] // Add a reference to the object attribute. //----------------------------------------------------------------------------- int dpiObjectAttr_addRef(dpiObjectAttr *attr) { return dpiGen__addRef(attr, DPI_HTYPE_OBJECT_ATTR, __func__); } //----------------------------------------------------------------------------- // dpiObjectAttr_getInfo() [PUBLIC] // Return information about the attribute to the caller. //----------------------------------------------------------------------------- int dpiObjectAttr_getInfo(dpiObjectAttr *attr, dpiObjectAttrInfo *info) { dpiError error; if (dpiGen__startPublicFn(attr, DPI_HTYPE_OBJECT_ATTR, __func__, &error) < 0) return dpiGen__endPublicFn(attr, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(attr, info) info->name = attr->name; info->nameLength = attr->nameLength; // the size of the dpiDataTypeInfo structure changed in version 5.1 and // again in 5.2; this check and memcpy() for older versions can be removed // once 6.0 is released if (attr->env->context->dpiMinorVersion > 1) { info->typeInfo = attr->typeInfo; } else if (attr->env->context->dpiMinorVersion == 1) { memcpy(&info->typeInfo, &attr->typeInfo, sizeof(dpiDataTypeInfo__v51)); } else { memcpy(&info->typeInfo, &attr->typeInfo, sizeof(dpiDataTypeInfo__v50)); } return dpiGen__endPublicFn(attr, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiObjectAttr_release() [PUBLIC] // Release a reference to the object attribute. //----------------------------------------------------------------------------- int dpiObjectAttr_release(dpiObjectAttr *attr) { return dpiGen__release(attr, DPI_HTYPE_OBJECT_ATTR, __func__); } odpi-5.6.4/src/dpiObjectType.c000066400000000000000000000356471510466437300162110ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiObjectType.c // Implementation of object types. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static int dpiObjectType__init(dpiObjectType *objType, void *handle, uint32_t handleType, dpiError *error); //----------------------------------------------------------------------------- // dpiObjectType__allocate() [INTERNAL] // Allocate and initialize an object type structure. //----------------------------------------------------------------------------- int dpiObjectType__allocate(dpiConn *conn, void *handle, uint32_t handleType, dpiObjectType **objType, dpiError *error) { dpiObjectType *tempObjType; // create structure and retain reference to connection *objType = NULL; if (dpiGen__allocate(DPI_HTYPE_OBJECT_TYPE, conn->env, (void**) &tempObjType, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempObjType->conn = conn; // perform initialization if (dpiObjectType__init(tempObjType, handle, handleType, error) < 0) { dpiObjectType__free(tempObjType, error); return DPI_FAILURE; } *objType = tempObjType; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObjectType__check() [INTERNAL] // Validate that the connection from which the object type was created is // still connected and issue an error if it is not. //----------------------------------------------------------------------------- static int dpiObjectType__check(dpiObjectType *objType, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(objType, DPI_HTYPE_OBJECT_TYPE, fnName, error) < 0) return DPI_FAILURE; return dpiConn__checkConnected(objType->conn, error); } //----------------------------------------------------------------------------- // dpiObjectType__describe() [INTERNAL] // Describe the object type and store information about it. Note that a // separate call to OCIDescribeAny() is made in order to support nested types; // an illegal attribute value is returned if this is not done. //----------------------------------------------------------------------------- static int dpiObjectType__describe(dpiObjectType *objType, void *describeHandle, dpiError *error) { void *collectionParam, *param; uint16_t typeCode; // describe the type if (dpiOci__describeAny(objType->conn, objType->tdo, 0, DPI_OCI_OTYPE_PTR, describeHandle, error) < 0) return DPI_FAILURE; // get top level parameter descriptor if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, ¶m, 0, DPI_OCI_ATTR_PARAM, "get top level parameter", error) < 0) return DPI_FAILURE; // determine type code if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, &typeCode, 0, DPI_OCI_ATTR_TYPECODE, "get type code", error) < 0) return DPI_FAILURE; objType->typeCode = typeCode; // determine the schema of the type if (dpiUtils__getAttrStringWithDup("get schema", param, DPI_OCI_DTYPE_PARAM, DPI_OCI_ATTR_SCHEMA_NAME, &objType->schema, &objType->schemaLength, error) < 0) return DPI_FAILURE; // determine the name of the type if (dpiUtils__getAttrStringWithDup("get name", param, DPI_OCI_DTYPE_PARAM, DPI_OCI_ATTR_NAME, &objType->name, &objType->nameLength, error) < 0) return DPI_FAILURE; // determine the package name of the type if (objType->env->versionInfo->versionNum > 11) { if (dpiUtils__getAttrStringWithDup("get package name", param, DPI_OCI_DTYPE_PARAM, DPI_OCI_ATTR_PACKAGE_NAME, &objType->packageName, &objType->packageNameLength, error) < 0) return DPI_FAILURE; } // determine the number of attributes if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, (void*) &objType->numAttributes, 0, DPI_OCI_ATTR_NUM_TYPE_ATTRS, "get number of attributes", error) < 0) return DPI_FAILURE; // if a collection, need to determine the element type if (typeCode == DPI_SQLT_NCO) { objType->isCollection = 1; // acquire collection parameter descriptor if (dpiOci__attrGet(param, DPI_OCI_DTYPE_PARAM, &collectionParam, 0, DPI_OCI_ATTR_COLLECTION_ELEMENT, "get collection descriptor", error) < 0) return DPI_FAILURE; // determine type of element if (dpiOracleType__populateTypeInfo(objType->conn, collectionParam, DPI_OCI_DTYPE_PARAM, &objType->elementTypeInfo, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObjectType__free() [INTERNAL] // Free the memory for an object type. //----------------------------------------------------------------------------- void dpiObjectType__free(dpiObjectType *objType, dpiError *error) { if (objType->conn) { dpiGen__setRefCount(objType->conn, error, -1); objType->conn = NULL; } if (objType->elementTypeInfo.objectType) { dpiGen__setRefCount(objType->elementTypeInfo.objectType, error, -1); objType->elementTypeInfo.objectType = NULL; } if (objType->schema) { dpiUtils__freeMemory((void*) objType->schema); objType->schema = NULL; } if (objType->name) { dpiUtils__freeMemory((void*) objType->name); objType->name = NULL; } if (objType->packageName) { dpiUtils__freeMemory((void*) objType->packageName); objType->packageName = NULL; } dpiUtils__freeMemory(objType); } //----------------------------------------------------------------------------- // dpiObjectType__init() [INTERNAL] // Initialize the object type. //----------------------------------------------------------------------------- static int dpiObjectType__init(dpiObjectType *objType, void *handle, uint32_t handleType, dpiError *error) { void *describeHandle, *tdoReference; // retrieve TDO of the parameter and pin it in the cache if (dpiOci__attrGet(handle, handleType, (void*) &tdoReference, 0, DPI_OCI_ATTR_REF_TDO, "get TDO reference", error) < 0) return DPI_FAILURE; if (dpiOci__objectPin(objType->env->handle, tdoReference, &objType->tdo, error) < 0) return DPI_FAILURE; // acquire a describe handle if (dpiOci__handleAlloc(objType->env->handle, &describeHandle, DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", error) < 0) return DPI_FAILURE; // describe the type if (dpiObjectType__describe(objType, describeHandle, error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return DPI_FAILURE; } // free the describe handle dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiObjectType__isXmlType() [INTERNAL] // Returns a boolean indicating if the object type in question refers to the // type SYS.XMLTYPE. //----------------------------------------------------------------------------- int dpiObjectType__isXmlType(dpiObjectType *objType) { static const char *schema = "SYS", *name = "XMLTYPE"; size_t schemaLength, nameLength; schemaLength = strlen(schema); nameLength = strlen(name); return (objType->schemaLength == schemaLength && strncmp(objType->schema, schema, schemaLength) == 0 && objType->nameLength == nameLength && strncmp(objType->name, name, nameLength) == 0); } //----------------------------------------------------------------------------- // dpiObjectType_addRef() [PUBLIC] // Add a reference to the object type. //----------------------------------------------------------------------------- int dpiObjectType_addRef(dpiObjectType *objType) { return dpiGen__addRef(objType, DPI_HTYPE_OBJECT_TYPE, __func__); } //----------------------------------------------------------------------------- // dpiObjectType_createObject() [PUBLIC] // Create a new object of the specified type and return it. Return NULL on // error. //----------------------------------------------------------------------------- int dpiObjectType_createObject(dpiObjectType *objType, dpiObject **obj) { dpiError error; int status; // validate parameters if (dpiObjectType__check(objType, __func__, &error) < 0) return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(objType, obj) status = dpiObject__allocate(objType, NULL, NULL, NULL, obj, &error); return dpiGen__endPublicFn(objType, status, &error); } //----------------------------------------------------------------------------- // dpiObjectType_getAttributes() [PUBLIC] // Get the attributes for the object type in the provided array. //----------------------------------------------------------------------------- int dpiObjectType_getAttributes(dpiObjectType *objType, uint16_t numAttributes, dpiObjectAttr **attributes) { void *topLevelParam, *attrListParam, *attrParam, *describeHandle; dpiError error; uint16_t i; // validate object type and the number of attributes if (dpiObjectType__check(objType, __func__, &error) < 0) return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(objType, attributes) if (numAttributes < objType->numAttributes) { dpiError__set(&error, "get attributes", DPI_ERR_ARRAY_SIZE_TOO_SMALL, numAttributes); return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); } if (numAttributes == 0) return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); // acquire a describe handle if (dpiOci__handleAlloc(objType->env->handle, &describeHandle, DPI_OCI_HTYPE_DESCRIBE, "allocate describe handle", &error) < 0) return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); // describe the type if (dpiOci__describeAny(objType->conn, objType->tdo, 0, DPI_OCI_OTYPE_PTR, describeHandle, &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); } // get the top level parameter descriptor if (dpiOci__attrGet(describeHandle, DPI_OCI_HTYPE_DESCRIBE, &topLevelParam, 0, DPI_OCI_ATTR_PARAM, "get top level param", &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); } // get the attribute list parameter descriptor if (dpiOci__attrGet(topLevelParam, DPI_OCI_DTYPE_PARAM, (void*) &attrListParam, 0, DPI_OCI_ATTR_LIST_TYPE_ATTRS, "get attr list param", &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); } // create attribute structure for each attribute for (i = 0; i < objType->numAttributes; i++) { if (dpiOci__paramGet(attrListParam, DPI_OCI_DTYPE_PARAM, &attrParam, (uint32_t) i + 1, "get attribute param", &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); } if (dpiObjectAttr__allocate(objType, attrParam, &attributes[i], &error) < 0) { dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); } } // free the describe handle dpiOci__handleFree(describeHandle, DPI_OCI_HTYPE_DESCRIBE); return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiObjectType_getInfo() [PUBLIC] // Return information about the object type. //----------------------------------------------------------------------------- int dpiObjectType_getInfo(dpiObjectType *objType, dpiObjectTypeInfo *info) { dpiError error; if (dpiGen__startPublicFn(objType, DPI_HTYPE_OBJECT_TYPE, __func__, &error) < 0) return dpiGen__endPublicFn(objType, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(objType, info) info->name = objType->name; info->nameLength = objType->nameLength; info->packageName = objType->packageName; info->packageNameLength = objType->packageNameLength; info->schema = objType->schema; info->schemaLength = objType->schemaLength; info->isCollection = objType->isCollection; info->numAttributes = objType->numAttributes; // the size of the dpiDataTypeInfo structure changed in version 5.1 and // again in 5.2; this check and memcpy() for older versions can be removed // once 6.0 is released if (objType->env->context->dpiMinorVersion > 1) { info->elementTypeInfo = objType->elementTypeInfo; } else if (objType->env->context->dpiMinorVersion == 1) { memcpy(&info->elementTypeInfo, &objType->elementTypeInfo, sizeof(dpiDataTypeInfo__v51)); } else { memcpy(&info->elementTypeInfo, &objType->elementTypeInfo, sizeof(dpiDataTypeInfo__v50)); } return dpiGen__endPublicFn(objType, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiObjectType_release() [PUBLIC] // Release a reference to the object type. //----------------------------------------------------------------------------- int dpiObjectType_release(dpiObjectType *objType) { return dpiGen__release(objType, DPI_HTYPE_OBJECT_TYPE, __func__); } odpi-5.6.4/src/dpiOci.c000066400000000000000000005640421510466437300146470ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiOci.c // Link to OCI using dynamic linking. The OCI library (11.2+) is loaded // dynamically and a function table kept for the functions that are used by // DPI. This function table is populated as functions are used and permits use // of all versions of OCI from one driver. //----------------------------------------------------------------------------- #include "dpiImpl.h" // define structure used for loading the OCI library typedef struct { void *handle; char *nameBuffer; size_t nameBufferLength; char *moduleNameBuffer; size_t moduleNameBufferLength; char *loadError; size_t loadErrorLength; char *errorBuffer; size_t errorBufferLength; char *envBuffer; size_t envBufferLength; char **configDir; } dpiOciLoadLibParams; // forward declarations of internal functions only used in this file static void *dpiOci__allocateMem(void *unused, size_t size); static void dpiOci__freeMem(void *unused, void *ptr); static int dpiOci__loadLibValidate(dpiContextCreateParams *params, dpiOciLoadLibParams *loadParams, dpiVersionInfo *versionInfo, dpiError *error); static int dpiOci__loadLibWithDir(dpiOciLoadLibParams *loadParams, const char *dirName, size_t dirNameLength, int scanAllNames, dpiError *error); static int dpiOci__loadLibWithName(dpiOciLoadLibParams *loadParams, const char *libName, dpiError *error); static int dpiOci__loadSymbol(const char *symbolName, void **symbol, dpiError *error); static void *dpiOci__reallocMem(void *unused, void *ptr, size_t newSize); // macro to simplify code for loading each symbol #define DPI_OCI_LOAD_SYMBOL(symbolName, symbol) \ if (!symbol && dpiOci__loadSymbol(symbolName, (void**) &symbol, \ error) < 0) \ return DPI_FAILURE; // macro to ensure that an error handle is available #define DPI_OCI_ENSURE_ERROR_HANDLE(error) \ if (!error->handle && dpiError__initHandle(error) < 0) \ return DPI_FAILURE; // macros to simplify code for checking results of OCI calls #define DPI_OCI_ERROR_OCCURRED(status) \ (status != DPI_OCI_SUCCESS && status != DPI_OCI_SUCCESS_WITH_INFO) #define DPI_OCI_CHECK_AND_RETURN(error, status, conn, action) \ if (status != DPI_OCI_SUCCESS) \ return dpiError__setFromOCI(error, status, conn, action); \ return DPI_SUCCESS; // macro to get the default mode to use when binding #define DPI_OCI_DEFAULT_BIND_MODE(stmt) \ (stmt->env->versionInfo->versionNum < 23 \ || (stmt->env->versionInfo->versionNum == 23 \ && stmt->env->versionInfo->releaseNum < 6)) ? DPI_OCI_DEFAULT : \ DPI_OCI_BIND_DEDICATED_REF_CURSOR // typedefs for all OCI functions used by ODPI-C typedef int (*dpiOciFnType__aqDeq)(void *svchp, void *errhp, const char *queue_name, void *deqopt, void *msgprop, void *payload_tdo, void **payload, void **payload_ind, void **msgid, uint32_t flags); typedef int (*dpiOciFnType__aqDeqArray)(void *svchp, void *errhp, const char *queue_name, void *deqopt, uint32_t *iters, void **msgprop, void *payload_tdo, void **payload, void **payload_ind, void **msgid, void *ctxp, void *deqcbfp, uint32_t flags); typedef int (*dpiOciFnType__aqEnq)(void *svchp, void *errhp, const char *queue_name, void *enqopt, void *msgprop, void *payload_tdo, void **payload, void **payload_ind, void **msgid, uint32_t flags); typedef int (*dpiOciFnType__aqEnqArray)(void *svchp, void *errhp, const char *queue_name, void *enqopt, uint32_t *iters, void **msgprop, void *payload_tdo, void **payload, void **payload_ind, void **msgid, void *ctxp, void *enqcbfp, uint32_t flags); typedef int (*dpiOciFnType__arrayDescriptorAlloc)(const void *parenth, void **descpp, const uint32_t type, uint32_t array_size, const size_t xtramem_sz, void **usrmempp); typedef int (*dpiOciFnType__arrayDescriptorFree)(void **descp, const uint32_t type); typedef int (*dpiOciFnType__attrGet)(const void *trgthndlp, uint32_t trghndltyp, void *attributep, uint32_t *sizep, uint32_t attrtype, void *errhp); typedef int (*dpiOciFnType__attrSet)(void *trgthndlp, uint32_t trghndltyp, void *attributep, uint32_t size, uint32_t attrtype, void *errhp); typedef int (*dpiOciFnType__bindByName)(void *stmtp, void **bindp, void *errhp, const char *placeholder, int32_t placeh_len, void *valuep, int32_t value_sz, uint16_t dty, void *indp, uint16_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, uint32_t mode); typedef int (*dpiOciFnType__bindByName2)(void *stmtp, void **bindp, void *errhp, const char *placeholder, int32_t placeh_len, void *valuep, int64_t value_sz, uint16_t dty, void *indp, uint32_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, uint32_t mode); typedef int (*dpiOciFnType__bindByPos)(void *stmtp, void **bindp, void *errhp, uint32_t position, void *valuep, int32_t value_sz, uint16_t dty, void *indp, uint16_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, uint32_t mode); typedef int (*dpiOciFnType__bindByPos2)(void *stmtp, void **bindp, void *errhp, uint32_t position, void *valuep, int64_t value_sz, uint16_t dty, void *indp, uint32_t *alenp, uint16_t *rcodep, uint32_t maxarr_len, uint32_t *curelep, uint32_t mode); typedef int (*dpiOciFnType__bindDynamic)(void *bindp, void *errhp, void *ictxp, void *icbfp, void *octxp, void *ocbfp); typedef int (*dpiOciFnType__bindObject)(void *bindp, void *errhp, const void *type, void **pgvpp, uint32_t *pvszsp, void **indpp, uint32_t *indszp); typedef int (*dpiOciFnType__break)(void *hndlp, void *errhp); typedef void (*dpiOciFnType__clientVersion)(int *major_version, int *minor_version, int *update_num, int *patch_num, int *port_update_num); typedef int (*dpiOciFnType__collAppend)(void *env, void *err, const void *elem, const void *elemind, void *coll); typedef int (*dpiOciFnType__collAssignElem)(void *env, void *err, int32_t index, const void *elem, const void *elemind, void *coll); typedef int (*dpiOciFnType__collGetElem)(void *env, void *err, const void *coll, int32_t index, int *exists, void **elem, void **elemind); typedef int (*dpiOciFnType__collSize)(void *env, void *err, const void *coll, int32_t *size); typedef int (*dpiOciFnType__collTrim)(void *env, void *err, int32_t trim_num, void *coll); typedef int (*dpiOciFnType__contextGetValue)(void *hdl, void *err, const char *key, uint8_t keylen, void **ctx_value); typedef int (*dpiOciFnType__contextSetValue)(void *hdl, void *err, uint16_t duration, const char *key, uint8_t keylen, void *ctx_value); typedef int (*dpiOciFnType__dateTimeConstruct)(void *hndl, void *err, void *datetime, int16_t yr, uint8_t mnth, uint8_t dy, uint8_t hr, uint8_t mm, uint8_t ss, uint32_t fsec, const char *tz, size_t tzLength); typedef int (*dpiOciFnType__dateTimeConvert)(void *hndl, void *err, void *indate, void *outdate); typedef int (*dpiOciFnType__dateTimeGetDate)(void *hndl, void *err, const void *date, int16_t *yr, uint8_t *mnth, uint8_t *dy); typedef int (*dpiOciFnType__dateTimeGetTime)(void *hndl, void *err, void *datetime, uint8_t *hr, uint8_t *mm, uint8_t *ss, uint32_t *fsec); typedef int (*dpiOciFnType__dateTimeGetTimeZoneOffset)(void *hndl, void *err, const void *datetime, int8_t *hr, int8_t *mm); typedef int (*dpiOciFnType__dateTimeIntervalAdd)(void *hndl, void *err, void *datetime, void *inter, void *outdatetime); typedef int (*dpiOciFnType__dateTimeSubtract)(void *hndl, void *err, void *indate1, void *indate2, void *inter); typedef int (*dpiOciFnType__dbShutdown)(void *svchp, void *errhp, void *admhp, uint32_t mode); typedef int (*dpiOciFnType__dbStartup)(void *svchp, void *errhp, void *admhp, uint32_t mode, uint32_t flags); typedef int (*dpiOciFnType__defineByPos)(void *stmtp, void **defnp, void *errhp, uint32_t position, void *valuep, int32_t value_sz, uint16_t dty, void *indp, uint16_t *rlenp, uint16_t *rcodep, uint32_t mode); typedef int (*dpiOciFnType__defineByPos2)(void *stmtp, void **defnp, void *errhp, uint32_t position, void *valuep, uint64_t value_sz, uint16_t dty, void *indp, uint32_t *rlenp, uint16_t *rcodep, uint32_t mode); typedef int (*dpiOciFnType__defineDynamic)(void *defnp, void *errhp, void *octxp, void *ocbfp); typedef int (*dpiOciFnType__defineObject)(void *defnp, void *errhp, const void *type, void **pgvpp, uint32_t *pvszsp, void **indpp, uint32_t *indszp); typedef int (*dpiOciFnType__describeAny)(void *svchp, void *errhp, void *objptr, uint32_t objnm_len, uint8_t objptr_typ, uint8_t info_level, uint8_t objtyp, void *dschp); typedef int (*dpiOciFnType__descriptorAlloc)(const void *parenth, void **descpp, const uint32_t type, const size_t xtramem_sz, void **usrmempp); typedef int (*dpiOciFnType__descriptorFree)(void *descp, const uint32_t type); typedef int (*dpiOciFnType__envNlsCreate)(void **envp, uint32_t mode, void *ctxp, void *malocfp, void *ralocfp, void *mfreefp, size_t xtramem_sz, void **usrmempp, uint16_t charset, uint16_t ncharset); typedef int (*dpiOciFnType__errorGet)(void *hndlp, uint32_t recordno, char *sqlstate, int32_t *errcodep, char *bufp, uint32_t bufsiz, uint32_t type); typedef int (*dpiOciFnType__handleAlloc)(const void *parenth, void **hndlpp, const uint32_t type, const size_t xtramem_sz, void **usrmempp); typedef int (*dpiOciFnType__handleFree)(void *hndlp, const uint32_t type); typedef int (*dpiOciFnType__intervalGetDaySecond)(void *hndl, void *err, int32_t *dy, int32_t *hr, int32_t *mm, int32_t *ss, int32_t *fsec, const void *result); typedef int (*dpiOciFnType__intervalGetYearMonth)(void *hndl, void *err, int32_t *yr, int32_t *mnth, const void *result); typedef int (*dpiOciFnType__intervalSetDaySecond)(void *hndl, void *err, int32_t dy, int32_t hr, int32_t mm, int32_t ss, int32_t fsec, void *result); typedef int (*dpiOciFnType__intervalSetYearMonth)(void *hndl, void *err, int32_t yr, int32_t mnth, void *result); typedef int (*dpiOciFnType__jsonDomDocGet)(void *svchp, void *jsond, dpiJznDomDoc **jDomDoc, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__jsonTextBufferParse)(void *hndlp, void *jsond, void *bufp, uint64_t buf_sz, uint32_t validation, uint16_t encoding, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__lobClose)(void *svchp, void *errhp, void *locp); typedef int (*dpiOciFnType__lobCreateTemporary)(void *svchp, void *errhp, void *locp, uint16_t csid, uint8_t csfrm, uint8_t lobtype, int cache, uint16_t duration); typedef int (*dpiOciFnType__lobFileExists)(void *svchp, void *errhp, void *filep, int *flag); typedef int (*dpiOciFnType__lobFileGetName)(void *envhp, void *errhp, const void *filep, char *dir_alias, uint16_t *d_length, char *filename, uint16_t *f_length); typedef int (*dpiOciFnType__lobFileSetName)(void *envhp, void *errhp, void **filepp, const char *dir_alias, uint16_t d_length, const char *filename, uint16_t f_length); typedef int (*dpiOciFnType__lobFreeTemporary)(void *svchp, void *errhp, void *locp); typedef int (*dpiOciFnType__lobGetChunkSize)(void *svchp, void *errhp, void *locp, uint32_t *chunksizep); typedef int (*dpiOciFnType__lobGetLength2)(void *svchp, void *errhp, void *locp, uint64_t *lenp); typedef int (*dpiOciFnType__lobIsOpen)(void *svchp, void *errhp, void *locp, int *flag); typedef int (*dpiOciFnType__lobIsTemporary)(void *envp, void *errhp, void *locp, int *is_temporary); typedef int (*dpiOciFnType__lobLocatorAssign)(void *svchp, void *errhp, const void *src_locp, void **dst_locpp); typedef int (*dpiOciFnType__lobOpen)(void *svchp, void *errhp, void *locp, uint8_t mode); typedef int (*dpiOciFnType__lobRead2)(void *svchp, void *errhp, void *locp, uint64_t *byte_amtp, uint64_t *char_amtp, uint64_t offset, void *bufp, uint64_t bufl, uint8_t piece, void *ctxp, void *cbfp, uint16_t csid, uint8_t csfrm); typedef int (*dpiOciFnType__lobTrim2)(void *svchp, void *errhp, void *locp, uint64_t newlen); typedef int (*dpiOciFnType__lobWrite2)(void *svchp, void *errhp, void *locp, uint64_t *byte_amtp, uint64_t *char_amtp, uint64_t offset, void *bufp, uint64_t buflen, uint8_t piece, void *ctxp, void *cbfp, uint16_t csid, uint8_t csfrm); typedef int (*dpiOciFnType__memoryAlloc)(void *hdl, void *err, void **mem, uint16_t dur, uint32_t size, uint32_t flags); typedef int (*dpiOciFnType__memoryFree)(void *hdl, void *err, void *mem); typedef int (*dpiOciFnType__nlsCharSetConvert)(void *envhp, void *errhp, uint16_t dstid, void *dstp, size_t dstlen, uint16_t srcid, const void *srcp, size_t srclen, size_t *rsize); typedef int (*dpiOciFnType__nlsCharSetIdToName)(void *envhp, char *buf, size_t buflen, uint16_t id); typedef uint16_t (*dpiOciFnType__nlsCharSetNameToId)(void *envhp, const char *name); typedef int (*dpiOciFnType__nlsEnvironmentVariableGet)(void *val, size_t size, uint16_t item, uint16_t charset, size_t *rsize); typedef int (*dpiOciFnType__nlsNameMap)(void *envhp, char *buf, size_t buflen, const char *srcbuf, uint32_t flag); typedef int (*dpiOciFnType__nlsNumericInfoGet)(void *envhp, void *errhp, int32_t *val, uint16_t item); typedef int (*dpiOciFnType__numberFromInt)(void *err, const void *inum, unsigned int inum_length, unsigned int inum_s_flag, void *number); typedef int (*dpiOciFnType__numberFromReal)(void *err, const void *number, unsigned int rsl_length, void *rsl); typedef int (*dpiOciFnType__numberToInt)(void *err, const void *number, unsigned int rsl_length, unsigned int rsl_flag, void *rsl); typedef int (*dpiOciFnType__numberToReal)(void *err, const void *number, unsigned int rsl_length, void *rsl); typedef int (*dpiOciFnType__objectCopy)(void *env, void *err, const void *svc, void *source, void *null_source, void *target, void *null_target, void *tdo, uint16_t duration, uint8_t option); typedef int (*dpiOciFnType__objectFree)(void *env, void *err, void *instance, uint16_t flags); typedef int (*dpiOciFnType__objectGetAttr)(void *env, void *err, void *instance, void *null_struct, void *tdo, const char **names, const uint32_t *lengths, const uint32_t name_count, const uint32_t *indexes, const uint32_t index_count, int16_t *attr_null_status, void **attr_null_struct, void **attr_value, void **attr_tdo); typedef int (*dpiOciFnType__objectGetInd)(void *env, void *err, void *instance, void **null_struct); typedef int (*dpiOciFnType__objectNew)(void *env, void *err, const void *svc, uint16_t typecode, void *tdo, void *table, uint16_t duration, int value, void **instance); typedef int (*dpiOciFnType__objectPin)(void *env, void *err, void *object_ref, void *corhdl, int pin_option, uint16_t pin_duration, int lock_option, void **object); typedef int (*dpiOciFnType__objectSetAttr)(void *env, void *err, void *instance, void *null_struct, void *tdo, const char **names, const uint32_t *lengths, const uint32_t name_count, const uint32_t *indexes, const uint32_t index_count, const int16_t null_status, const void *attr_null_struct, const void *attr_value); typedef int (*dpiOciFnType__paramGet)(const void *hndlp, uint32_t htype, void *errhp, void **parmdpp, uint32_t pos); typedef int (*dpiOciFnType__passwordChange)(void *svchp, void *errhp, const char *user_name, uint32_t usernm_len, const char *opasswd, uint32_t opasswd_len, const char *npasswd, uint32_t npasswd_len, uint32_t mode); typedef int (*dpiOciFnType__ping)(void *svchp, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__rawAssignBytes)(void *env, void *err, const char *rhs, uint32_t rhs_len, void **lhs); typedef void *(*dpiOciFnType__rawPtr)(void *env, const void *raw); typedef int (*dpiOciFnType__rawResize)(void *env, void *err, uint32_t new_size, void **raw); typedef uint32_t (*dpiOciFnType__rawSize)(void * env, const void *raw); typedef int (*dpiOciFnType__rowidToChar)(void *rowidDesc, char *outbfp, uint16_t *outbflp, void *errhp); typedef int (*dpiOciFnType__serverAttach)(void *srvhp, void *errhp, const char *dblink, int32_t dblink_len, uint32_t mode); typedef int (*dpiOciFnType__serverDetach)(void *srvhp, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__serverRelease)(void *hndlp, void *errhp, char *bufp, uint32_t bufsz, uint8_t hndltype, uint32_t *version); typedef int (*dpiOciFnType__serverRelease2)(void *hndlp, void *errhp, char *bufp, uint32_t bufsz, uint8_t hndltype, uint32_t *version, uint32_t mode); typedef int (*dpiOciFnType__sessionBegin)(void *svchp, void *errhp, void *usrhp, uint32_t credt, uint32_t mode); typedef int (*dpiOciFnType__sessionEnd)(void *svchp, void *errhp, void *usrhp, uint32_t mode); typedef int (*dpiOciFnType__sessionGet)(void *envhp, void *errhp, void **svchp, void *authhp, const char *poolName, uint32_t poolName_len, const char *tagInfo, uint32_t tagInfo_len, const char **retTagInfo, uint32_t *retTagInfo_len, int *found, uint32_t mode); typedef int (*dpiOciFnType__sessionPoolCreate)(void *envhp, void *errhp, void *spoolhp, char **poolName, uint32_t *poolNameLen, const char *connStr, uint32_t connStrLen, uint32_t sessMin, uint32_t sessMax, uint32_t sessIncr, const char *userid, uint32_t useridLen, const char *password, uint32_t passwordLen, uint32_t mode); typedef int (*dpiOciFnType__sessionPoolDestroy)(void *spoolhp, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sessionRelease)(void *svchp, void *errhp, const char *tag, uint32_t tag_len, uint32_t mode); typedef int (*dpiOciFnType__shardingKeyColumnAdd)(void *shardingKey, void *errhp, void *col, uint32_t colLen, uint16_t colType, uint32_t mode); typedef int (*dpiOciFnType__sodaBulkInsert)(void *svchp, void *collection, void **documentarray, uint32_t arraylen, void *opoptns, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaBulkInsertAndGet)(void *svchp, void *collection, void **documentarray, uint32_t arraylen, void *opoptns, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaBulkInsertAndGetWithOpts)(void *svchp, void *collection, void **documentarray, uint32_t arraylen, void *oproptns, void *opoptns, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaCollCreateWithMetadata)(void *svchp, const char *collname, uint32_t collnamelen, const char *metadata, uint32_t metadatalen, void **collection, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaCollDrop)(void *svchp, void *coll, int *isDropped, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaCollGetNext)(void *svchp, const void *cur, void **coll, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaCollList)(void *svchp, const char *startname, uint32_t stnamelen, void **cur, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaCollOpen)(void *svchp, const char *collname, uint32_t collnamelen, void **coll, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaCollTruncate)(void *svchp, void *collection, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaDataGuideGet)(void *svchp, const void *collection, uint32_t docFlags, void **doc, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaDocCount)(void *svchp, const void *coll, const void *optns, uint64_t *numdocs, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaDocGetNext)(void *svchp, const void *cur, void **doc, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaFind)(void *svchp, const void *coll, const void *findOptions, uint32_t docFlags, void **cursor, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaFindOne)(void *svchp, const void *coll, const void *findOptions, uint32_t docFlags, void **doc, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaIndexCreate)(void *svchp, const void *coll, const char *indexspec, uint32_t speclen, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaIndexDrop)(void *svchp, const char *indexname, uint32_t indexnamelen, int *isDropped, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaIndexList)(void *svchp, const void *collection, uint32_t flags, void **indexList, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaInsert)(void *svchp, void *collection, void *document, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaInsertAndGet)(void *svchp, void *collection, void **document, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaInsertAndGetWithOpts)(void *svchp, void *collection, void **document, void *oproptns, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaOperKeysSet)(const void *operhp, const char **keysArray, uint32_t *lengthsArray, uint32_t count, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaRemove)(void *svchp, const void *coll, const void *optns, uint64_t *removeCount, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaReplOne)(void *svchp, const void *coll, const void *optns, void *document, int *isReplaced, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaReplOneAndGet)(void *svchp, const void *coll, const void *optns, void **document, int *isReplaced, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaSave)(void *svchp, void *collection, void *document, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaSaveAndGet)(void *svchp, void *collection, void **document, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__sodaSaveAndGetWithOpts)(void *svchp, void *collection, void **document, void *oproptns, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__stmtExecute)(void *svchp, void *stmtp, void *errhp, uint32_t iters, uint32_t rowoff, const void *snap_in, void *snap_out, uint32_t mode); typedef int (*dpiOciFnType__stmtFetch2)(void *stmtp, void *errhp, uint32_t nrows, uint16_t orientation, int32_t scrollOffset, uint32_t mode); typedef int (*dpiOciFnType__stmtGetBindInfo)(void *stmtp, void *errhp, uint32_t size, uint32_t startloc, int32_t *found, char *bvnp[], uint8_t bvnl[], char *invp[], uint8_t inpl[], uint8_t dupl[], void **hndl); typedef int (*dpiOciFnType__stmtGetNextResult)(void *stmthp, void *errhp, void **result, uint32_t *rtype, uint32_t mode); typedef int (*dpiOciFnType__stmtPrepare2)(void *svchp, void **stmtp, void *errhp, const char *stmt, uint32_t stmt_len, const char *key, uint32_t key_len, uint32_t language, uint32_t mode); typedef int (*dpiOciFnType__stmtRelease)(void *stmtp, void *errhp, const char *key, uint32_t key_len, uint32_t mode); typedef int (*dpiOciFnType__stringAssignText)(void *env, void *err, const char *rhs, uint32_t rhs_len, void **lhs); typedef char *(*dpiOciFnType__stringPtr)(void *env, const void *vs); typedef int (*dpiOciFnType__stringResize)(void *env, void *err, uint32_t new_size, void **str); typedef uint32_t (*dpiOciFnType__stringSize)(void *env, const void *vs); typedef int (*dpiOciFnType__subscriptionRegister)(void *svchp, void **subscrhpp, uint16_t count, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__subscriptionUnRegister)(void *svchp, void *subscrhp, void *errhp, uint32_t mode); typedef int (*dpiOciFnType__tableDelete)(void *env, void *err, int32_t index, void *tbl); typedef int (*dpiOciFnType__tableExists)(void *env, void *err, const void *tbl, int32_t index, int *exists); typedef int (*dpiOciFnType__tableFirst)(void *env, void *err, const void *tbl, int32_t *index); typedef int (*dpiOciFnType__tableLast)(void *env, void *err, const void *tbl, int32_t *index); typedef int (*dpiOciFnType__tableNext)(void *env, void *err, int32_t index, const void *tbl, int32_t *next_index, int *exists); typedef int (*dpiOciFnType__tablePrev)(void *env, void *err, int32_t index, const void *tbl, int32_t *prev_index, int *exists); typedef int (*dpiOciFnType__tableSize)(void *env, void *err, const void *tbl, int32_t *size); typedef int (*dpiOciFnType__threadKeyDestroy)(void *hndl, void *err, void **key); typedef int (*dpiOciFnType__threadKeyGet)(void *hndl, void *err, void *key, void **pValue); typedef int (*dpiOciFnType__threadKeyInit)(void *hndl, void *err, void **key, void *destFn); typedef int (*dpiOciFnType__threadKeySet)(void *hndl, void *err, void *key, void *value); typedef void (*dpiOciFnType__threadProcessInit)(void); typedef int (*dpiOciFnType__transCommit)(void *svchp, void *errhp, uint32_t flags); typedef int (*dpiOciFnType__transDetach)(void *svchp, void *errhp, uint32_t flags); typedef int (*dpiOciFnType__transForget)(void *svchp, void *errhp, uint32_t flags); typedef int (*dpiOciFnType__transPrepare)(void *svchp, void *errhp, uint32_t flags); typedef int (*dpiOciFnType__transRollback)(void *svchp, void *errhp, uint32_t flags); typedef int (*dpiOciFnType__transStart)(void *svchp, void *errhp, unsigned int timeout, uint32_t flags); typedef int (*dpiOciFnType__typeByFullName)(void *env, void *err, const void *svc, const char *full_type_name, uint32_t full_type_name_length, const char *version_name, uint32_t version_name_length, uint16_t pin_duration, int get_option, void **tdo); typedef int (*dpiOciFnType__typeByName)(void *env, void *err, const void *svc, const char *schema_name, uint32_t s_length, const char *type_name, uint32_t t_length, const char *version_name, uint32_t v_length, uint16_t pin_duration, int get_option, void **tdo); typedef int (*dpiOciFnType__vectorFromArray)(void *vectord, void *errhp, uint8_t vformat, uint32_t vdim, void *vecarray, uint32_t mode); typedef int (*dpiOciFnType__vectorFromSparseArray)(void *vectord, void *errhp, uint8_t vformat, uint32_t vdim, uint32_t indices, void *indarray, void *vecarray, uint32_t mode); typedef int (*dpiOciFnType__vectorToArray)(void *vectord, void *errhp, uint8_t vformat, uint32_t *vdim, void *vecarray, uint32_t mode); typedef int (*dpiOciFnType__vectorToSparseArray)(void *vectord, void *errhp, uint8_t vformat, uint32_t *vdim, uint32_t *indices, void *indarray, void *vecarray, uint32_t mode); // library handle for dynamically loaded OCI library static void *dpiOciLibHandle = NULL; // library names to search static const char *dpiOciLibNames[] = { #if defined _WIN32 || defined __CYGWIN__ "oci.dll", #elif __APPLE__ "libclntsh.dylib", "libclntsh.dylib.19.1", "libclntsh.dylib.18.1", "libclntsh.dylib.12.1", "libclntsh.dylib.11.1", "libclntsh.dylib.20.1", "libclntsh.dylib.21.1", #else "libclntsh.so", "libclntsh.so.19.1", "libclntsh.so.18.1", "libclntsh.so.12.1", "libclntsh.so.11.1", "libclntsh.so.20.1", "libclntsh.so.21.1", #endif NULL }; // subdirectory for configuration directory static const char *dpiOciConfigSubDir = "network/admin"; // all OCI symbols used by ODPI-C static struct { dpiOciFnType__aqDeq fnAqDeq; dpiOciFnType__aqDeqArray fnAqDeqArray; dpiOciFnType__aqEnq fnAqEnq; dpiOciFnType__aqEnqArray fnAqEnqArray; dpiOciFnType__arrayDescriptorAlloc fnArrayDescriptorAlloc; dpiOciFnType__arrayDescriptorFree fnArrayDescriptorFree; dpiOciFnType__attrGet fnAttrGet; dpiOciFnType__attrSet fnAttrSet; dpiOciFnType__bindByName fnBindByName; dpiOciFnType__bindByName2 fnBindByName2; dpiOciFnType__bindByPos fnBindByPos; dpiOciFnType__bindByPos2 fnBindByPos2; dpiOciFnType__bindDynamic fnBindDynamic; dpiOciFnType__bindObject fnBindObject; dpiOciFnType__break fnBreak; dpiOciFnType__clientVersion fnClientVersion; dpiOciFnType__collAppend fnCollAppend; dpiOciFnType__collAssignElem fnCollAssignElem; dpiOciFnType__collGetElem fnCollGetElem; dpiOciFnType__collSize fnCollSize; dpiOciFnType__collTrim fnCollTrim; dpiOciFnType__contextGetValue fnContextGetValue; dpiOciFnType__contextSetValue fnContextSetValue; dpiOciFnType__dateTimeConstruct fnDateTimeConstruct; dpiOciFnType__dateTimeConvert fnDateTimeConvert; dpiOciFnType__dateTimeGetDate fnDateTimeGetDate; dpiOciFnType__dateTimeGetTime fnDateTimeGetTime; dpiOciFnType__dateTimeGetTimeZoneOffset fnDateTimeGetTimeZoneOffset; dpiOciFnType__dateTimeIntervalAdd fnDateTimeIntervalAdd; dpiOciFnType__dateTimeSubtract fnDateTimeSubtract; dpiOciFnType__dbShutdown fnDbShutdown; dpiOciFnType__dbStartup fnDbStartup; dpiOciFnType__defineByPos fnDefineByPos; dpiOciFnType__defineByPos2 fnDefineByPos2; dpiOciFnType__defineDynamic fnDefineDynamic; dpiOciFnType__defineObject fnDefineObject; dpiOciFnType__describeAny fnDescribeAny; dpiOciFnType__descriptorAlloc fnDescriptorAlloc; dpiOciFnType__descriptorFree fnDescriptorFree; dpiOciFnType__envNlsCreate fnEnvNlsCreate; dpiOciFnType__errorGet fnErrorGet; dpiOciFnType__handleAlloc fnHandleAlloc; dpiOciFnType__handleFree fnHandleFree; dpiOciFnType__intervalGetDaySecond fnIntervalGetDaySecond; dpiOciFnType__intervalGetYearMonth fnIntervalGetYearMonth; dpiOciFnType__intervalSetDaySecond fnIntervalSetDaySecond; dpiOciFnType__intervalSetYearMonth fnIntervalSetYearMonth; dpiOciFnType__jsonDomDocGet fnJsonDomDocGet; dpiOciFnType__jsonTextBufferParse fnJsonTextBufferParse; dpiOciFnType__lobClose fnLobClose; dpiOciFnType__lobCreateTemporary fnLobCreateTemporary; dpiOciFnType__lobFileExists fnLobFileExists; dpiOciFnType__lobFileGetName fnLobFileGetName; dpiOciFnType__lobFileSetName fnLobFileSetName; dpiOciFnType__lobFreeTemporary fnLobFreeTemporary; dpiOciFnType__lobGetChunkSize fnLobGetChunkSize; dpiOciFnType__lobGetLength2 fnLobGetLength2; dpiOciFnType__lobIsOpen fnLobIsOpen; dpiOciFnType__lobIsTemporary fnLobIsTemporary; dpiOciFnType__lobLocatorAssign fnLobLocatorAssign; dpiOciFnType__lobOpen fnLobOpen; dpiOciFnType__lobRead2 fnLobRead2; dpiOciFnType__lobTrim2 fnLobTrim2; dpiOciFnType__lobWrite2 fnLobWrite2; dpiOciFnType__memoryAlloc fnMemoryAlloc; dpiOciFnType__memoryFree fnMemoryFree; dpiOciFnType__nlsCharSetConvert fnNlsCharSetConvert; dpiOciFnType__nlsCharSetIdToName fnNlsCharSetIdToName; dpiOciFnType__nlsCharSetNameToId fnNlsCharSetNameToId; dpiOciFnType__nlsEnvironmentVariableGet fnNlsEnvironmentVariableGet; dpiOciFnType__nlsNameMap fnNlsNameMap; dpiOciFnType__nlsNumericInfoGet fnNlsNumericInfoGet; dpiOciFnType__numberFromInt fnNumberFromInt; dpiOciFnType__numberFromReal fnNumberFromReal; dpiOciFnType__numberToInt fnNumberToInt; dpiOciFnType__numberToReal fnNumberToReal; dpiOciFnType__objectCopy fnObjectCopy; dpiOciFnType__objectFree fnObjectFree; dpiOciFnType__objectGetAttr fnObjectGetAttr; dpiOciFnType__objectGetInd fnObjectGetInd; dpiOciFnType__objectNew fnObjectNew; dpiOciFnType__objectPin fnObjectPin; dpiOciFnType__objectSetAttr fnObjectSetAttr; dpiOciFnType__paramGet fnParamGet; dpiOciFnType__passwordChange fnPasswordChange; dpiOciFnType__ping fnPing; dpiOciFnType__rawAssignBytes fnRawAssignBytes; dpiOciFnType__rawPtr fnRawPtr; dpiOciFnType__rawResize fnRawResize; dpiOciFnType__rawSize fnRawSize; dpiOciFnType__rowidToChar fnRowidToChar; dpiOciFnType__serverAttach fnServerAttach; dpiOciFnType__serverDetach fnServerDetach; dpiOciFnType__serverRelease fnServerRelease; dpiOciFnType__serverRelease2 fnServerRelease2; dpiOciFnType__sessionBegin fnSessionBegin; dpiOciFnType__sessionEnd fnSessionEnd; dpiOciFnType__sessionGet fnSessionGet; dpiOciFnType__sessionPoolCreate fnSessionPoolCreate; dpiOciFnType__sessionPoolDestroy fnSessionPoolDestroy; dpiOciFnType__sessionRelease fnSessionRelease; dpiOciFnType__shardingKeyColumnAdd fnShardingKeyColumnAdd; dpiOciFnType__stmtExecute fnStmtExecute; dpiOciFnType__sodaBulkInsert fnSodaBulkInsert; dpiOciFnType__sodaBulkInsertAndGet fnSodaBulkInsertAndGet; dpiOciFnType__sodaBulkInsertAndGetWithOpts fnSodaBulkInsertAndGetWithOpts; dpiOciFnType__sodaCollCreateWithMetadata fnSodaCollCreateWithMetadata; dpiOciFnType__sodaCollDrop fnSodaCollDrop; dpiOciFnType__sodaCollGetNext fnSodaCollGetNext; dpiOciFnType__sodaCollList fnSodaCollList; dpiOciFnType__sodaCollOpen fnSodaCollOpen; dpiOciFnType__sodaCollTruncate fnSodaCollTruncate; dpiOciFnType__sodaDataGuideGet fnSodaDataGuideGet; dpiOciFnType__sodaDocCount fnSodaDocCount; dpiOciFnType__sodaDocGetNext fnSodaDocGetNext; dpiOciFnType__sodaFind fnSodaFind; dpiOciFnType__sodaFindOne fnSodaFindOne; dpiOciFnType__sodaIndexCreate fnSodaIndexCreate; dpiOciFnType__sodaIndexDrop fnSodaIndexDrop; dpiOciFnType__sodaIndexList fnSodaIndexList; dpiOciFnType__sodaInsert fnSodaInsert; dpiOciFnType__sodaInsertAndGet fnSodaInsertAndGet; dpiOciFnType__sodaInsertAndGetWithOpts fnSodaInsertAndGetWithOpts; dpiOciFnType__sodaOperKeysSet fnSodaOperKeysSet; dpiOciFnType__sodaRemove fnSodaRemove; dpiOciFnType__sodaReplOne fnSodaReplOne; dpiOciFnType__sodaReplOneAndGet fnSodaReplOneAndGet; dpiOciFnType__sodaSave fnSodaSave; dpiOciFnType__sodaSaveAndGet fnSodaSaveAndGet; dpiOciFnType__sodaSaveAndGetWithOpts fnSodaSaveAndGetWithOpts; dpiOciFnType__stmtFetch2 fnStmtFetch2; dpiOciFnType__stmtGetBindInfo fnStmtGetBindInfo; dpiOciFnType__stmtGetNextResult fnStmtGetNextResult; dpiOciFnType__stmtPrepare2 fnStmtPrepare2; dpiOciFnType__stmtRelease fnStmtRelease; dpiOciFnType__stringAssignText fnStringAssignText; dpiOciFnType__stringPtr fnStringPtr; dpiOciFnType__stringResize fnStringResize; dpiOciFnType__stringSize fnStringSize; dpiOciFnType__subscriptionRegister fnSubscriptionRegister; dpiOciFnType__subscriptionUnRegister fnSubscriptionUnRegister; dpiOciFnType__tableDelete fnTableDelete; dpiOciFnType__tableExists fnTableExists; dpiOciFnType__tableFirst fnTableFirst; dpiOciFnType__tableLast fnTableLast; dpiOciFnType__tableNext fnTableNext; dpiOciFnType__tablePrev fnTablePrev; dpiOciFnType__tableSize fnTableSize; dpiOciFnType__threadKeyDestroy fnThreadKeyDestroy; dpiOciFnType__threadKeyGet fnThreadKeyGet; dpiOciFnType__threadKeyInit fnThreadKeyInit; dpiOciFnType__threadKeySet fnThreadKeySet; dpiOciFnType__threadProcessInit fnThreadProcessInit; dpiOciFnType__transCommit fnTransCommit; dpiOciFnType__transDetach fnTransDetach; dpiOciFnType__transForget fnTransForget; dpiOciFnType__transPrepare fnTransPrepare; dpiOciFnType__transRollback fnTransRollback; dpiOciFnType__transStart fnTransStart; dpiOciFnType__typeByFullName fnTypeByFullName; dpiOciFnType__typeByName fnTypeByName; dpiOciFnType__vectorFromArray fnVectorFromArray; dpiOciFnType__vectorFromSparseArray fnVectorFromSparseArray; dpiOciFnType__vectorToArray fnVectorToArray; dpiOciFnType__vectorToSparseArray fnVectorToSparseArray; } dpiOciSymbols; //----------------------------------------------------------------------------- // dpiOci__allocateMem() [INTERNAL] // Wrapper for OCI allocation of memory, only used when debugging memory // allocation. //----------------------------------------------------------------------------- static void *dpiOci__allocateMem(UNUSED void *unused, size_t size) { void *ptr; ptr = malloc(size); dpiDebug__print("OCI allocated %u bytes at %p\n", size, ptr); return ptr; } //----------------------------------------------------------------------------- // dpiOci__aqDeq() [INTERNAL] // Wrapper for OCIAQDeq(). //----------------------------------------------------------------------------- int dpiOci__aqDeq(dpiConn *conn, const char *queueName, void *options, void *msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIAQDeq", dpiOciSymbols.fnAqDeq) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnAqDeq)(conn->handle, error->handle, queueName, options, msgProps, payloadType, payload, payloadInd, msgId, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "dequeue message"); } //----------------------------------------------------------------------------- // dpiOci__aqDeqArray() [INTERNAL] // Wrapper for OCIAQDeqArray(). //----------------------------------------------------------------------------- int dpiOci__aqDeqArray(dpiConn *conn, const char *queueName, void *options, uint32_t *numIters, void **msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIAQDeqArray", dpiOciSymbols.fnAqDeqArray) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnAqDeqArray)(conn->handle, error->handle, queueName, options, numIters, msgProps, payloadType, payload, payloadInd, msgId, NULL, NULL, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "dequeue messages"); } //----------------------------------------------------------------------------- // dpiOci__aqEnq() [INTERNAL] // Wrapper for OCIAQEnq(). //----------------------------------------------------------------------------- int dpiOci__aqEnq(dpiConn *conn, const char *queueName, void *options, void *msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIAQEnq", dpiOciSymbols.fnAqEnq) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnAqEnq)(conn->handle, error->handle, queueName, options, msgProps, payloadType, payload, payloadInd, msgId, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "enqueue message"); } //----------------------------------------------------------------------------- // dpiOci__aqEnqArray() [INTERNAL] // Wrapper for OCIAQEnqArray(). //----------------------------------------------------------------------------- int dpiOci__aqEnqArray(dpiConn *conn, const char *queueName, void *options, uint32_t *numIters, void **msgProps, void *payloadType, void **payload, void **payloadInd, void **msgId, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIAQEnqArray", dpiOciSymbols.fnAqEnqArray) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnAqEnqArray)(conn->handle, error->handle, queueName, options, numIters, msgProps, payloadType, payload, payloadInd, msgId, NULL, NULL, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "enqueue messages"); } //----------------------------------------------------------------------------- // dpiOci__arrayDescriptorAlloc() [INTERNAL] // Wrapper for OCIArrayDescriptorAlloc(). //----------------------------------------------------------------------------- int dpiOci__arrayDescriptorAlloc(void *envHandle, void **handle, uint32_t handleType, uint32_t arraySize, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIArrayDescriptorAlloc", dpiOciSymbols.fnArrayDescriptorAlloc) status = (*dpiOciSymbols.fnArrayDescriptorAlloc)(envHandle, handle, handleType, arraySize, 0, NULL); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "allocate descriptors"); } //----------------------------------------------------------------------------- // dpiOci__arrayDescriptorFree() [INTERNAL] // Wrapper for OCIArrayDescriptorFree(). //----------------------------------------------------------------------------- int dpiOci__arrayDescriptorFree(void **handle, uint32_t handleType) { dpiError *error = NULL; int status; DPI_OCI_LOAD_SYMBOL("OCIArrayDescriptorFree", dpiOciSymbols.fnArrayDescriptorFree) status = (*dpiOciSymbols.fnArrayDescriptorFree)(handle, handleType); if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_UNREPORTED_ERRORS) dpiDebug__print("free array descriptors %p, handleType %d failed\n", handle, handleType); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__attrGet() [INTERNAL] // Wrapper for OCIAttrGet(). //----------------------------------------------------------------------------- int dpiOci__attrGet(const void *handle, uint32_t handleType, void *ptr, uint32_t *size, uint32_t attribute, const char *action, dpiError *error) { int status; DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnAttrGet)(handle, handleType, ptr, size, attribute, error->handle); if (status == DPI_OCI_NO_DATA && size) { *size = 0; return DPI_SUCCESS; } else if (!action) { return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); } //----------------------------------------------------------------------------- // dpiOci__attrSet() [INTERNAL] // Wrapper for OCIAttrSet(). //----------------------------------------------------------------------------- int dpiOci__attrSet(void *handle, uint32_t handleType, void *ptr, uint32_t size, uint32_t attribute, const char *action, dpiError *error) { int status; DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnAttrSet)(handle, handleType, ptr, size, attribute, error->handle); if (!action) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); } //----------------------------------------------------------------------------- // dpiOci__bindByName() [INTERNAL] // Wrapper for OCIBindByName(). //----------------------------------------------------------------------------- int dpiOci__bindByName(dpiStmt *stmt, void **bindHandle, const char *name, int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error) { uint32_t mode = DPI_OCI_DEFAULT; int status; if (dynamicBind) mode |= DPI_OCI_DATA_AT_EXEC; DPI_OCI_LOAD_SYMBOL("OCIBindByName", dpiOciSymbols.fnBindByName) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBindByName)(stmt->handle, bindHandle, error->handle, name, nameLength, (dynamicBind) ? NULL : var->buffer.data.asRaw, (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, var->type->oracleType, (dynamicBind) ? NULL : var->buffer.indicator, (dynamicBind || var->type->sizeInBytes) ? NULL : var->buffer.actualLength16, (dynamicBind) ? NULL : var->buffer.returnCode, (var->isArray) ? var->buffer.maxArraySize : 0, (var->isArray) ? &var->buffer.actualArraySize : NULL, mode); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by name"); } //----------------------------------------------------------------------------- // dpiOci__bindByName2() [INTERNAL] // Wrapper for OCIBindByName2(). //----------------------------------------------------------------------------- int dpiOci__bindByName2(dpiStmt *stmt, void **bindHandle, const char *name, int32_t nameLength, int dynamicBind, dpiVar *var, dpiError *error) { uint32_t mode = DPI_OCI_DEFAULT_BIND_MODE(stmt); int status; if (dynamicBind) mode |= DPI_OCI_DATA_AT_EXEC; DPI_OCI_LOAD_SYMBOL("OCIBindByName2", dpiOciSymbols.fnBindByName2) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBindByName2)(stmt->handle, bindHandle, error->handle, name, nameLength, (dynamicBind) ? NULL : var->buffer.data.asRaw, (var->isDynamic) ? INT_MAX : var->sizeInBytes, var->type->oracleType, (dynamicBind) ? NULL : var->buffer.indicator, (dynamicBind || var->type->sizeInBytes) ? NULL : var->buffer.actualLength32, (dynamicBind) ? NULL : var->buffer.returnCode, (var->isArray) ? var->buffer.maxArraySize : 0, (var->isArray) ? &var->buffer.actualArraySize : NULL, mode); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by name"); } //----------------------------------------------------------------------------- // dpiOci__bindByPos() [INTERNAL] // Wrapper for OCIBindByPos(). //----------------------------------------------------------------------------- int dpiOci__bindByPos(dpiStmt *stmt, void **bindHandle, uint32_t pos, int dynamicBind, dpiVar *var, dpiError *error) { uint32_t mode = DPI_OCI_DEFAULT; int status; if (dynamicBind) mode |= DPI_OCI_DATA_AT_EXEC; DPI_OCI_LOAD_SYMBOL("OCIBindByPos", dpiOciSymbols.fnBindByPos) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBindByPos)(stmt->handle, bindHandle, error->handle, pos, (dynamicBind) ? NULL : var->buffer.data.asRaw, (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, var->type->oracleType, (dynamicBind) ? NULL : var->buffer.indicator, (dynamicBind || var->type->sizeInBytes) ? NULL : var->buffer.actualLength16, (dynamicBind) ? NULL : var->buffer.returnCode, (var->isArray) ? var->buffer.maxArraySize : 0, (var->isArray) ? &var->buffer.actualArraySize : NULL, mode); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by position"); } //----------------------------------------------------------------------------- // dpiOci__bindByPos2() [INTERNAL] // Wrapper for OCIBindByPos2(). //----------------------------------------------------------------------------- int dpiOci__bindByPos2(dpiStmt *stmt, void **bindHandle, uint32_t pos, int dynamicBind, dpiVar *var, dpiError *error) { uint32_t mode = DPI_OCI_DEFAULT_BIND_MODE(stmt); int status; if (dynamicBind) mode |= DPI_OCI_DATA_AT_EXEC; DPI_OCI_LOAD_SYMBOL("OCIBindByPos2", dpiOciSymbols.fnBindByPos2) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBindByPos2)(stmt->handle, bindHandle, error->handle, pos, (dynamicBind) ? NULL : var->buffer.data.asRaw, (var->isDynamic) ? INT_MAX : var->sizeInBytes, var->type->oracleType, (dynamicBind) ? NULL : var->buffer.indicator, (dynamicBind || var->type->sizeInBytes) ? NULL : var->buffer.actualLength32, (dynamicBind) ? NULL : var->buffer.returnCode, (var->isArray) ? var->buffer.maxArraySize : 0, (var->isArray) ? &var->buffer.actualArraySize : NULL, mode); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "bind by position"); } //----------------------------------------------------------------------------- // dpiOci__bindDynamic() [INTERNAL] // Wrapper for OCIBindDynamic(). //----------------------------------------------------------------------------- int dpiOci__bindDynamic(dpiVar *var, void *bindHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIBindDynamic", dpiOciSymbols.fnBindDynamic) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBindDynamic)(bindHandle, error->handle, var, (void*) dpiVar__inBindCallback, var, (void*) dpiVar__outBindCallback); DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "bind dynamic"); } //----------------------------------------------------------------------------- // dpiOci__bindObject() [INTERNAL] // Wrapper for OCIBindObject(). //----------------------------------------------------------------------------- int dpiOci__bindObject(dpiVar *var, void *bindHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIBindObject", dpiOciSymbols.fnBindObject) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBindObject)(bindHandle, error->handle, var->objectType->tdo, (void**) var->buffer.data.asRaw, 0, var->buffer.objectIndicator, 0); DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "bind object"); } //----------------------------------------------------------------------------- // dpiOci__break() [INTERNAL] // Wrapper for OCIBreak(). //----------------------------------------------------------------------------- int dpiOci__break(dpiConn *conn, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIBreak", dpiOciSymbols.fnBreak) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnBreak)(conn->handle, error->handle); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "break execution"); } //----------------------------------------------------------------------------- // dpiOci__collAppend() [INTERNAL] // Wrapper for OCICollAppend(). //----------------------------------------------------------------------------- int dpiOci__collAppend(dpiConn *conn, const void *elem, const void *elemInd, void *coll, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCICollAppend", dpiOciSymbols.fnCollAppend) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnCollAppend)(conn->env->handle, error->handle, elem, elemInd, coll); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "append element"); } //----------------------------------------------------------------------------- // dpiOci__collAssignElem() [INTERNAL] // Wrapper for OCICollAssignElem(). //----------------------------------------------------------------------------- int dpiOci__collAssignElem(dpiConn *conn, int32_t index, const void *elem, const void *elemInd, void *coll, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCICollAssignElem", dpiOciSymbols.fnCollAssignElem) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnCollAssignElem)(conn->env->handle, error->handle, index, elem, elemInd, coll); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "assign element"); } //----------------------------------------------------------------------------- // dpiOci__collGetElem() [INTERNAL] // Wrapper for OCICollGetElem(). //----------------------------------------------------------------------------- int dpiOci__collGetElem(dpiConn *conn, void *coll, int32_t index, int *exists, void **elem, void **elemInd, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCICollGetElem", dpiOciSymbols.fnCollGetElem) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnCollGetElem)(conn->env->handle, error->handle, coll, index, exists, elem, elemInd); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get element"); } //----------------------------------------------------------------------------- // dpiOci__collSize() [INTERNAL] // Wrapper for OCICollSize(). //----------------------------------------------------------------------------- int dpiOci__collSize(dpiConn *conn, void *coll, int32_t *size, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCICollSize", dpiOciSymbols.fnCollSize) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnCollSize)(conn->env->handle, error->handle, coll, size); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get size"); } //----------------------------------------------------------------------------- // dpiOci__collTrim() [INTERNAL] // Wrapper for OCICollTrim(). //----------------------------------------------------------------------------- int dpiOci__collTrim(dpiConn *conn, uint32_t numToTrim, void *coll, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCICollTrim", dpiOciSymbols.fnCollTrim) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnCollTrim)(conn->env->handle, error->handle, (int32_t) numToTrim, coll); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "trim"); } //----------------------------------------------------------------------------- // dpiOci__contextGetValue() [INTERNAL] // Wrapper for OCIContextGetValue(). //----------------------------------------------------------------------------- int dpiOci__contextGetValue(dpiConn *conn, const char *key, uint32_t keyLength, void **value, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIContextGetValue", dpiOciSymbols.fnContextGetValue) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnContextGetValue)(conn->sessionHandle, error->handle, key, (uint8_t) keyLength, value); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get context value"); } //----------------------------------------------------------------------------- // dpiOci__contextSetValue() [INTERNAL] // Wrapper for OCIContextSetValue(). //----------------------------------------------------------------------------- int dpiOci__contextSetValue(dpiConn *conn, const char *key, uint32_t keyLength, void *value, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIContextSetValue", dpiOciSymbols.fnContextSetValue) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnContextSetValue)(conn->sessionHandle, error->handle, DPI_OCI_DURATION_SESSION, key, (uint8_t) keyLength, value); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "set context value"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeConstruct() [INTERNAL] // Wrapper for OCIDateTimeConstruct(). //----------------------------------------------------------------------------- int dpiOci__dateTimeConstruct(void *envHandle, void *handle, int16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second, uint32_t fsecond, const char *tz, size_t tzLength, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeConstruct", dpiOciSymbols.fnDateTimeConstruct) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeConstruct)(envHandle, error->handle, handle, year, month, day, hour, minute, second, fsecond, tz, tzLength); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "construct date"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeConvert() [INTERNAL] // Wrapper for OCIDateTimeConvert(). //----------------------------------------------------------------------------- int dpiOci__dateTimeConvert(void *envHandle, void *inDate, void *outDate, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeConvert", dpiOciSymbols.fnDateTimeConvert) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeConvert)(envHandle, error->handle, inDate, outDate); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "convert date"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeGetDate() [INTERNAL] // Wrapper for OCIDateTimeGetDate(). //----------------------------------------------------------------------------- int dpiOci__dateTimeGetDate(void *envHandle, void *handle, int16_t *year, uint8_t *month, uint8_t *day, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetDate", dpiOciSymbols.fnDateTimeGetDate) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeGetDate)(envHandle, error->handle, handle, year, month, day); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get date portion"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeGetTime() [INTERNAL] // Wrapper for OCIDateTimeGetTime(). //----------------------------------------------------------------------------- int dpiOci__dateTimeGetTime(void *envHandle, void *handle, uint8_t *hour, uint8_t *minute, uint8_t *second, uint32_t *fsecond, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetTime", dpiOciSymbols.fnDateTimeGetTime) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeGetTime)(envHandle, error->handle, handle, hour, minute, second, fsecond); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get time portion"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeGetTimeZoneOffset() [INTERNAL] // Wrapper for OCIDateTimeGetTimeZoneOffset(). //----------------------------------------------------------------------------- int dpiOci__dateTimeGetTimeZoneOffset(void *envHandle, void *handle, int8_t *tzHourOffset, int8_t *tzMinuteOffset, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeGetTimeZoneOffset", dpiOciSymbols.fnDateTimeGetTimeZoneOffset) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeGetTimeZoneOffset)(envHandle, error->handle, handle, tzHourOffset, tzMinuteOffset); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get time zone portion"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeIntervalAdd() [INTERNAL] // Wrapper for OCIDateTimeIntervalAdd(). //----------------------------------------------------------------------------- int dpiOci__dateTimeIntervalAdd(void *envHandle, void *handle, void *interval, void *outHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeIntervalAdd", dpiOciSymbols.fnDateTimeIntervalAdd) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeIntervalAdd)(envHandle, error->handle, handle, interval, outHandle); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "add interval to date"); } //----------------------------------------------------------------------------- // dpiOci__dateTimeSubtract() [INTERNAL] // Wrapper for OCIDateTimeSubtract(). //----------------------------------------------------------------------------- int dpiOci__dateTimeSubtract(void *envHandle, void *handle1, void *handle2, void *interval, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDateTimeSubtract", dpiOciSymbols.fnDateTimeSubtract) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDateTimeSubtract)(envHandle, error->handle, handle1, handle2, interval); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "subtract date"); } //----------------------------------------------------------------------------- // dpiOci__dbShutdown() [INTERNAL] // Wrapper for OCIDBShutdown(). //----------------------------------------------------------------------------- int dpiOci__dbShutdown(dpiConn *conn, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDBShutdown", dpiOciSymbols.fnDbShutdown) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDbShutdown)(conn->handle, error->handle, NULL, mode); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "shutdown database"); } //----------------------------------------------------------------------------- // dpiOci__dbStartup() [INTERNAL] // Wrapper for OCIDBStartup(). //----------------------------------------------------------------------------- int dpiOci__dbStartup(dpiConn *conn, void *adminHandle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDBStartup", dpiOciSymbols.fnDbStartup) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDbStartup)(conn->handle, error->handle, adminHandle, DPI_OCI_DEFAULT, mode); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "startup database"); } //----------------------------------------------------------------------------- // dpiOci__defineByPos() [INTERNAL] // Wrapper for OCIDefineByPos(). //----------------------------------------------------------------------------- int dpiOci__defineByPos(dpiStmt *stmt, void **defineHandle, uint32_t pos, dpiVar *var, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDefineByPos", dpiOciSymbols.fnDefineByPos) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDefineByPos)(stmt->handle, defineHandle, error->handle, pos, (var->isDynamic) ? NULL : var->buffer.data.asRaw, (var->isDynamic) ? INT_MAX : (int32_t) var->sizeInBytes, var->type->oracleType, (var->isDynamic) ? NULL : var->buffer.indicator, (var->isDynamic) ? NULL : var->buffer.actualLength16, (var->isDynamic) ? NULL : var->buffer.returnCode, (var->isDynamic) ? DPI_OCI_DYNAMIC_FETCH : DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "define"); } //----------------------------------------------------------------------------- // dpiOci__defineByPos2() [INTERNAL] // Wrapper for OCIDefineByPos2(). //----------------------------------------------------------------------------- int dpiOci__defineByPos2(dpiStmt *stmt, void **defineHandle, uint32_t pos, dpiVar *var, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDefineByPos2", dpiOciSymbols.fnDefineByPos2) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDefineByPos2)(stmt->handle, defineHandle, error->handle, pos, (var->isDynamic) ? NULL : var->buffer.data.asRaw, (var->isDynamic) ? INT_MAX : var->sizeInBytes, var->type->oracleType, (var->isDynamic) ? NULL : var->buffer.indicator, (var->isDynamic) ? NULL : var->buffer.actualLength32, (var->isDynamic) ? NULL : var->buffer.returnCode, (var->isDynamic) ? DPI_OCI_DYNAMIC_FETCH : DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "define"); } //----------------------------------------------------------------------------- // dpiOci__defineDynamic() [INTERNAL] // Wrapper for OCIDefineDynamic(). //----------------------------------------------------------------------------- int dpiOci__defineDynamic(dpiVar *var, void *defineHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDefineDynamic", dpiOciSymbols.fnDefineDynamic) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDefineDynamic)(defineHandle, error->handle, var, (void*) dpiVar__defineCallback); DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "define dynamic"); } //----------------------------------------------------------------------------- // dpiOci__defineObject() [INTERNAL] // Wrapper for OCIDefineObject(). //----------------------------------------------------------------------------- int dpiOci__defineObject(dpiVar *var, void *defineHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDefineObject", dpiOciSymbols.fnDefineObject) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDefineObject)(defineHandle, error->handle, var->objectType->tdo, (void**) var->buffer.data.asRaw, 0, var->buffer.objectIndicator, 0); DPI_OCI_CHECK_AND_RETURN(error, status, var->conn, "define object"); } //----------------------------------------------------------------------------- // dpiOci__describeAny() [INTERNAL] // Wrapper for OCIDescribeAny(). //----------------------------------------------------------------------------- int dpiOci__describeAny(dpiConn *conn, void *obj, uint32_t objLength, uint8_t objType, void *describeHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDescribeAny", dpiOciSymbols.fnDescribeAny) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnDescribeAny)(conn->handle, error->handle, obj, objLength, objType, 0, DPI_OCI_PTYPE_TYPE, describeHandle); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "describe type"); } //----------------------------------------------------------------------------- // dpiOci__descriptorAlloc() [INTERNAL] // Wrapper for OCIDescriptorAlloc(). //----------------------------------------------------------------------------- int dpiOci__descriptorAlloc(void *envHandle, void **handle, const uint32_t handleType, const char *action, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIDescriptorAlloc", dpiOciSymbols.fnDescriptorAlloc) status = (*dpiOciSymbols.fnDescriptorAlloc)(envHandle, handle, handleType, 0, NULL); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); } //----------------------------------------------------------------------------- // dpiOci__descriptorFree() [INTERNAL] // Wrapper for OCIDescriptorFree(). //----------------------------------------------------------------------------- int dpiOci__descriptorFree(void *handle, uint32_t handleType) { dpiError *error = NULL; int status; DPI_OCI_LOAD_SYMBOL("OCIDescriptorFree", dpiOciSymbols.fnDescriptorFree) status = (*dpiOciSymbols.fnDescriptorFree)(handle, handleType); if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_UNREPORTED_ERRORS) dpiDebug__print("free descriptor %p, type %d failed\n", handle, handleType); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__envNlsCreate() [INTERNAL] // Wrapper for OCIEnvNlsCreate(). //----------------------------------------------------------------------------- int dpiOci__envNlsCreate(void **envHandle, uint32_t mode, uint16_t charsetId, uint16_t ncharsetId, dpiError *error) { void *mallocFn = NULL, *reallocFn = NULL, *freeFn = NULL; int status; *envHandle = NULL; DPI_OCI_LOAD_SYMBOL("OCIEnvNlsCreate", dpiOciSymbols.fnEnvNlsCreate) if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) { mallocFn = (void*) dpiOci__allocateMem; reallocFn = (void*) dpiOci__reallocMem; freeFn = (void*) dpiOci__freeMem; } status = (*dpiOciSymbols.fnEnvNlsCreate)(envHandle, mode, NULL, mallocFn, reallocFn, freeFn, 0, NULL, charsetId, ncharsetId); if (*envHandle) { if (status == DPI_OCI_SUCCESS || status == DPI_OCI_SUCCESS_WITH_INFO) return DPI_SUCCESS; if (dpiOci__errorGet(*envHandle, DPI_OCI_HTYPE_ENV, charsetId, "create env", error) == 0) return DPI_FAILURE; } return dpiError__set(error, "create env", DPI_ERR_CREATE_ENV); } //----------------------------------------------------------------------------- // dpiOci__errorGet() [INTERNAL] // Wrapper for OCIErrorGet(). //----------------------------------------------------------------------------- int dpiOci__errorGet(void *handle, uint32_t handleType, uint16_t charsetId, const char *action, dpiError *error) { uint32_t i, numChars, bufferChars; uint16_t *utf16chars; int status; char *ptr; DPI_OCI_LOAD_SYMBOL("OCIErrorGet", dpiOciSymbols.fnErrorGet) status = (*dpiOciSymbols.fnErrorGet)(handle, 1, NULL, &error->buffer->code, error->buffer->message, sizeof(error->buffer->message), handleType); if (status != DPI_OCI_SUCCESS) return dpiError__set(error, action, DPI_ERR_GET_FAILED); error->buffer->action = action; // determine length of message since OCI does not provide this information; // all encodings except UTF-16 can use normal string processing; cannot use // type whar_t for processing UTF-16, though, as its size may be 4 on some // platforms, not 2; also strip trailing whitespace from error messages if (charsetId == DPI_CHARSET_ID_UTF16) { numChars = 0; utf16chars = (uint16_t*) error->buffer->message; bufferChars = sizeof(error->buffer->message) / 2; for (i = 0; i < bufferChars; i++) { if (utf16chars[i] == 0) break; if (utf16chars[i] > 127 || !isspace(utf16chars[i])) numChars = i + 1; } error->buffer->messageLength = numChars * 2; } else { error->buffer->messageLength = (uint32_t) strlen(error->buffer->message); ptr = error->buffer->message + error->buffer->messageLength - 1; while (ptr > error->buffer->message && isspace((uint8_t) *ptr--)) error->buffer->messageLength--; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__freeMem() [INTERNAL] // Wrapper for OCI allocation of memory, only used when debugging memory // allocation. //----------------------------------------------------------------------------- static void dpiOci__freeMem(UNUSED void *unused, void *ptr) { char message[40]; (void) sprintf(message, "OCI freed ptr at %p", ptr); free(ptr); dpiDebug__print("%s\n", message); } //----------------------------------------------------------------------------- // dpiOci__handleAlloc() [INTERNAL] // Wrapper for OCIHandleAlloc(). //----------------------------------------------------------------------------- int dpiOci__handleAlloc(void *envHandle, void **handle, uint32_t handleType, const char *action, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIHandleAlloc", dpiOciSymbols.fnHandleAlloc) status = (*dpiOciSymbols.fnHandleAlloc)(envHandle, handle, handleType, 0, NULL); if (handleType == DPI_OCI_HTYPE_ERROR && status != DPI_OCI_SUCCESS) return dpiError__set(error, action, DPI_ERR_NO_MEMORY); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); } //----------------------------------------------------------------------------- // dpiOci__handleFree() [INTERNAL] // Wrapper for OCIHandleFree(). //----------------------------------------------------------------------------- int dpiOci__handleFree(void *handle, uint32_t handleType) { dpiError *error = NULL; int status; DPI_OCI_LOAD_SYMBOL("OCIHandleFree", dpiOciSymbols.fnHandleFree) status = (*dpiOciSymbols.fnHandleFree)(handle, handleType); if (status != DPI_OCI_SUCCESS && dpiDebugLevel & DPI_DEBUG_LEVEL_UNREPORTED_ERRORS) dpiDebug__print("free handle %p, handleType %d failed\n", handle, handleType); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__intervalGetDaySecond() [INTERNAL] // Wrapper for OCIIntervalGetDaySecond(). //----------------------------------------------------------------------------- int dpiOci__intervalGetDaySecond(void *envHandle, int32_t *day, int32_t *hour, int32_t *minute, int32_t *second, int32_t *fsecond, const void *interval, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIIntervalGetDaySecond", dpiOciSymbols.fnIntervalGetDaySecond) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnIntervalGetDaySecond)(envHandle, error->handle, day, hour, minute, second, fsecond, interval); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get interval components"); } //----------------------------------------------------------------------------- // dpiOci__intervalGetYearMonth() [INTERNAL] // Wrapper for OCIIntervalGetYearMonth(). //----------------------------------------------------------------------------- int dpiOci__intervalGetYearMonth(void *envHandle, int32_t *year, int32_t *month, const void *interval, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIIntervalGetYearMonth", dpiOciSymbols.fnIntervalGetYearMonth) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnIntervalGetYearMonth)(envHandle, error->handle, year, month, interval); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get interval components"); } //----------------------------------------------------------------------------- // dpiOci__intervalSetDaySecond() [INTERNAL] // Wrapper for OCIIntervalSetDaySecond(). //----------------------------------------------------------------------------- int dpiOci__intervalSetDaySecond(void *envHandle, int32_t day, int32_t hour, int32_t minute, int32_t second, int32_t fsecond, void *interval, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIIntervalSetDaySecond", dpiOciSymbols.fnIntervalSetDaySecond) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnIntervalSetDaySecond)(envHandle, error->handle, day, hour, minute, second, fsecond, interval); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set interval components"); } //----------------------------------------------------------------------------- // dpiOci__intervalSetYearMonth() [INTERNAL] // Wrapper for OCIIntervalSetYearMonth(). //----------------------------------------------------------------------------- int dpiOci__intervalSetYearMonth(void *envHandle, int32_t year, int32_t month, void *interval, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIIntervalSetYearMonth", dpiOciSymbols.fnIntervalSetYearMonth) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnIntervalSetYearMonth)(envHandle, error->handle, year, month, interval); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set interval components"); } //----------------------------------------------------------------------------- // dpiOci__jsonDomDocGet() [INTERNAL] // Wrapper for OCIJsonDomDocGet(). //----------------------------------------------------------------------------- int dpiOci__jsonDomDocGet(dpiJson *json, dpiJznDomDoc **domDoc, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIJsonDomDocGet", dpiOciSymbols.fnJsonDomDocGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnJsonDomDocGet)(json->conn->handle, json->handle, domDoc, error->handle, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, json->conn, "get JSON DOM doc"); } //----------------------------------------------------------------------------- // dpiOci__jsonTextBufferParse() [INTERNAL] // Wrapper for OCIJsonTextBufferParse(). //----------------------------------------------------------------------------- int dpiOci__jsonTextBufferParse(dpiJson *json, const char *value, uint64_t valueLength, uint32_t flags, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIJsonTextBufferParse", dpiOciSymbols.fnJsonTextBufferParse) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnJsonTextBufferParse)(json->conn->handle, json->handle, (void*) value, valueLength, (DPI_JZN_ALLOW_SCALAR_DOCUMENTS | flags), DPI_JZN_INPUT_UTF8, error->handle, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, json->conn, "parse JSON text"); } #ifdef _WIN32 //----------------------------------------------------------------------------- // dpiOci__checkDllArchitecture() [INTERNAL] // Check the architecture of the specified DLL name and check if it // matches the expected architecture. If it does not, the load error is // modified and DPI_SUCCESS is returned; otherwise, DPI_FAILURE is returned. //----------------------------------------------------------------------------- static int dpiOci__checkDllArchitecture(dpiOciLoadLibParams *loadParams, const char *name, dpiError *error) { const char *errorFormat = "%s is not the correct architecture"; IMAGE_DOS_HEADER dosHeader; IMAGE_NT_HEADERS ntHeaders; FILE *fp; // check DLL architecture fp = fopen(name, "rb"); if (!fp) return DPI_FAILURE; fread(&dosHeader, sizeof(dosHeader), 1, fp); if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) { fclose(fp); return DPI_FAILURE; } fseek(fp, dosHeader.e_lfanew, SEEK_SET); fread(&ntHeaders, sizeof(ntHeaders), 1, fp); fclose(fp); if (ntHeaders.Signature != IMAGE_NT_SIGNATURE) return DPI_FAILURE; #if defined _M_AMD64 if (ntHeaders.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) return DPI_FAILURE; #elif defined _M_IX86 if (ntHeaders.FileHeader.Machine == IMAGE_FILE_MACHINE_I386) return DPI_FAILURE; #else return DPI_FAILURE; #endif // store a modified error in the error buffer if (dpiUtils__ensureBuffer(strlen(errorFormat) + strlen(name) + 1, "allocate wrong architecture load error buffer", (void**) &loadParams->errorBuffer, &loadParams->errorBufferLength, error) < 0) return DPI_FAILURE; sprintf(loadParams->errorBuffer, errorFormat, name); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__getEnv() [INTERNAL] // Gets the value of the environment variable with the given name. If the // environment variable is not found, NULL is returned. On Windows, a buffer is // required. //----------------------------------------------------------------------------- static char *dpiOci__getEnv(dpiOciLoadLibParams *loadParams, const char *name) { DWORD numBytes, actualNumBytes; // call the first time to get the length; if the environment variable is // not found, NULL is returned numBytes = GetEnvironmentVariable(name, NULL, 0); if (numBytes == 0) return NULL; // ensure the buffer is large enough to receive the contents if (dpiUtils__ensureBuffer(numBytes + 1, "allocate environment variable", (void**) &loadParams->envBuffer, &loadParams->envBufferLength, NULL) < 0) return NULL; // call a second time to get the value actualNumBytes = GetEnvironmentVariable(name, loadParams->envBuffer, (DWORD) loadParams->envBufferLength); if (actualNumBytes + 1 != numBytes) return NULL; return loadParams->envBuffer; } //----------------------------------------------------------------------------- // dpiOci__getModuleDir() [INTERNAL] // Attempts to get the directory of the module from the given function // pointer. This is platform specific. //----------------------------------------------------------------------------- static int dpiOci__getModuleDir(void *fn, const char *moduleType, char **nameBuffer, size_t *nameBufferLength, dpiError *error) { HMODULE module = NULL; DWORD result = 0; char *temp; // attempt to get the module handle from a known function pointer if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR) fn, &module) == 0) return DPI_FAILURE; // attempt to get the module name from the module; the size of the buffer // is increased as needed as there is no other known way to acquire the // full name (MAX_PATH is no longer the maximum path length) if (dpiUtils__ensureBuffer(MAX_PATH, "allocate module name", (void**) nameBuffer, nameBufferLength, error) < 0) { FreeLibrary(module); return DPI_FAILURE; } while (1) { result = GetModuleFileName(module, *nameBuffer, (DWORD) *nameBufferLength); if (result < (DWORD) *nameBufferLength) break; if (dpiUtils__ensureBuffer(*nameBufferLength * 2, "allocate module name", (void**) nameBuffer, nameBufferLength, error) < 0) { FreeLibrary(module); return DPI_FAILURE; } } FreeLibrary(module); if (result == 0) return DPI_FAILURE; if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("%s module name is %s\n", moduleType, *nameBuffer); // strip off the module name and only return the directory name temp = strrchr(*nameBuffer, '\\'); if (temp) { *temp = '\0'; return DPI_SUCCESS; } return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiOci__findAndCheckDllArchitecture() [INTERNAL] // Attempt to find the specified DLL name using the standard search path and // if the DLL can be found but is of the wrong architecture, include the full // name of the DLL in the load error. Return DPI_SUCCESS if such a DLL was // found and was of the wrong architecture (in which case the load error has // been set); otherwise, return DPI_FAILURE so that the normal load error can // be determined. //----------------------------------------------------------------------------- static int dpiOci__findAndCheckDllArchitecture(dpiOciLoadLibParams *loadParams, const char *name, dpiError *error) { DWORD bufferLength; char *temp, *path; size_t length; int status; // if the name of the DLL is an absolute path, check it directly temp = strchr(name, '\\'); if (temp) return dpiOci__checkDllArchitecture(loadParams, name, error); // check current directory bufferLength = GetCurrentDirectory(0, NULL); if (bufferLength == 0) return DPI_FAILURE; if (dpiUtils__ensureBuffer(strlen(name) + 1 + bufferLength, "allocate load params name buffer (current dir)", (void**) &loadParams->nameBuffer, &loadParams->nameBufferLength, error) < 0) return DPI_FAILURE; if (GetCurrentDirectory(bufferLength, loadParams->nameBuffer) == 0) return DPI_FAILURE; temp = loadParams->nameBuffer + strlen(loadParams->nameBuffer); *temp++ = '\\'; strcpy(temp, name); status = dpiOci__checkDllArchitecture(loadParams, loadParams->nameBuffer, error); // search PATH path = dpiOci__getEnv(loadParams, "PATH"); if (path) { while (status < 0) { temp = strchr(path, ';'); if (temp) { length = temp - path; } else { length = strlen(path); } if (dpiUtils__ensureBuffer(strlen(name) + length + 2, "allocate load params name buffer (PATH)", (void**) &loadParams->nameBuffer, &loadParams->nameBufferLength, error) < 0) return DPI_FAILURE; (void) sprintf(loadParams->nameBuffer, "%.*s\\%s", (int) length, path, name); status = dpiOci__checkDllArchitecture(loadParams, loadParams->nameBuffer, error); if (!temp) break; path = temp + 1; } } return status; } //----------------------------------------------------------------------------- // dpiOci__loadLibWithName() [INTERNAL] // Platform specific method of loading the library with a specific name. // Load errors are stored in the temporary load error buffer and do not cause // the function to fail; other errors (such as memory allocation errors) will // result in failure. //----------------------------------------------------------------------------- static int dpiOci__loadLibWithName(dpiOciLoadLibParams *loadParams, const char *name, dpiError *error) { DWORD errorNum; // attempt to load the library loadParams->handle = LoadLibrary(name); if (loadParams->handle) return DPI_SUCCESS; // if DLL is of the wrong architecture, attempt to locate the DLL that was // loaded and use that information if it can be found errorNum = GetLastError(); if (errorNum == ERROR_BAD_EXE_FORMAT && dpiOci__findAndCheckDllArchitecture(loadParams, name, error) == 0) return DPI_SUCCESS; // otherwise, attempt to get the error message return dpiUtils__getWindowsError(errorNum, &loadParams->errorBuffer, &loadParams->errorBufferLength, error); } // for platforms other than Windows #else //----------------------------------------------------------------------------- // dpiOci__getEnv() [INTERNAL] // Gets the value of the environment variable with the given name. If the // environment variable is not found, NULL is returned. //----------------------------------------------------------------------------- static char *dpiOci__getEnv(UNUSED dpiOciLoadLibParams *loadParams, const char *name) { return getenv(name); } //----------------------------------------------------------------------------- // dpiOci__getModuleDir() [INTERNAL] // Attempts to get the directory of the module from the given function // pointer. This is platform specific. //----------------------------------------------------------------------------- static int dpiOci__getModuleDir(void *fn, const char *moduleType, char **nameBuffer, size_t *nameBufferLength, dpiError *error) { #ifndef _AIX Dl_info info; char *temp; if (dladdr(fn, &info) != 0) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("%s module name is %s\n", moduleType, info.dli_fname); if (dpiUtils__ensureBuffer(strlen(info.dli_fname) + 1, "allocate module name", (void**) nameBuffer, nameBufferLength, error) < 0) return DPI_FAILURE; strcpy(*nameBuffer, info.dli_fname); temp = strrchr(*nameBuffer, '/'); if (temp) { *temp = '\0'; return DPI_SUCCESS; } } #endif return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiOci__loadLibWithName() [INTERNAL] // Platform specific method of loading the library with a specific name. // Load errors are stored in the temporary load error buffer and do not cause // the function to fail; other errors (such as memory allocation errors) will // result in failure. //----------------------------------------------------------------------------- static int dpiOci__loadLibWithName(dpiOciLoadLibParams *loadParams, const char *libName, dpiError *error) { char *osError; loadParams->handle = dlopen(libName, RTLD_LAZY); if (!loadParams->handle) { osError = dlerror(); if (dpiUtils__ensureBuffer(strlen(osError) + 1, "allocate load error buffer", (void**) &loadParams->errorBuffer, &loadParams->errorBufferLength, error) < 0) return DPI_FAILURE; strcpy(loadParams->errorBuffer, osError); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__loadLibWithOracleHome() [INTERNAL] // Attempts to load the library from the lib subdirectory of an Oracle home // pointed to by the environemnt variable ORACLE_HOME. //----------------------------------------------------------------------------- static int dpiOci__loadLibWithOracleHome(dpiOciLoadLibParams *loadParams, dpiError *error) { char *oracleHome, *oracleHomeLibDir; size_t oracleHomeLength; int status; // check environment variable; if not set, attempt cannot proceed oracleHome = dpiOci__getEnv(loadParams, "ORACLE_HOME"); if (!oracleHome) return DPI_FAILURE; // a zero-length directory is ignored oracleHomeLength = strlen(oracleHome); if (oracleHomeLength == 0) return DPI_FAILURE; // craft directory to search if (dpiUtils__allocateMemory(1, oracleHomeLength + 5, 0, "allocate ORACLE_HOME dir name", (void**) &oracleHomeLibDir, error) < 0) return DPI_FAILURE; (void) sprintf(oracleHomeLibDir, "%s/lib", oracleHome); // perform search status = dpiOci__loadLibWithDir(loadParams, oracleHomeLibDir, strlen(oracleHomeLibDir), 0, error); dpiUtils__freeMemory(oracleHomeLibDir); return status; } #endif //----------------------------------------------------------------------------- // dpiOci__calculateConfigDir() [INTERNAL] // Attempt to calculate the default configuration directory to use when // locating configuration files. If the value cannot be calculated, no errors // are raised. //----------------------------------------------------------------------------- static void dpiOci__calculateConfigDir(dpiOciLoadLibParams *loadParams) { size_t nameBufferLength = 0; char *nameBuffer = NULL; char *baseDir; int status; // first check to see if the environment variable TNS_ADMIN is set baseDir = dpiOci__getEnv(loadParams, "TNS_ADMIN"); if (baseDir) { status = dpiUtils__allocateMemory(1, strlen(baseDir) + 1, 0, "allocate config dir", (void**) loadParams->configDir, NULL); if (status == DPI_SUCCESS) strcpy(*loadParams->configDir, baseDir); return; } // otherwise, check the environment variable ORACLE_HOME is set and if not, // look for the directory in which the Oracle Client library which has been // loaded baseDir = dpiOci__getEnv(loadParams, "ORACLE_HOME"); if (!baseDir) { status = dpiOci__getModuleDir(dpiOciSymbols.fnThreadProcessInit, "OCI", &nameBuffer, &nameBufferLength, NULL); if (status == DPI_SUCCESS) baseDir = nameBuffer; } if (baseDir) { status = dpiUtils__allocateMemory(1, strlen(baseDir) + strlen(dpiOciConfigSubDir) + 2, 0, "allocate config dir", (void**) loadParams->configDir, NULL); if (status == DPI_SUCCESS) sprintf(*loadParams->configDir, "%s/%s", baseDir, dpiOciConfigSubDir); } if (nameBuffer) dpiUtils__freeMemory(nameBuffer); } //----------------------------------------------------------------------------- // dpiOci__loadLibWithDir() [INTERNAL] // Helper function for loading the OCI library. If a directory is specified, // that directory is searched; otherwise, an unqualfied search is performed // using the normal OS library loading rules. //----------------------------------------------------------------------------- static int dpiOci__loadLibWithDir(dpiOciLoadLibParams *loadParams, const char *dirName, size_t dirNameLength, int scanAllNames, dpiError *error) { const char *searchName; size_t nameLength; int i; // report attempt with directory, if applicable if (dirName && dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("load in dir %.*s\n", (int) dirNameLength, dirName); // iterate over all possible options for (i = 0; dpiOciLibNames[i]; i++) { // determine name to search if (!dirName) { searchName = dpiOciLibNames[i]; } else { nameLength = strlen(dpiOciLibNames[i]) + dirNameLength + 2; if (dpiUtils__ensureBuffer(nameLength, "allocate name buffer", (void**) &loadParams->nameBuffer, &loadParams->nameBufferLength, error) < 0) return DPI_FAILURE; (void) sprintf(loadParams->nameBuffer, "%.*s/%s", (int) dirNameLength, dirName, dpiOciLibNames[i]); searchName = loadParams->nameBuffer; } // attempt to load the library using the calculated name; failure here // implies something other than a load failure and this error is // reported immediately if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("load with name %s\n", searchName); if (dpiOci__loadLibWithName(loadParams, searchName, error) < 0) return DPI_FAILURE; // success is also reported immediately if (loadParams->handle) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("load by OS successful\n"); return DPI_SUCCESS; } // load failed; store the first failure that occurs which will be // reported if no successful loads were made and no other errors took // place if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("load by OS failure: %s\n", loadParams->errorBuffer); if (i == 0) { if (dpiUtils__ensureBuffer(loadParams->errorBufferLength, "allocate load error buffer", (void**) &loadParams->loadError, &loadParams->loadErrorLength, error) < 0) return DPI_FAILURE; strcpy(loadParams->loadError, loadParams->errorBuffer); if (!scanAllNames) break; } } // no attempts were successful return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiOci__loadLib() [INTERNAL] // Load the OCI library. //----------------------------------------------------------------------------- int dpiOci__loadLib(dpiContextCreateParams *params, dpiVersionInfo *clientVersionInfo, char **configDir, dpiError *error) { static const char *envNamesToCheck[] = { "ORACLE_HOME", "ORA_TZFILE", "TNS_ADMIN", #ifdef _WIN32 "PATH", #else "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "LIBPATH", "SHLIB_PATH", #endif NULL }; dpiOciLoadLibParams loadLibParams; const char *temp; int status, i; // initialize loading parameters; these are used to provide space for // loading errors and the names that are being searched; memory is // allocated dynamically in order to avoid potential issues with long paths // on some platforms memset(&loadLibParams, 0, sizeof(loadLibParams)); loadLibParams.configDir = configDir; // log the directory parameter values and any environment variables that // have an impact on loading the library if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) { // first log directory parameter values dpiDebug__print("Context Parameters:\n"); if (params->oracleClientLibDir) dpiDebug__print(" Oracle Client Lib Dir: %s\n", params->oracleClientLibDir); if (params->oracleClientConfigDir) dpiDebug__print(" Oracle Client Config Dir: %s\n", params->oracleClientConfigDir); // now log environment variable values dpiDebug__print("Environment Variables:\n"); for (i = 0; envNamesToCheck[i]; i++) { temp = dpiOci__getEnv(&loadLibParams, envNamesToCheck[i]); if (temp) dpiDebug__print(" %s => \"%s\"\n", envNamesToCheck[i], temp); } } // if a config directory was specified in the create params, set the // TNS_ADMIN environment variable if (params->oracleClientConfigDir) { #ifdef _WIN32 if (!SetEnvironmentVariable("TNS_ADMIN", params->oracleClientConfigDir)) { #else if (setenv("TNS_ADMIN", params->oracleClientConfigDir, 1) != 0) { #endif return dpiError__setFromOS(error, "set TNS_ADMIN environment variable"); } } // if a lib directory was specified in the create params, look for the OCI // library in that location only if (params->oracleClientLibDir) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("load in parameter directory\n"); status = dpiOci__loadLibWithDir(&loadLibParams, params->oracleClientLibDir, strlen(params->oracleClientLibDir), 1, error); // otherwise, use the normal loading mechanism } else { // first try the directory in which the ODPI-C library itself is found if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("check ODPI-C module directory\n"); status = dpiOci__getModuleDir(dpiContext_createWithParams, "ODPI-C", &loadLibParams.moduleNameBuffer, &loadLibParams.moduleNameBufferLength, error); if (status == DPI_SUCCESS) status = dpiOci__loadLibWithDir(&loadLibParams, loadLibParams.moduleNameBuffer, strlen(loadLibParams.moduleNameBuffer), 0, error); // if that fails, try the default OS library loading mechanism if (status < 0) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("load with OS search heuristics\n"); status = dpiOci__loadLibWithDir(&loadLibParams, NULL, 0, 1, error); } #ifndef _WIN32 // if that fails, on platforms other than Windows, attempt to load // from $ORACLE_HOME/lib if (status < 0) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("check ORACLE_HOME\n"); status = dpiOci__loadLibWithOracleHome(&loadLibParams, error); } #endif } // if no attempts succeeded and no other error was reported, craft the // error message that will be returned if (status < 0 && (int) error->buffer->errorNum == 0) { const char *bits = (sizeof(void*) == 8) ? "64" : "32"; dpiError__set(error, "load library", DPI_ERR_LOAD_LIBRARY, bits, loadLibParams.loadError, params->loadErrorUrl); } // validate library, if a library was loaded if (status == DPI_SUCCESS) { dpiOciLibHandle = loadLibParams.handle; status = dpiOci__loadLibValidate(params, &loadLibParams, clientVersionInfo, error); } // free any memory that was allocated if (loadLibParams.nameBuffer) dpiUtils__freeMemory(loadLibParams.nameBuffer); if (loadLibParams.moduleNameBuffer) dpiUtils__freeMemory(loadLibParams.moduleNameBuffer); if (loadLibParams.loadError) dpiUtils__freeMemory(loadLibParams.loadError); if (loadLibParams.errorBuffer) dpiUtils__freeMemory(loadLibParams.errorBuffer); if (loadLibParams.envBuffer) dpiUtils__freeMemory(loadLibParams.envBuffer); // free the library, if a library was loaded and any error occurred if (status < 0) { if (dpiOciLibHandle != NULL) { #ifdef _WIN32 FreeLibrary(dpiOciLibHandle); #else dlclose(dpiOciLibHandle); #endif dpiOciLibHandle = NULL; } memset(&dpiOciSymbols, 0, sizeof(dpiOciSymbols)); return DPI_FAILURE; } // if no Oracle Client configuration directory was specified, set the // value to contain the calculated value instead if (!params->oracleClientConfigDir) params->oracleClientConfigDir = *configDir; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__loadLibValidate() [INTERNAL] // Validate the OCI library after loading. //----------------------------------------------------------------------------- static int dpiOci__loadLibValidate(dpiContextCreateParams *params, dpiOciLoadLibParams *loadParams, dpiVersionInfo *clientVersionInfo, dpiError *error) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_LOAD_LIB) dpiDebug__print("validating loaded library\n"); // determine the OCI client version information if (dpiOci__loadSymbol("OCIClientVersion", (void**) &dpiOciSymbols.fnClientVersion, NULL) < 0) return dpiError__set(error, "load symbol OCIClientVersion", DPI_ERR_ORACLE_CLIENT_UNSUPPORTED); memset(clientVersionInfo, 0, sizeof(*clientVersionInfo)); (*dpiOciSymbols.fnClientVersion)(&clientVersionInfo->versionNum, &clientVersionInfo->releaseNum, &clientVersionInfo->updateNum, &clientVersionInfo->portReleaseNum, &clientVersionInfo->portUpdateNum); if (clientVersionInfo->versionNum == 0) return dpiError__set(error, "get OCI client version", DPI_ERR_ORACLE_CLIENT_UNSUPPORTED); clientVersionInfo->fullVersionNum = (uint32_t) DPI_ORACLE_VERSION_TO_NUMBER(clientVersionInfo->versionNum, clientVersionInfo->releaseNum, clientVersionInfo->updateNum, clientVersionInfo->portReleaseNum, clientVersionInfo->portUpdateNum); // OCI version must be a minimum of 11.2 if (dpiUtils__checkClientVersion(clientVersionInfo, 11, 2, error) < 0) return DPI_FAILURE; // initialize threading capability in the OCI library // this must be run prior to any other OCI threading calls DPI_OCI_LOAD_SYMBOL("OCIThreadProcessInit", dpiOciSymbols.fnThreadProcessInit) (*dpiOciSymbols.fnThreadProcessInit)(); // load symbols for key functions which are called many times // this list should be kept as small as possible in order to avoid // overhead in looking up symbols at startup DPI_OCI_LOAD_SYMBOL("OCIAttrGet", dpiOciSymbols.fnAttrGet) DPI_OCI_LOAD_SYMBOL("OCIAttrSet", dpiOciSymbols.fnAttrSet) DPI_OCI_LOAD_SYMBOL("OCIThreadKeyGet", dpiOciSymbols.fnThreadKeyGet) // if a configuration directory is not supplied, calculate one, if possible if (!params->oracleClientConfigDir) dpiOci__calculateConfigDir(loadParams); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__loadSymbol() [INTERNAL] // Return the symbol for the function that is to be called. The symbol table // is first consulted. If the symbol is not found there, it is looked up and // then stored there so the next invocation does not have to perform the // lookup. //----------------------------------------------------------------------------- static int dpiOci__loadSymbol(const char *symbolName, void **symbol, dpiError *error) { #ifdef _WIN32 *symbol = GetProcAddress(dpiOciLibHandle, symbolName); #else *symbol = dlsym(dpiOciLibHandle, symbolName); #endif if (!*symbol) return dpiError__set(error, "get symbol", DPI_ERR_LOAD_SYMBOL, symbolName); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__lobClose() [INTERNAL] // Wrapper for OCILobClose(). //----------------------------------------------------------------------------- int dpiOci__lobClose(dpiLob *lob, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobClose", dpiOciSymbols.fnLobClose) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobClose)(lob->conn->handle, error->handle, lob->locator); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "close LOB"); } //----------------------------------------------------------------------------- // dpiOci__lobCreateTemporary() [INTERNAL] // Wrapper for OCILobCreateTemporary(). //----------------------------------------------------------------------------- int dpiOci__lobCreateTemporary(dpiLob *lob, dpiError *error) { uint8_t lobType; int status; DPI_OCI_LOAD_SYMBOL("OCILobCreateTemporary", dpiOciSymbols.fnLobCreateTemporary) DPI_OCI_ENSURE_ERROR_HANDLE(error) if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BLOB) lobType = DPI_OCI_TEMP_BLOB; else lobType = DPI_OCI_TEMP_CLOB; status = (*dpiOciSymbols.fnLobCreateTemporary)(lob->conn->handle, error->handle, lob->locator, DPI_OCI_DEFAULT, lob->type->charsetForm, lobType, 1, DPI_OCI_DURATION_SESSION); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "create temporary LOB"); } //----------------------------------------------------------------------------- // dpiOci__lobFileExists() [INTERNAL] // Wrapper for OCILobFileExists(). //----------------------------------------------------------------------------- int dpiOci__lobFileExists(dpiLob *lob, int *exists, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobFileExists", dpiOciSymbols.fnLobFileExists) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobFileExists)(lob->conn->handle, error->handle, lob->locator, exists); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get file exists"); } //----------------------------------------------------------------------------- // dpiOci__lobFileGetName() [INTERNAL] // Wrapper for OCILobFileGetName(). //----------------------------------------------------------------------------- int dpiOci__lobFileGetName(dpiLob *lob, char *dirAlias, uint16_t *dirAliasLength, char *name, uint16_t *nameLength, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobFileGetName", dpiOciSymbols.fnLobFileGetName) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobFileGetName)(lob->env->handle, error->handle, lob->locator, dirAlias, dirAliasLength, name, nameLength); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get LOB file name"); } //----------------------------------------------------------------------------- // dpiOci__lobFileSetName() [INTERNAL] // Wrapper for OCILobFileSetName(). //----------------------------------------------------------------------------- int dpiOci__lobFileSetName(dpiLob *lob, const char *dirAlias, uint16_t dirAliasLength, const char *name, uint16_t nameLength, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobFileSetName", dpiOciSymbols.fnLobFileSetName) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobFileSetName)(lob->env->handle, error->handle, &lob->locator, dirAlias, dirAliasLength, name, nameLength); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "set LOB file name"); } //----------------------------------------------------------------------------- // dpiOci__lobFreeTemporary() [INTERNAL] // Wrapper for OCILobFreeTemporary(). //----------------------------------------------------------------------------- int dpiOci__lobFreeTemporary(dpiConn *conn, void *lobLocator, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobFreeTemporary", dpiOciSymbols.fnLobFreeTemporary) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobFreeTemporary)(conn->handle, error->handle, lobLocator); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "free temporary LOB"); } //----------------------------------------------------------------------------- // dpiOci__lobGetChunkSize() [INTERNAL] // Wrapper for OCILobGetChunkSize(). //----------------------------------------------------------------------------- int dpiOci__lobGetChunkSize(dpiLob *lob, uint32_t *size, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobGetChunkSize", dpiOciSymbols.fnLobGetChunkSize) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobGetChunkSize)(lob->conn->handle, error->handle, lob->locator, size); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get chunk size"); } //----------------------------------------------------------------------------- // dpiOci__lobGetLength2() [INTERNAL] // Wrapper for OCILobGetLength2(). //----------------------------------------------------------------------------- int dpiOci__lobGetLength2(dpiLob *lob, uint64_t *size, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobGetLength2", dpiOciSymbols.fnLobGetLength2) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobGetLength2)(lob->conn->handle, error->handle, lob->locator, size); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "get length"); } //----------------------------------------------------------------------------- // dpiOci__lobIsOpen() [INTERNAL] // Wrapper for OCILobIsOpen(). //----------------------------------------------------------------------------- int dpiOci__lobIsOpen(dpiLob *lob, int *isOpen, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobIsOpen", dpiOciSymbols.fnLobIsOpen) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobIsOpen)(lob->conn->handle, error->handle, lob->locator, isOpen); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "check is open"); } //----------------------------------------------------------------------------- // dpiOci__lobIsTemporary() [INTERNAL] // Wrapper for OCILobIsTemporary(). //----------------------------------------------------------------------------- int dpiOci__lobIsTemporary(dpiLob *lob, int *isTemporary, int checkError, dpiError *error) { int status; *isTemporary = 0; DPI_OCI_LOAD_SYMBOL("OCILobIsTemporary", dpiOciSymbols.fnLobIsTemporary) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobIsTemporary)(lob->env->handle, error->handle, lob->locator, isTemporary); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "check is temporary"); } //----------------------------------------------------------------------------- // dpiOci__lobLocatorAssign() [INTERNAL] // Wrapper for OCILobLocatorAssign(). //----------------------------------------------------------------------------- int dpiOci__lobLocatorAssign(dpiLob *lob, void **copiedHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobLocatorAssign", dpiOciSymbols.fnLobLocatorAssign) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobLocatorAssign)(lob->conn->handle, error->handle, lob->locator, copiedHandle); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "assign locator"); } //----------------------------------------------------------------------------- // dpiOci__lobOpen() [INTERNAL] // Wrapper for OCILobOpen(). //----------------------------------------------------------------------------- int dpiOci__lobOpen(dpiLob *lob, dpiError *error) { uint8_t mode; int status; DPI_OCI_LOAD_SYMBOL("OCILobOpen", dpiOciSymbols.fnLobOpen) DPI_OCI_ENSURE_ERROR_HANDLE(error) mode = (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_BFILE) ? DPI_OCI_LOB_READONLY : DPI_OCI_LOB_READWRITE; status = (*dpiOciSymbols.fnLobOpen)(lob->conn->handle, error->handle, lob->locator, mode); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "close LOB"); } //----------------------------------------------------------------------------- // dpiOci__lobRead2() [INTERNAL] // Wrapper for OCILobRead2(). //----------------------------------------------------------------------------- int dpiOci__lobRead2(dpiLob *lob, uint64_t offset, uint64_t *amountInBytes, uint64_t *amountInChars, char *buffer, uint64_t bufferLength, dpiError *error) { uint16_t charsetId; int status; DPI_OCI_LOAD_SYMBOL("OCILobRead2", dpiOciSymbols.fnLobRead2) DPI_OCI_ENSURE_ERROR_HANDLE(error) charsetId = (lob->type->charsetForm == DPI_SQLCS_NCHAR) ? lob->env->ncharsetId : lob->env->charsetId; status = (*dpiOciSymbols.fnLobRead2)(lob->conn->handle, error->handle, lob->locator, amountInBytes, amountInChars, offset, buffer, bufferLength, DPI_OCI_ONE_PIECE, NULL, NULL, charsetId, lob->type->charsetForm); if (status == DPI_OCI_NEED_DATA) { *amountInChars = 0; *amountInBytes = 0; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "read from LOB"); } //----------------------------------------------------------------------------- // dpiOci__lobTrim2() [INTERNAL] // Wrapper for OCILobTrim2(). //----------------------------------------------------------------------------- int dpiOci__lobTrim2(dpiLob *lob, uint64_t newLength, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCILobTrim2", dpiOciSymbols.fnLobTrim2) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnLobTrim2)(lob->conn->handle, error->handle, lob->locator, newLength); if (status == DPI_OCI_INVALID_HANDLE) return dpiOci__lobCreateTemporary(lob, error); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "trim LOB"); } //----------------------------------------------------------------------------- // dpiOci__lobWrite2() [INTERNAL] // Wrapper for OCILobWrite2(). //----------------------------------------------------------------------------- int dpiOci__lobWrite2(dpiLob *lob, uint64_t offset, const char *value, uint64_t valueLength, dpiError *error) { uint64_t lengthInBytes = valueLength, lengthInChars = 0; uint16_t charsetId; int status; DPI_OCI_LOAD_SYMBOL("OCILobWrite2", dpiOciSymbols.fnLobWrite2) DPI_OCI_ENSURE_ERROR_HANDLE(error) charsetId = (lob->type->charsetForm == DPI_SQLCS_NCHAR) ? lob->env->ncharsetId : lob->env->charsetId; status = (*dpiOciSymbols.fnLobWrite2)(lob->conn->handle, error->handle, lob->locator, &lengthInBytes, &lengthInChars, offset, (void*) value, valueLength, DPI_OCI_ONE_PIECE, NULL, NULL, charsetId, lob->type->charsetForm); DPI_OCI_CHECK_AND_RETURN(error, status, lob->conn, "write to LOB"); } //----------------------------------------------------------------------------- // dpiOci__memoryAlloc() [INTERNAL] // Wrapper for OCIMemoryAlloc(). //----------------------------------------------------------------------------- int dpiOci__memoryAlloc(dpiConn *conn, void **ptr, uint32_t size, int checkError, dpiError *error) { int status; *ptr = NULL; DPI_OCI_LOAD_SYMBOL("OCIMemoryAlloc", dpiOciSymbols.fnMemoryAlloc) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnMemoryAlloc)(conn->sessionHandle, error->handle, ptr, DPI_OCI_DURATION_SESSION, size, DPI_OCI_MEMORY_CLEARED); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "allocate memory"); } //----------------------------------------------------------------------------- // dpiOci__memoryFree() [INTERNAL] // Wrapper for OCIMemoryFree(). //----------------------------------------------------------------------------- int dpiOci__memoryFree(dpiConn *conn, void *ptr, dpiError *error) { DPI_OCI_LOAD_SYMBOL("OCIMemoryFree", dpiOciSymbols.fnMemoryFree) DPI_OCI_ENSURE_ERROR_HANDLE(error) (*dpiOciSymbols.fnMemoryFree)(conn->sessionHandle, error->handle, ptr); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__nlsCharSetConvert() [INTERNAL] // Wrapper for OCINlsCharSetConvert(). //----------------------------------------------------------------------------- int dpiOci__nlsCharSetConvert(void *envHandle, uint16_t destCharsetId, char *dest, size_t destLength, uint16_t sourceCharsetId, const char *source, size_t sourceLength, size_t *resultSize, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINlsCharSetConvert", dpiOciSymbols.fnNlsCharSetConvert) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnNlsCharSetConvert)(envHandle, error->handle, destCharsetId, dest, destLength, sourceCharsetId, source, sourceLength, resultSize); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "convert text"); } //----------------------------------------------------------------------------- // dpiOci__nlsCharSetIdToName() [INTERNAL] // Wrapper for OCINlsCharSetIdToName(). //----------------------------------------------------------------------------- int dpiOci__nlsCharSetIdToName(void *envHandle, char *buf, size_t bufLength, uint16_t charsetId, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINlsCharSetIdToName", dpiOciSymbols.fnNlsCharSetIdToName) status = (*dpiOciSymbols.fnNlsCharSetIdToName)(envHandle, buf, bufLength, charsetId); return (status == DPI_OCI_SUCCESS) ? DPI_SUCCESS : DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiOci__nlsCharSetNameToId() [INTERNAL] // Wrapper for OCINlsCharSetNameToId(). //----------------------------------------------------------------------------- int dpiOci__nlsCharSetNameToId(void *envHandle, const char *name, uint16_t *charsetId, dpiError *error) { DPI_OCI_LOAD_SYMBOL("OCINlsCharSetNameToId", dpiOciSymbols.fnNlsCharSetNameToId) *charsetId = (*dpiOciSymbols.fnNlsCharSetNameToId)(envHandle, name); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__nlsEnvironmentVariableGet() [INTERNAL] // Wrapper for OCIEnvironmentVariableGet(). //----------------------------------------------------------------------------- int dpiOci__nlsEnvironmentVariableGet(uint16_t item, void *value, dpiError *error) { size_t ignored; int status; DPI_OCI_LOAD_SYMBOL("OCINlsEnvironmentVariableGet", dpiOciSymbols.fnNlsEnvironmentVariableGet) status = (*dpiOciSymbols.fnNlsEnvironmentVariableGet)(value, 0, item, 0, &ignored); if (status != DPI_OCI_SUCCESS) return dpiError__set(error, "get NLS environment variable", DPI_ERR_NLS_ENV_VAR_GET); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__nlsNameMap() [INTERNAL] // Wrapper for OCINlsNameMap(). //----------------------------------------------------------------------------- int dpiOci__nlsNameMap(void *envHandle, char *buf, size_t bufLength, const char *source, uint32_t flag, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINlsNameMap", dpiOciSymbols.fnNlsNameMap) status = (*dpiOciSymbols.fnNlsNameMap)(envHandle, buf, bufLength, source, flag); return (status == DPI_OCI_SUCCESS) ? DPI_SUCCESS : DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiOci__nlsNumericInfoGet() [INTERNAL] // Wrapper for OCINlsNumericInfoGet(). //----------------------------------------------------------------------------- int dpiOci__nlsNumericInfoGet(void *envHandle, int32_t *value, uint16_t item, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINlsNumericInfoGet", dpiOciSymbols.fnNlsNumericInfoGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnNlsNumericInfoGet)(envHandle, error->handle, value, item); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get NLS info"); } //----------------------------------------------------------------------------- // dpiOci__numberFromInt() [INTERNAL] // Wrapper for OCINumberFromInt(). //----------------------------------------------------------------------------- int dpiOci__numberFromInt(const void *value, unsigned int valueLength, unsigned int flags, void *number, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINumberFromInt", dpiOciSymbols.fnNumberFromInt) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnNumberFromInt)(error->handle, value, valueLength, flags, number); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number from integer"); } //----------------------------------------------------------------------------- // dpiOci__numberFromReal() [INTERNAL] // Wrapper for OCINumberFromReal(). //----------------------------------------------------------------------------- int dpiOci__numberFromReal(const double value, void *number, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINumberFromReal", dpiOciSymbols.fnNumberFromReal) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnNumberFromReal)(error->handle, &value, sizeof(double), number); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number from real"); } //----------------------------------------------------------------------------- // dpiOci__numberToInt() [INTERNAL] // Wrapper for OCINumberToInt(). //----------------------------------------------------------------------------- int dpiOci__numberToInt(void *number, void *value, unsigned int valueLength, unsigned int flags, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINumberToInt", dpiOciSymbols.fnNumberToInt) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnNumberToInt)(error->handle, number, valueLength, flags, value); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number to integer"); } //----------------------------------------------------------------------------- // dpiOci__numberToReal() [INTERNAL] // Wrapper for OCINumberToReal(). //----------------------------------------------------------------------------- int dpiOci__numberToReal(double *value, void *number, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCINumberToReal", dpiOciSymbols.fnNumberToReal) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnNumberToReal)(error->handle, number, sizeof(double), value); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "number to real"); } //----------------------------------------------------------------------------- // dpiOci__objectCopy() [INTERNAL] // Wrapper for OCIObjectCopy(). //----------------------------------------------------------------------------- int dpiOci__objectCopy(dpiObject *obj, void *sourceInstance, void *sourceIndicator, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectCopy", dpiOciSymbols.fnObjectCopy) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectCopy)(obj->env->handle, error->handle, obj->type->conn->handle, sourceInstance, sourceIndicator, obj->instance, obj->indicator, obj->type->tdo, DPI_OCI_DURATION_SESSION, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "copy object"); } //----------------------------------------------------------------------------- // dpiOci__objectFree() [INTERNAL] // Wrapper for OCIObjectFree(). //----------------------------------------------------------------------------- int dpiOci__objectFree(void *envHandle, void *data, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectFree", dpiOciSymbols.fnObjectFree) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectFree)(envHandle, error->handle, data, DPI_OCI_DEFAULT); if (checkError && DPI_OCI_ERROR_OCCURRED(status)) { dpiError__setFromOCI(error, status, NULL, "free instance"); // during the attempt to free, PL/SQL records fail with error // "ORA-21602: operation does not support the specified typecode", but // a subsequent attempt will yield error "OCI-21500: internal error // code" and crash the process, so pretend like the free was // successful! if (error->buffer->code == 21602) return DPI_SUCCESS; return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__objectGetAttr() [INTERNAL] // Wrapper for OCIObjectGetAttr(). //----------------------------------------------------------------------------- int dpiOci__objectGetAttr(dpiObject *obj, dpiObjectAttr *attr, int16_t *scalarValueIndicator, void **valueIndicator, void **value, void **tdo, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectGetAttr", dpiOciSymbols.fnObjectGetAttr) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectGetAttr)(obj->env->handle, error->handle, obj->instance, obj->indicator, obj->type->tdo, &attr->name, &attr->nameLength, 1, 0, 0, scalarValueIndicator, valueIndicator, value, tdo); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get attribute"); } //----------------------------------------------------------------------------- // dpiOci__objectGetInd() [INTERNAL] // Wrapper for OCIObjectGetInd(). //----------------------------------------------------------------------------- int dpiOci__objectGetInd(dpiObject *obj, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectGetInd", dpiOciSymbols.fnObjectGetInd) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectGetInd)(obj->env->handle, error->handle, obj->instance, &obj->indicator); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get indicator"); } //----------------------------------------------------------------------------- // dpiOci__objectNew() [INTERNAL] // Wrapper for OCIObjectNew(). //----------------------------------------------------------------------------- int dpiOci__objectNew(dpiObject *obj, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectNew", dpiOciSymbols.fnObjectNew) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectNew)(obj->env->handle, error->handle, obj->type->conn->handle, obj->type->typeCode, obj->type->tdo, NULL, DPI_OCI_DURATION_SESSION, 1, &obj->instance); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "create object"); } //----------------------------------------------------------------------------- // dpiOci__objectPin() [INTERNAL] // Wrapper for OCIObjectPin(). //----------------------------------------------------------------------------- int dpiOci__objectPin(void *envHandle, void *objRef, void **obj, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectPin", dpiOciSymbols.fnObjectPin) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectPin)(envHandle, error->handle, objRef, NULL, DPI_OCI_PIN_ANY, DPI_OCI_DURATION_SESSION, DPI_OCI_LOCK_NONE, obj); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "pin reference"); } //----------------------------------------------------------------------------- // dpiOci__objectSetAttr() [INTERNAL] // Wrapper for OCIObjectSetAttr(). //----------------------------------------------------------------------------- int dpiOci__objectSetAttr(dpiObject *obj, dpiObjectAttr *attr, int16_t scalarValueIndicator, void *valueIndicator, const void *value, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIObjectSetAttr", dpiOciSymbols.fnObjectSetAttr) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnObjectSetAttr)(obj->env->handle, error->handle, obj->instance, obj->indicator, obj->type->tdo, &attr->name, &attr->nameLength, 1, NULL, 0, scalarValueIndicator, valueIndicator, value); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "set attribute"); } //----------------------------------------------------------------------------- // dpiOci__passwordChange() [INTERNAL] // Wrapper for OCIPasswordChange(). //----------------------------------------------------------------------------- int dpiOci__passwordChange(dpiConn *conn, const char *userName, uint32_t userNameLength, const char *oldPassword, uint32_t oldPasswordLength, const char *newPassword, uint32_t newPasswordLength, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIPasswordChange", dpiOciSymbols.fnPasswordChange) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnPasswordChange)(conn->handle, error->handle, userName, userNameLength, oldPassword, oldPasswordLength, newPassword, newPasswordLength, mode); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "change password"); } //----------------------------------------------------------------------------- // dpiOci__paramGet() [INTERNAL] // Wrapper for OCIParamGet(). //----------------------------------------------------------------------------- int dpiOci__paramGet(const void *handle, uint32_t handleType, void **parameter, uint32_t pos, const char *action, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIParamGet", dpiOciSymbols.fnParamGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnParamGet)(handle, handleType, error->handle, parameter, pos); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, action); } //----------------------------------------------------------------------------- // dpiOci__ping() [INTERNAL] // Wrapper for OCIPing(). //----------------------------------------------------------------------------- int dpiOci__ping(dpiConn *conn, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIPing", dpiOciSymbols.fnPing) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnPing)(conn->handle, error->handle, DPI_OCI_DEFAULT); if (DPI_OCI_ERROR_OCCURRED(status)) { dpiError__setFromOCI(error, status, conn, "ping"); // attempting to ping a database earlier than 10g will result in error // ORA-1010: invalid OCI operation, but that implies a successful ping // so ignore that error and treat it as a successful operation if (error->buffer->code == 1010) return DPI_SUCCESS; return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__rawAssignBytes() [INTERNAL] // Wrapper for OCIRawAssignBytes(). //----------------------------------------------------------------------------- int dpiOci__rawAssignBytes(void *envHandle, const char *value, uint32_t valueLength, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIRawAssignBytes", dpiOciSymbols.fnRawAssignBytes) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnRawAssignBytes)(envHandle, error->handle, value, valueLength, handle); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "assign bytes to raw"); } //----------------------------------------------------------------------------- // dpiOci__rawPtr() [INTERNAL] // Wrapper for OCIRawPtr(). //----------------------------------------------------------------------------- int dpiOci__rawPtr(void *envHandle, void *handle, void **ptr) { dpiError *error = NULL; DPI_OCI_LOAD_SYMBOL("OCIRawPtr", dpiOciSymbols.fnRawPtr) *ptr = (*dpiOciSymbols.fnRawPtr)(envHandle, handle); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__rawResize() [INTERNAL] // Wrapper for OCIRawResize(). //----------------------------------------------------------------------------- int dpiOci__rawResize(void *envHandle, void **handle, uint32_t newSize, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIRawResize", dpiOciSymbols.fnRawResize) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnRawResize)(envHandle, error->handle, newSize, handle); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "resize raw"); } //----------------------------------------------------------------------------- // dpiOci__rawSize() [INTERNAL] // Wrapper for OCIRawSize(). //----------------------------------------------------------------------------- int dpiOci__rawSize(void *envHandle, void *handle, uint32_t *size) { dpiError *error = NULL; DPI_OCI_LOAD_SYMBOL("OCIRawSize", dpiOciSymbols.fnRawSize) *size = (*dpiOciSymbols.fnRawSize)(envHandle, handle); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__reallocMem() [INTERNAL] // Wrapper for OCI allocation of memory, only used when debugging memory // allocation. //----------------------------------------------------------------------------- static void *dpiOci__reallocMem(UNUSED void *unused, void *ptr, size_t newSize) { char message[80]; void *newPtr; (void) sprintf(message, "OCI reallocated ptr at %p", ptr); newPtr = realloc(ptr, newSize); dpiDebug__print("%s to %u bytes at %p\n", message, newSize, newPtr); return newPtr; } //----------------------------------------------------------------------------- // dpiOci__rowidToChar() [INTERNAL] // Wrapper for OCIRowidToChar(). //----------------------------------------------------------------------------- int dpiOci__rowidToChar(dpiRowid *rowid, char *buffer, uint16_t *bufferSize, dpiError *error) { uint16_t origSize; int status; DPI_OCI_LOAD_SYMBOL("OCIRowidToChar", dpiOciSymbols.fnRowidToChar) DPI_OCI_ENSURE_ERROR_HANDLE(error) origSize = *bufferSize; status = (*dpiOciSymbols.fnRowidToChar)(rowid->handle, buffer, bufferSize, error->handle); if (origSize == 0) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get rowid as string"); } //----------------------------------------------------------------------------- // dpiOci__serverAttach() [INTERNAL] // Wrapper for OCIServerAttach(). //----------------------------------------------------------------------------- int dpiOci__serverAttach(dpiConn *conn, const char *connectString, uint32_t connectStringLength, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIServerAttach", dpiOciSymbols.fnServerAttach) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnServerAttach)(conn->serverHandle, error->handle, connectString, (int32_t) connectStringLength, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "server attach"); } //----------------------------------------------------------------------------- // dpiOci__serverDetach() [INTERNAL] // Wrapper for OCIServerDetach(). //----------------------------------------------------------------------------- int dpiOci__serverDetach(dpiConn *conn, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIServerDetach", dpiOciSymbols.fnServerDetach) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnServerDetach)(conn->serverHandle, error->handle, DPI_OCI_DEFAULT); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "detatch from server"); } //----------------------------------------------------------------------------- // dpiOci__serverRelease() [INTERNAL] // Wrapper for OCIServerRelease(). //----------------------------------------------------------------------------- int dpiOci__serverRelease(dpiConn *conn, char *buffer, uint32_t bufferSize, uint32_t *version, uint32_t mode, dpiError *error) { int status; DPI_OCI_ENSURE_ERROR_HANDLE(error) if (conn->env->versionInfo->versionNum < 18) { DPI_OCI_LOAD_SYMBOL("OCIServerRelease", dpiOciSymbols.fnServerRelease) status = (*dpiOciSymbols.fnServerRelease)(conn->handle, error->handle, buffer, bufferSize, DPI_OCI_HTYPE_SVCCTX, version); } else { DPI_OCI_LOAD_SYMBOL("OCIServerRelease2", dpiOciSymbols.fnServerRelease2) status = (*dpiOciSymbols.fnServerRelease2)(conn->handle, error->handle, buffer, bufferSize, DPI_OCI_HTYPE_SVCCTX, version, mode); } DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get server version"); } //----------------------------------------------------------------------------- // dpiOci__sessionBegin() [INTERNAL] // Wrapper for OCISessionBegin(). //----------------------------------------------------------------------------- int dpiOci__sessionBegin(dpiConn *conn, uint32_t credentialType, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISessionBegin", dpiOciSymbols.fnSessionBegin) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSessionBegin)(conn->handle, error->handle, conn->sessionHandle, credentialType, mode); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "begin session"); } //----------------------------------------------------------------------------- // dpiOci__sessionEnd() [INTERNAL] // Wrapper for OCISessionEnd(). //----------------------------------------------------------------------------- int dpiOci__sessionEnd(dpiConn *conn, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISessionEnd", dpiOciSymbols.fnSessionEnd) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSessionEnd)(conn->handle, error->handle, conn->sessionHandle, DPI_OCI_DEFAULT); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "end session"); } //----------------------------------------------------------------------------- // dpiOci__sessionGet() [INTERNAL] // Wrapper for OCISessionGet(). //----------------------------------------------------------------------------- int dpiOci__sessionGet(void *envHandle, void **handle, void *authInfo, const char *connectString, uint32_t connectStringLength, const char *tag, uint32_t tagLength, const char **outTag, uint32_t *outTagLength, int *found, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISessionGet", dpiOciSymbols.fnSessionGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSessionGet)(envHandle, error->handle, handle, authInfo, connectString, connectStringLength, tag, tagLength, outTag, outTagLength, found, mode); // OCI might return a stale handle even though the call to OCISessionGet() // failed; clear it to avoid unexpected errors being thrown, masking any // true errors if (status < 0) *handle = NULL; DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "get session"); } //----------------------------------------------------------------------------- // dpiOci__sessionPoolCreate() [INTERNAL] // Wrapper for OCISessionPoolCreate(). //----------------------------------------------------------------------------- int dpiOci__sessionPoolCreate(dpiPool *pool, const char *connectString, uint32_t connectStringLength, uint32_t minSessions, uint32_t maxSessions, uint32_t sessionIncrement, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISessionPoolCreate", dpiOciSymbols.fnSessionPoolCreate) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSessionPoolCreate)(pool->env->handle, error->handle, pool->handle, (char**) &pool->name, &pool->nameLength, connectString, connectStringLength, minSessions, maxSessions, sessionIncrement, userName, userNameLength, password, passwordLength, mode); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "create pool"); } //----------------------------------------------------------------------------- // dpiOci__sessionPoolDestroy() [INTERNAL] // Wrapper for OCISessionPoolDestroy(). //----------------------------------------------------------------------------- int dpiOci__sessionPoolDestroy(dpiPool *pool, uint32_t mode, int checkError, dpiError *error) { void *handle; int status; DPI_OCI_LOAD_SYMBOL("OCISessionPoolDestroy", dpiOciSymbols.fnSessionPoolDestroy) DPI_OCI_ENSURE_ERROR_HANDLE(error) // clear the pool handle immediately so that no further attempts are made // to use the pool while the pool is being closed; if the pool close fails, // restore the pool handle afterwards handle = pool->handle; pool->handle = NULL; status = (*dpiOciSymbols.fnSessionPoolDestroy)(handle, error->handle, mode); if (checkError && DPI_OCI_ERROR_OCCURRED(status)) { pool->handle = handle; return dpiError__setFromOCI(error, status, NULL, "destroy pool"); } dpiOci__handleFree(handle, DPI_OCI_HTYPE_SPOOL); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__sessionRelease() [INTERNAL] // Wrapper for OCISessionRelease(). //----------------------------------------------------------------------------- int dpiOci__sessionRelease(dpiConn *conn, const char *tag, uint32_t tagLength, uint32_t mode, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISessionRelease", dpiOciSymbols.fnSessionRelease) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSessionRelease)(conn->handle, error->handle, tag, tagLength, mode); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "release session"); } //----------------------------------------------------------------------------- // dpiOci__shardingKeyColumnAdd() [INTERNAL] // Wrapper for OCIshardingKeyColumnAdd(). //----------------------------------------------------------------------------- int dpiOci__shardingKeyColumnAdd(void *shardingKey, void *col, uint32_t colLen, uint16_t colType, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIShardingKeyColumnAdd", dpiOciSymbols.fnShardingKeyColumnAdd) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnShardingKeyColumnAdd)(shardingKey, error->handle, col, colLen, colType, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "add sharding column"); } //----------------------------------------------------------------------------- // dpiOci__sodaBulkInsert() [INTERNAL] // Wrapper for OCISodaBulkInsert(). //----------------------------------------------------------------------------- int dpiOci__sodaBulkInsert(dpiSodaColl *coll, void **documents, uint32_t numDocuments, void *outputOptions, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsert", dpiOciSymbols.fnSodaBulkInsert) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaBulkInsert)(coll->db->conn->handle, coll->handle, documents, numDocuments, outputOptions, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "insert multiple documents"); } //----------------------------------------------------------------------------- // dpiOci__sodaBulkInsertAndGet() [INTERNAL] // Wrapper for OCISodaBulkInsertAndGet(). //----------------------------------------------------------------------------- int dpiOci__sodaBulkInsertAndGet(dpiSodaColl *coll, void **documents, uint32_t numDocuments, void *outputOptions, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsertAndGet", dpiOciSymbols.fnSodaBulkInsertAndGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaBulkInsertAndGet)(coll->db->conn->handle, coll->handle, documents, numDocuments, outputOptions, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "insert (and get) multiple documents"); } //----------------------------------------------------------------------------- // dpiOci__sodaBulkInsertAndGetWithOpts() [INTERNAL] // Wrapper for OCISodaBulkInsertAndGetWithOpts(). //----------------------------------------------------------------------------- int dpiOci__sodaBulkInsertAndGetWithOpts(dpiSodaColl *coll, void **documents, uint32_t numDocuments, void *operOptions, void *outputOptions, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaBulkInsertAndGetWithOpts", dpiOciSymbols.fnSodaBulkInsertAndGetWithOpts) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaBulkInsertAndGetWithOpts) (coll->db->conn->handle, coll->handle, documents, numDocuments, operOptions, outputOptions, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "insert (and get) multiple documents with options"); } //----------------------------------------------------------------------------- // dpiOci__sodaCollCreateWithMetadata() [INTERNAL] // Wrapper for OCISodaCollCreateWithMetadata(). //----------------------------------------------------------------------------- int dpiOci__sodaCollCreateWithMetadata(dpiSodaDb *db, const char *name, uint32_t nameLength, const char *metadata, uint32_t metadataLength, uint32_t mode, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaCollCreateWithMetadata", dpiOciSymbols.fnSodaCollCreateWithMetadata) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaCollCreateWithMetadata)(db->conn->handle, name, nameLength, metadata, metadataLength, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, "create SODA collection"); } //----------------------------------------------------------------------------- // dpiOci__sodaCollDrop() [INTERNAL] // Wrapper for OCISodaCollDrop(). //----------------------------------------------------------------------------- int dpiOci__sodaCollDrop(dpiSodaColl *coll, int *isDropped, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaCollDrop", dpiOciSymbols.fnSodaCollDrop) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaCollDrop)(coll->db->conn->handle, coll->handle, isDropped, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "drop SODA collection"); } //----------------------------------------------------------------------------- // dpiOci__sodaCollGetNext() [INTERNAL] // Wrapper for OCISodaCollGetNext(). //----------------------------------------------------------------------------- int dpiOci__sodaCollGetNext(dpiConn *conn, void *cursorHandle, void **collectionHandle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaCollGetNext", dpiOciSymbols.fnSodaCollGetNext) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaCollGetNext)(conn->handle, cursorHandle, collectionHandle, error->handle, DPI_OCI_DEFAULT); if (status == DPI_OCI_NO_DATA) { *collectionHandle = NULL; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get next collection"); } //----------------------------------------------------------------------------- // dpiOci__sodaCollList() [INTERNAL] // Wrapper for OCISodaCollList(). //----------------------------------------------------------------------------- int dpiOci__sodaCollList(dpiSodaDb *db, const char *startingName, uint32_t startingNameLength, void **handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaCollList", dpiOciSymbols.fnSodaCollList) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaCollList)(db->conn->handle, startingName, startingNameLength, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, "get SODA collection cursor"); } //----------------------------------------------------------------------------- // dpiOci__sodaCollOpen() [INTERNAL] // Wrapper for OCISodaCollOpen(). //----------------------------------------------------------------------------- int dpiOci__sodaCollOpen(dpiSodaDb *db, const char *name, uint32_t nameLength, uint32_t mode, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaCollOpen", dpiOciSymbols.fnSodaCollOpen) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaCollOpen)(db->conn->handle, name, nameLength, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, db->conn, "open SODA collection"); } //----------------------------------------------------------------------------- // dpiOci__sodaCollTruncate() [INTERNAL] // Wrapper for OCISodaCollTruncate(). //----------------------------------------------------------------------------- int dpiOci__sodaCollTruncate(dpiSodaColl *coll, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaCollTruncate", dpiOciSymbols.fnSodaCollTruncate) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaCollTruncate)(coll->db->conn->handle, coll->handle, error->handle, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "truncate SODA collection"); } //----------------------------------------------------------------------------- // dpiOci__sodaDataGuideGet() [INTERNAL] // Wrapper for OCISodaDataGuideGet(). //----------------------------------------------------------------------------- int dpiOci__sodaDataGuideGet(dpiSodaColl *coll, void **handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaDataGuideGet", dpiOciSymbols.fnSodaDataGuideGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaDataGuideGet)(coll->db->conn->handle, coll->handle, DPI_OCI_SODA_AS_AL32UTF8, handle, error->handle, mode); if (DPI_OCI_ERROR_OCCURRED(status)) { dpiError__setFromOCI(error, status, coll->db->conn, "get data guide"); if (error->buffer->code != 24801) return DPI_FAILURE; *handle = NULL; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__sodaDocCount() [INTERNAL] // Wrapper for OCISodaDocCount(). //----------------------------------------------------------------------------- int dpiOci__sodaDocCount(dpiSodaColl *coll, void *options, uint32_t mode, uint64_t *count, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaDocCount", dpiOciSymbols.fnSodaDocCount) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaDocCount)(coll->db->conn->handle, coll->handle, options, count, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "get document count"); } //----------------------------------------------------------------------------- // dpiOci__sodaDocGetNext() [INTERNAL] // Wrapper for OCISodaDocGetNext(). //----------------------------------------------------------------------------- int dpiOci__sodaDocGetNext(dpiSodaDocCursor *cursor, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaDocGetNext", dpiOciSymbols.fnSodaDocGetNext) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaDocGetNext)(cursor->coll->db->conn->handle, cursor->handle, handle, error->handle, DPI_OCI_DEFAULT); if (status == DPI_OCI_NO_DATA) { *handle = NULL; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, cursor->coll->db->conn, "get next document"); } //----------------------------------------------------------------------------- // dpiOci__sodaFind() [INTERNAL] // Wrapper for OCISodaFind(). //----------------------------------------------------------------------------- int dpiOci__sodaFind(dpiSodaColl *coll, const void *options, uint32_t flags, uint32_t mode, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaFind", dpiOciSymbols.fnSodaFind) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaFind)(coll->db->conn->handle, coll->handle, options, flags, handle, error->handle, mode); if (status == DPI_OCI_NO_DATA) { *handle = NULL; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "find SODA documents"); } //----------------------------------------------------------------------------- // dpiOci__sodaFindOne() [INTERNAL] // Wrapper for OCISodaFindOne(). //----------------------------------------------------------------------------- int dpiOci__sodaFindOne(dpiSodaColl *coll, const void *options, uint32_t flags, uint32_t mode, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaFindOne", dpiOciSymbols.fnSodaFindOne) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaFindOne)(coll->db->conn->handle, coll->handle, options, flags, handle, error->handle, mode); if (status == DPI_OCI_NO_DATA) { *handle = NULL; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "get SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaIndexCreate() [INTERNAL] // Wrapper for OCISodaIndexCreate(). //----------------------------------------------------------------------------- int dpiOci__sodaIndexCreate(dpiSodaColl *coll, const char *indexSpec, uint32_t indexSpecLength, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaIndexCreate", dpiOciSymbols.fnSodaIndexCreate) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaIndexCreate)(coll->db->conn->handle, coll->handle, indexSpec, indexSpecLength, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "create index"); } //----------------------------------------------------------------------------- // dpiOci__sodaIndexDrop() [INTERNAL] // Wrapper for OCISodaIndexDrop(). //----------------------------------------------------------------------------- int dpiOci__sodaIndexDrop(dpiSodaColl *coll, const char *name, uint32_t nameLength, uint32_t mode, int *isDropped, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaIndexDrop", dpiOciSymbols.fnSodaIndexDrop) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaIndexDrop)(coll->db->conn->handle, name, nameLength, isDropped, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "drop index"); } //----------------------------------------------------------------------------- // dpiOci__sodaIndexList() [INTERNAL] // Wrapper for OCISodaIndexList(). //----------------------------------------------------------------------------- int dpiOci__sodaIndexList(dpiSodaColl *coll, uint32_t flags, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaIndexList", dpiOciSymbols.fnSodaIndexList) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaIndexList)(coll->db->conn->handle, coll->handle, flags, handle, error->handle, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "get index list"); } //----------------------------------------------------------------------------- // dpiOci__sodaInsert() [INTERNAL] // Wrapper for OCISodaInsert(). //----------------------------------------------------------------------------- int dpiOci__sodaInsert(dpiSodaColl *coll, void *handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaInsert", dpiOciSymbols.fnSodaInsert) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaInsert)(coll->db->conn->handle, coll->handle, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "insert SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaInsertAndGet() [INTERNAL] // Wrapper for OCISodaInsertAndGet(). //----------------------------------------------------------------------------- int dpiOci__sodaInsertAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaInsertAndGet", dpiOciSymbols.fnSodaInsertAndGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaInsertAndGet)(coll->db->conn->handle, coll->handle, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "insert and get SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaInsertAndGetWithOpts() [INTERNAL] // Wrapper for OCISodaInsertAndGetWithOpts(). //----------------------------------------------------------------------------- int dpiOci__sodaInsertAndGetWithOpts(dpiSodaColl *coll, void **handle, void *operOptions, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaInsertAndGetWithOpts", dpiOciSymbols.fnSodaInsertAndGetWithOpts) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaInsertAndGetWithOpts) (coll->db->conn->handle, coll->handle, handle, operOptions, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "insert and get SODA document with options"); } //----------------------------------------------------------------------------- // dpiOci__sodaOperKeysSet() [INTERNAL] // Wrapper for OCISodaOperKeysSet(). //----------------------------------------------------------------------------- int dpiOci__sodaOperKeysSet(const dpiSodaOperOptions *options, void *handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaOperKeysSet", dpiOciSymbols.fnSodaOperKeysSet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaOperKeysSet)(handle, options->keys, options->keyLengths, options->numKeys, error->handle, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "set operation options keys"); } //----------------------------------------------------------------------------- // dpiOci__sodaRemove() [INTERNAL] // Wrapper for OCISodaRemove(). //----------------------------------------------------------------------------- int dpiOci__sodaRemove(dpiSodaColl *coll, void *options, uint32_t mode, uint64_t *count, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaRemove", dpiOciSymbols.fnSodaRemove) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaRemove)(coll->db->conn->handle, coll->handle, options, count, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "remove documents from SODA collection"); } //----------------------------------------------------------------------------- // dpiOci__sodaReplOne() [INTERNAL] // Wrapper for OCISodaReplOne(). //----------------------------------------------------------------------------- int dpiOci__sodaReplOne(dpiSodaColl *coll, const void *options, void *handle, uint32_t mode, int *isReplaced, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaReplOne", dpiOciSymbols.fnSodaReplOne) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaReplOne)(coll->db->conn->handle, coll->handle, options, handle, isReplaced, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "replace SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaReplOneAndGet() [INTERNAL] // Wrapper for OCISodaReplOneAndGet(). //----------------------------------------------------------------------------- int dpiOci__sodaReplOneAndGet(dpiSodaColl *coll, const void *options, void **handle, uint32_t mode, int *isReplaced, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaReplOneAndGet", dpiOciSymbols.fnSodaReplOneAndGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaReplOneAndGet)(coll->db->conn->handle, coll->handle, options, handle, isReplaced, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "replace and get SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaSave() [INTERNAL] // Wrapper for OCISodaSave(). //----------------------------------------------------------------------------- int dpiOci__sodaSave(dpiSodaColl *coll, void *handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaSave", dpiOciSymbols.fnSodaSave) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaSave)(coll->db->conn->handle, coll->handle, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "save SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaSaveAndGet() [INTERNAL] // Wrapper for OCISodaSaveAndGet(). //----------------------------------------------------------------------------- int dpiOci__sodaSaveAndGet(dpiSodaColl *coll, void **handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaSaveAndGet", dpiOciSymbols.fnSodaSaveAndGet) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaSaveAndGet)(coll->db->conn->handle, coll->handle, handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "save and get SODA document"); } //----------------------------------------------------------------------------- // dpiOci__sodaSaveAndGetWithOpts() [INTERNAL] // Wrapper for OCISodaSaveAndGetWithOpts(). //----------------------------------------------------------------------------- int dpiOci__sodaSaveAndGetWithOpts(dpiSodaColl *coll, void **handle, void *operOptions, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISodaSaveAndGetWithOpts", dpiOciSymbols.fnSodaSaveAndGetWithOpts) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSodaSaveAndGetWithOpts)(coll->db->conn->handle, coll->handle, handle, operOptions, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, coll->db->conn, "save and get SODA document"); } //----------------------------------------------------------------------------- // dpiOci__stmtExecute() [INTERNAL] // Wrapper for OCIStmtExecute(). //----------------------------------------------------------------------------- int dpiOci__stmtExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIStmtExecute", dpiOciSymbols.fnStmtExecute) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStmtExecute)(stmt->conn->handle, stmt->handle, error->handle, numIters, 0, 0, 0, mode); DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "execute"); } //----------------------------------------------------------------------------- // dpiOci__stmtFetch2() [INTERNAL] // Wrapper for OCIStmtFetch2(). //----------------------------------------------------------------------------- int dpiOci__stmtFetch2(dpiStmt *stmt, uint32_t numRows, uint16_t fetchMode, int32_t offset, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIStmtFetch2", dpiOciSymbols.fnStmtFetch2) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStmtFetch2)(stmt->handle, error->handle, numRows, fetchMode, offset, DPI_OCI_DEFAULT); if (status == DPI_OCI_NO_DATA || fetchMode == DPI_MODE_FETCH_LAST) { stmt->hasRowsToFetch = 0; } else if (DPI_OCI_ERROR_OCCURRED(status)) { return dpiError__setFromOCI(error, status, stmt->conn, "fetch"); } else { stmt->hasRowsToFetch = 1; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__stmtGetBindInfo() [INTERNAL] // Wrapper for OCIStmtGetBindInfo(). //----------------------------------------------------------------------------- int dpiOci__stmtGetBindInfo(dpiStmt *stmt, uint32_t size, uint32_t startLoc, int32_t *numFound, char *names[], uint8_t nameLengths[], char *indNames[], uint8_t indNameLengths[], uint8_t isDuplicate[], void *bindHandles[], dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIStmtGetBindInfo", dpiOciSymbols.fnStmtGetBindInfo) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStmtGetBindInfo)(stmt->handle, error->handle, size, startLoc, numFound, names, nameLengths, indNames, indNameLengths, isDuplicate, bindHandles); if (status == DPI_OCI_NO_DATA) { *numFound = 0; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "get bind info"); } //----------------------------------------------------------------------------- // dpiOci__stmtGetNextResult() [INTERNAL] // Wrapper for OCIStmtGetNextResult(). //----------------------------------------------------------------------------- int dpiOci__stmtGetNextResult(dpiStmt *stmt, void **handle, dpiError *error) { uint32_t returnType; int status; DPI_OCI_LOAD_SYMBOL("OCIStmtGetNextResult", dpiOciSymbols.fnStmtGetNextResult) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStmtGetNextResult)(stmt->handle, error->handle, handle, &returnType, DPI_OCI_DEFAULT); if (status == DPI_OCI_NO_DATA) { *handle = NULL; return DPI_SUCCESS; } DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "get next result"); } //----------------------------------------------------------------------------- // dpiOci__stmtPrepare2() [INTERNAL] // Wrapper for OCIStmtPrepare2(). //----------------------------------------------------------------------------- int dpiOci__stmtPrepare2(dpiStmt *stmt, const char *sql, uint32_t sqlLength, const char *tag, uint32_t tagLength, dpiError *error) { uint32_t mode = DPI_OCI_DEFAULT; int status; DPI_OCI_LOAD_SYMBOL("OCIStmtPrepare2", dpiOciSymbols.fnStmtPrepare2) DPI_OCI_ENSURE_ERROR_HANDLE(error) if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 2, NULL) == DPI_SUCCESS) mode |= DPI_OCI_PREP2_GET_SQL_ID; status = (*dpiOciSymbols.fnStmtPrepare2)(stmt->conn->handle, &stmt->handle, error->handle, sql, sqlLength, tag, tagLength, DPI_OCI_NTV_SYNTAX, mode); if (DPI_OCI_ERROR_OCCURRED(status)) { stmt->handle = NULL; return dpiError__setFromOCI(error, status, stmt->conn, "prepare SQL"); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__stmtRelease() [INTERNAL] // Wrapper for OCIStmtRelease(). //----------------------------------------------------------------------------- int dpiOci__stmtRelease(dpiStmt *stmt, const char *tag, uint32_t tagLength, int checkError, dpiError *error) { uint32_t mode = DPI_OCI_DEFAULT; uint32_t cacheSize = 0; int status; // if the statement should be deleted from the cache, first check to see // that there actually is a cache currently being used; otherwise, the // error "ORA-24300: bad value for mode" will be raised if (stmt->deleteFromCache) { dpiOci__attrGet(stmt->conn->handle, DPI_OCI_HTYPE_SVCCTX, &cacheSize, NULL, DPI_OCI_ATTR_STMTCACHESIZE, NULL, error); if (cacheSize > 0) mode |= DPI_OCI_STRLS_CACHE_DELETE; } DPI_OCI_LOAD_SYMBOL("OCIStmtRelease", dpiOciSymbols.fnStmtRelease) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStmtRelease)(stmt->handle, error->handle, tag, tagLength, mode); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, stmt->conn, "release statement"); } //----------------------------------------------------------------------------- // dpiOci__stringAssignText() [INTERNAL] // Wrapper for OCIStringAssignText(). //----------------------------------------------------------------------------- int dpiOci__stringAssignText(void *envHandle, const char *value, uint32_t valueLength, void **handle, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIStringAssignText", dpiOciSymbols.fnStringAssignText) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStringAssignText)(envHandle, error->handle, value, valueLength, handle); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "assign to string"); } //----------------------------------------------------------------------------- // dpiOci__stringPtr() [INTERNAL] // Wrapper for OCIStringPtr(). //----------------------------------------------------------------------------- int dpiOci__stringPtr(void *envHandle, void *handle, char **ptr) { dpiError *error = NULL; DPI_OCI_LOAD_SYMBOL("OCIStringPtr", dpiOciSymbols.fnStringPtr) *ptr = (*dpiOciSymbols.fnStringPtr)(envHandle, handle); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__stringResize() [INTERNAL] // Wrapper for OCIStringResize(). //----------------------------------------------------------------------------- int dpiOci__stringResize(void *envHandle, void **handle, uint32_t newSize, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIStringResize", dpiOciSymbols.fnStringResize) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnStringResize)(envHandle, error->handle, newSize, handle); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "resize string"); } //----------------------------------------------------------------------------- // dpiOci__stringSize() [INTERNAL] // Wrapper for OCIStringSize(). //----------------------------------------------------------------------------- int dpiOci__stringSize(void *envHandle, void *handle, uint32_t *size) { dpiError *error = NULL; DPI_OCI_LOAD_SYMBOL("OCIStringSize", dpiOciSymbols.fnStringSize) *size = (*dpiOciSymbols.fnStringSize)(envHandle, handle); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__subscriptionRegister() [INTERNAL] // Wrapper for OCISubscriptionRegister(). //----------------------------------------------------------------------------- int dpiOci__subscriptionRegister(dpiConn *conn, void **handle, uint32_t mode, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCISubscriptionRegister", dpiOciSymbols.fnSubscriptionRegister) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnSubscriptionRegister)(conn->handle, handle, 1, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "register"); } //----------------------------------------------------------------------------- // dpiOci__subscriptionUnRegister() [INTERNAL] // Wrapper for OCISubscriptionUnRegister(). //----------------------------------------------------------------------------- int dpiOci__subscriptionUnRegister(dpiConn *conn, dpiSubscr *subscr, dpiError *error) { uint32_t mode; int status; DPI_OCI_LOAD_SYMBOL("OCISubscriptionUnRegister", dpiOciSymbols.fnSubscriptionUnRegister) DPI_OCI_ENSURE_ERROR_HANDLE(error) mode = (subscr->clientInitiated) ? DPI_OCI_SECURE_NOTIFICATION : DPI_OCI_DEFAULT; status = (*dpiOciSymbols.fnSubscriptionUnRegister)(conn->handle, subscr->handle, error->handle, mode); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "unregister"); } //----------------------------------------------------------------------------- // dpiOci__tableDelete() [INTERNAL] // Wrapper for OCITableDelete(). //----------------------------------------------------------------------------- int dpiOci__tableDelete(dpiObject *obj, int32_t index, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITableDelete", dpiOciSymbols.fnTableDelete) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTableDelete)(obj->env->handle, error->handle, index, obj->instance); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "delete element"); } //----------------------------------------------------------------------------- // dpiOci__tableExists() [INTERNAL] // Wrapper for OCITableExists(). //----------------------------------------------------------------------------- int dpiOci__tableExists(dpiObject *obj, int32_t index, int *exists, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITableExists", dpiOciSymbols.fnTableExists) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTableExists)(obj->env->handle, error->handle, obj->instance, index, exists); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get index exists"); } //----------------------------------------------------------------------------- // dpiOci__tableFirst() [INTERNAL] // Wrapper for OCITableFirst(). //----------------------------------------------------------------------------- int dpiOci__tableFirst(dpiObject *obj, int32_t *index, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITableFirst", dpiOciSymbols.fnTableFirst) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTableFirst)(obj->env->handle, error->handle, obj->instance, index); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get first index"); } //----------------------------------------------------------------------------- // dpiOci__tableLast() [INTERNAL] // Wrapper for OCITableLast(). //----------------------------------------------------------------------------- int dpiOci__tableLast(dpiObject *obj, int32_t *index, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITableLast", dpiOciSymbols.fnTableLast) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTableLast)(obj->env->handle, error->handle, obj->instance, index); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get last index"); } //----------------------------------------------------------------------------- // dpiOci__tableNext() [INTERNAL] // Wrapper for OCITableNext(). //----------------------------------------------------------------------------- int dpiOci__tableNext(dpiObject *obj, int32_t index, int32_t *nextIndex, int *exists, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITableNext", dpiOciSymbols.fnTableNext) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTableNext)(obj->env->handle, error->handle, index, obj->instance, nextIndex, exists); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get next index"); } //----------------------------------------------------------------------------- // dpiOci__tablePrev() [INTERNAL] // Wrapper for OCITablePrev(). //----------------------------------------------------------------------------- int dpiOci__tablePrev(dpiObject *obj, int32_t index, int32_t *prevIndex, int *exists, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITablePrev", dpiOciSymbols.fnTablePrev) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTablePrev)(obj->env->handle, error->handle, index, obj->instance, prevIndex, exists); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get prev index"); } //----------------------------------------------------------------------------- // dpiOci__tableSize() [INTERNAL] // Wrapper for OCITableSize(). //----------------------------------------------------------------------------- int dpiOci__tableSize(dpiObject *obj, int32_t *size, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITableSize", dpiOciSymbols.fnTableSize) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTableSize)(obj->env->handle, error->handle, obj->instance, size); DPI_OCI_CHECK_AND_RETURN(error, status, obj->type->conn, "get size"); } //----------------------------------------------------------------------------- // dpiOci__threadKeyDestroy() [INTERNAL] // Wrapper for OCIThreadKeyDestroy(). //----------------------------------------------------------------------------- int dpiOci__threadKeyDestroy(void *envHandle, void *errorHandle, void **key, dpiError *error) { DPI_OCI_LOAD_SYMBOL("OCIThreadKeyDestroy", dpiOciSymbols.fnThreadKeyDestroy) (*dpiOciSymbols.fnThreadKeyDestroy)(envHandle, errorHandle, key); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__threadKeyGet() [INTERNAL] // Wrapper for OCIThreadKeyGet(). //----------------------------------------------------------------------------- int dpiOci__threadKeyGet(void *envHandle, void *errorHandle, void *key, void **value, dpiError *error) { int status; status = (*dpiOciSymbols.fnThreadKeyGet)(envHandle, errorHandle, key, value); if (status != DPI_OCI_SUCCESS) return dpiError__set(error, "get TLS error", DPI_ERR_TLS_ERROR); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__threadKeyInit() [INTERNAL] // Wrapper for OCIThreadKeyInit(). //----------------------------------------------------------------------------- int dpiOci__threadKeyInit(void *envHandle, void *errorHandle, void **key, void *destroyFunc, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIThreadKeyInit", dpiOciSymbols.fnThreadKeyInit) status = (*dpiOciSymbols.fnThreadKeyInit)(envHandle, errorHandle, key, destroyFunc); DPI_OCI_CHECK_AND_RETURN(error, status, NULL, "initialize thread key"); } //----------------------------------------------------------------------------- // dpiOci__threadKeySet() [INTERNAL] // Wrapper for OCIThreadKeySet(). //----------------------------------------------------------------------------- int dpiOci__threadKeySet(void *envHandle, void *errorHandle, void *key, void *value, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIThreadKeySet", dpiOciSymbols.fnThreadKeySet) status = (*dpiOciSymbols.fnThreadKeySet)(envHandle, errorHandle, key, value); if (status != DPI_OCI_SUCCESS) return dpiError__set(error, "set TLS error", DPI_ERR_TLS_ERROR); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiOci__transCommit() [INTERNAL] // Wrapper for OCITransCommit(). //----------------------------------------------------------------------------- int dpiOci__transCommit(dpiConn *conn, uint32_t flags, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITransCommit", dpiOciSymbols.fnTransCommit) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTransCommit)(conn->handle, error->handle, flags); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "commit"); } //----------------------------------------------------------------------------- // dpiOci__transDetach() [INTERNAL] // Wrapper for OCITransDetach(). //----------------------------------------------------------------------------- int dpiOci__transDetach(dpiConn *conn, uint32_t flags, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITransDetach", dpiOciSymbols.fnTransDetach) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTransDetach)(conn->handle, error->handle, flags); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "detach TPC transaction"); } //----------------------------------------------------------------------------- // dpiOci__transForget() [INTERNAL] // Wrapper for OCITransForget(). //----------------------------------------------------------------------------- int dpiOci__transForget(dpiConn *conn, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITransForget", dpiOciSymbols.fnTransForget) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTransForget)(conn->handle, error->handle, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "forget TPC transaction"); } //----------------------------------------------------------------------------- // dpiOci__transPrepare() [INTERNAL] // Wrapper for OCITransPrepare(). //----------------------------------------------------------------------------- int dpiOci__transPrepare(dpiConn *conn, int *commitNeeded, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITransPrepare", dpiOciSymbols.fnTransPrepare) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTransPrepare)(conn->handle, error->handle, DPI_OCI_DEFAULT); *commitNeeded = (status == DPI_OCI_SUCCESS); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "prepare transaction"); } //----------------------------------------------------------------------------- // dpiOci__transRollback() [INTERNAL] // Wrapper for OCITransRollback(). //----------------------------------------------------------------------------- int dpiOci__transRollback(dpiConn *conn, int checkError, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITransRollback", dpiOciSymbols.fnTransRollback) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTransRollback)(conn->handle, error->handle, DPI_OCI_DEFAULT); if (!checkError) return DPI_SUCCESS; DPI_OCI_CHECK_AND_RETURN(error, status, conn, "rollback"); } //----------------------------------------------------------------------------- // dpiOci__transStart() [INTERNAL] // Wrapper for OCITransStart(). //----------------------------------------------------------------------------- int dpiOci__transStart(dpiConn *conn, uint32_t transactionTimeout, uint32_t flags, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITransStart", dpiOciSymbols.fnTransStart) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTransStart)(conn->handle, error->handle, transactionTimeout, flags); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "start transaction"); } //----------------------------------------------------------------------------- // dpiOci__typeByName() [INTERNAL] // Wrapper for OCITypeByName(). //----------------------------------------------------------------------------- int dpiOci__typeByName(dpiConn *conn, const char *schema, uint32_t schemaLength, const char *name, uint32_t nameLength, void **tdo, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITypeByName", dpiOciSymbols.fnTypeByName) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTypeByName)(conn->env->handle, error->handle, conn->handle, schema, schemaLength, name, nameLength, NULL, 0, DPI_OCI_DURATION_SESSION, DPI_OCI_TYPEGET_ALL, tdo); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get type by name"); } //----------------------------------------------------------------------------- // dpiOci__typeByFullName() [INTERNAL] // Wrapper for OCITypeByFullName(). //----------------------------------------------------------------------------- int dpiOci__typeByFullName(dpiConn *conn, const char *name, uint32_t nameLength, void **tdo, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCITypeByFullName", dpiOciSymbols.fnTypeByFullName) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnTypeByFullName)(conn->env->handle, error->handle, conn->handle, name, nameLength, NULL, 0, DPI_OCI_DURATION_SESSION, DPI_OCI_TYPEGET_ALL, tdo); DPI_OCI_CHECK_AND_RETURN(error, status, conn, "get type by full name"); } //----------------------------------------------------------------------------- // dpiOci__vectorFromArray() [INTERNAL] // Wrapper for OCIVectorFromArray(). //----------------------------------------------------------------------------- int dpiOci__vectorFromArray(dpiVector *vector, dpiVectorInfo *info, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIVectorFromArray", dpiOciSymbols.fnVectorFromArray) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnVectorFromArray)(vector->handle, error->handle, info->format, info->numDimensions, info->dimensions.asPtr, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, vector->conn, "vector from array"); } //----------------------------------------------------------------------------- // dpiOci__vectorFromSparseArray() [INTERNAL] // Wrapper for OCIVectorFromSparseArray(). //----------------------------------------------------------------------------- int dpiOci__vectorFromSparseArray(dpiVector *vector, dpiVectorInfo *info, dpiError *error) { int status; if (dpiUtils__checkClientVersion(vector->env->versionInfo, 23, 7, error) < 0) return DPI_FAILURE; DPI_OCI_LOAD_SYMBOL("OCIVectorFromSparseArray", dpiOciSymbols.fnVectorFromSparseArray) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnVectorFromSparseArray)(vector->handle, error->handle, info->format, info->numDimensions, info->numSparseValues, info->sparseIndices, info->dimensions.asPtr, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, vector->conn, "vector from array"); } //----------------------------------------------------------------------------- // dpiOci__vectorToArray() [INTERNAL] // Wrapper for OCIVectorToArray(). //----------------------------------------------------------------------------- int dpiOci__vectorToArray(dpiVector *vector, dpiError *error) { int status; DPI_OCI_LOAD_SYMBOL("OCIVectorToArray", dpiOciSymbols.fnVectorToArray) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnVectorToArray)(vector->handle, error->handle, vector->format, &vector->numDimensions, vector->dimensions, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, vector->conn, "vector to array"); } //----------------------------------------------------------------------------- // dpiOci__vectorToSparseArray() [INTERNAL] // Wrapper for OCIVectorToSparseArray(). //----------------------------------------------------------------------------- int dpiOci__vectorToSparseArray(dpiVector *vector, dpiError *error) { uint32_t numDimensions = vector->numDimensions; int status; if (dpiUtils__checkClientVersion(vector->env->versionInfo, 23, 7, error) < 0) return DPI_FAILURE; DPI_OCI_LOAD_SYMBOL("OCIVectorToSparseArray", dpiOciSymbols.fnVectorToSparseArray) DPI_OCI_ENSURE_ERROR_HANDLE(error) status = (*dpiOciSymbols.fnVectorToSparseArray)(vector->handle, error->handle, vector->format, &numDimensions, &vector->numSparseValues, vector->sparseIndices, vector->dimensions, DPI_OCI_DEFAULT); DPI_OCI_CHECK_AND_RETURN(error, status, vector->conn, "vector to sparse array"); } odpi-5.6.4/src/dpiOracleType.c000066400000000000000000000773231510466437300162050ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiOracleType.c // Implementation of variable types. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // definition of Oracle types (MUST be in same order as enumeration) //----------------------------------------------------------------------------- static const dpiOracleType dpiAllOracleTypes[DPI_ORACLE_TYPE_MAX - DPI_ORACLE_TYPE_NONE - 1] = { { DPI_ORACLE_TYPE_VARCHAR, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_CHR, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form 0, // buffer size 1, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NVARCHAR, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_CHR, // internal Oracle type DPI_SQLCS_NCHAR, // charset form 0, // buffer size 1, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_CHAR, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_AFC, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form 0, // buffer size 1, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NCHAR, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_AFC, // internal Oracle type DPI_SQLCS_NCHAR, // charset form 0, // buffer size 1, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_ROWID, // public Oracle type DPI_NATIVE_TYPE_ROWID, // default native type DPI_SQLT_RDD, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 1, // is character data 1, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_RAW, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_BIN, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form 0, // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NATIVE_FLOAT, // public Oracle type DPI_NATIVE_TYPE_FLOAT, // default native type DPI_SQLT_BFLOAT, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(float), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NATIVE_DOUBLE, // public Oracle type DPI_NATIVE_TYPE_DOUBLE, // default native type DPI_SQLT_BDOUBLE, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(double), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NATIVE_INT, // public Oracle type DPI_NATIVE_TYPE_INT64, // default native type DPI_SQLT_INT, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(int64_t), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NUMBER, // public Oracle type DPI_NATIVE_TYPE_DOUBLE, // default native type DPI_SQLT_VNU, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form DPI_OCI_NUMBER_SIZE, // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_DATE, // public Oracle type DPI_NATIVE_TYPE_TIMESTAMP, // default native type DPI_SQLT_ODT, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(dpiOciDate), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_TIMESTAMP, // public Oracle type DPI_NATIVE_TYPE_TIMESTAMP, // default native type DPI_SQLT_TIMESTAMP, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_TIMESTAMP_TZ, // public Oracle type DPI_NATIVE_TYPE_TIMESTAMP, // default native type DPI_SQLT_TIMESTAMP_TZ, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_TIMESTAMP_LTZ, // public Oracle type DPI_NATIVE_TYPE_TIMESTAMP, // default native type DPI_SQLT_TIMESTAMP_LTZ, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_INTERVAL_DS, // public Oracle type DPI_NATIVE_TYPE_INTERVAL_DS, // default native type DPI_SQLT_INTERVAL_DS, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_INTERVAL_YM, // public Oracle type DPI_NATIVE_TYPE_INTERVAL_YM, // default native type DPI_SQLT_INTERVAL_YM, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_CLOB, // public Oracle type DPI_NATIVE_TYPE_LOB, // default native type DPI_SQLT_CLOB, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 1, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_NCLOB, // public Oracle type DPI_NATIVE_TYPE_LOB, // default native type DPI_SQLT_CLOB, // internal Oracle type DPI_SQLCS_NCHAR, // charset form sizeof(void*), // buffer size 1, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_BLOB, // public Oracle type DPI_NATIVE_TYPE_LOB, // default native type DPI_SQLT_BLOB, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_BFILE, // public Oracle type DPI_NATIVE_TYPE_LOB, // default native type DPI_SQLT_BFILE, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_STMT, // public Oracle type DPI_NATIVE_TYPE_STMT, // default native type DPI_SQLT_RSET, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_BOOLEAN, // public Oracle type DPI_NATIVE_TYPE_BOOLEAN, // default native type DPI_SQLT_BOL, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(int), // buffer size 0, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_OBJECT, // public Oracle type DPI_NATIVE_TYPE_OBJECT, // default native type DPI_SQLT_NTY, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_LONG_VARCHAR, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_CHR, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size 1, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_LONG_RAW, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_BIN, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size 0, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_NATIVE_UINT, // public Oracle type DPI_NATIVE_TYPE_UINT64, // default native type DPI_SQLT_UIN, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(uint64_t), // buffer size 0, // is character data 1, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_JSON, // public Oracle type DPI_NATIVE_TYPE_JSON, // default native type DPI_SQLT_JSON, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 0, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_JSON_OBJECT, // public Oracle type DPI_NATIVE_TYPE_JSON_OBJECT, // default native type 0, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(dpiJsonObject), // buffer size 0, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_JSON_ARRAY, // public Oracle type DPI_NATIVE_TYPE_JSON_ARRAY, // default native type 0, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(dpiJsonArray), // buffer size 0, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_UROWID, // public Oracle type DPI_NATIVE_TYPE_ROWID, // default native type DPI_SQLT_RDD, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 1, // is character data 1, // can be in array 1 // requires pre-fetch }, { DPI_ORACLE_TYPE_LONG_NVARCHAR, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_CHR, // internal Oracle type DPI_SQLCS_NCHAR, // charset form DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size 1, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_XMLTYPE, // public Oracle type DPI_NATIVE_TYPE_BYTES, // default native type DPI_SQLT_CHR, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form DPI_MAX_BASIC_BUFFER_SIZE + 1, // buffer size 1, // is character data 0, // can be in array 0 // requires pre-fetch }, { DPI_ORACLE_TYPE_VECTOR, // public Oracle type DPI_NATIVE_TYPE_VECTOR, // default native type DPI_SQLT_VEC, // internal Oracle type DPI_SQLCS_IMPLICIT, // charset form sizeof(void*), // buffer size 0, // is character data 0, // can be in array 1 // requires pre-fetch }, }; //----------------------------------------------------------------------------- // dpiOracleType__convertFromOracle() [INTERNAL] // Return a value from the dpiOracleTypeNum enumeration for the OCI data type // and charset form. If the OCI data type is not supported, 0 is returned. //----------------------------------------------------------------------------- static dpiOracleTypeNum dpiOracleType__convertFromOracle(uint16_t typeCode, uint8_t charsetForm) { switch(typeCode) { case DPI_SQLT_CHR: case DPI_SQLT_VCS: if (charsetForm == DPI_SQLCS_NCHAR) return DPI_ORACLE_TYPE_NVARCHAR; return DPI_ORACLE_TYPE_VARCHAR; case DPI_SQLT_INT: case DPI_SQLT_FLT: case DPI_SQLT_NUM: case DPI_SQLT_PDN: case DPI_SQLT_VNU: case DPI_SQLT_BFLOAT: case DPI_SQLT_BDOUBLE: case DPI_OCI_TYPECODE_SMALLINT: return DPI_ORACLE_TYPE_NUMBER; case DPI_SQLT_DAT: case DPI_SQLT_ODT: return DPI_ORACLE_TYPE_DATE; case DPI_SQLT_BIN: case DPI_SQLT_LVB: return DPI_ORACLE_TYPE_RAW; case DPI_SQLT_AFC: if (charsetForm == DPI_SQLCS_NCHAR) return DPI_ORACLE_TYPE_NCHAR; return DPI_ORACLE_TYPE_CHAR; case DPI_OCI_TYPECODE_BINARY_INTEGER: case DPI_OCI_TYPECODE_PLS_INTEGER: return DPI_ORACLE_TYPE_NATIVE_INT; case DPI_SQLT_IBFLOAT: return DPI_ORACLE_TYPE_NATIVE_FLOAT; case DPI_SQLT_IBDOUBLE: return DPI_ORACLE_TYPE_NATIVE_DOUBLE; case DPI_SQLT_DATE: case DPI_SQLT_TIMESTAMP: return DPI_ORACLE_TYPE_TIMESTAMP; case DPI_SQLT_TIMESTAMP_TZ: return DPI_ORACLE_TYPE_TIMESTAMP_TZ; case DPI_SQLT_TIMESTAMP_LTZ: return DPI_ORACLE_TYPE_TIMESTAMP_LTZ; case DPI_SQLT_NTY: case DPI_SQLT_REC: case DPI_SQLT_NCO: return DPI_ORACLE_TYPE_OBJECT; case DPI_SQLT_BOL: return DPI_ORACLE_TYPE_BOOLEAN; case DPI_SQLT_CLOB: if (charsetForm == DPI_SQLCS_NCHAR) return DPI_ORACLE_TYPE_NCLOB; return DPI_ORACLE_TYPE_CLOB; case DPI_SQLT_BLOB: return DPI_ORACLE_TYPE_BLOB; case DPI_SQLT_BFILE: return DPI_ORACLE_TYPE_BFILE; case DPI_SQLT_RDD: case DPI_OCI_TYPECODE_ROWID: return DPI_ORACLE_TYPE_ROWID; case DPI_SQLT_RSET: return DPI_ORACLE_TYPE_STMT; case DPI_SQLT_INTERVAL_DS: return DPI_ORACLE_TYPE_INTERVAL_DS; case DPI_SQLT_INTERVAL_YM: return DPI_ORACLE_TYPE_INTERVAL_YM; case DPI_SQLT_LNG: case DPI_OCI_TYPECODE_LONG: return DPI_ORACLE_TYPE_LONG_VARCHAR; case DPI_SQLT_LBI: case DPI_OCI_TYPECODE_LONG_RAW: return DPI_ORACLE_TYPE_LONG_RAW; case DPI_SQLT_JSON: return DPI_ORACLE_TYPE_JSON; case DPI_SQLT_VEC: return DPI_ORACLE_TYPE_VECTOR; } return (dpiOracleTypeNum) 0; } //----------------------------------------------------------------------------- // dpiOracleType__getFromNum() [INTERNAL] // Return the type associated with the type number. //----------------------------------------------------------------------------- const dpiOracleType *dpiOracleType__getFromNum(dpiOracleTypeNum typeNum, dpiError *error) { if (typeNum > DPI_ORACLE_TYPE_NONE && typeNum < DPI_ORACLE_TYPE_MAX) return &dpiAllOracleTypes[typeNum - DPI_ORACLE_TYPE_NONE - 1]; dpiError__set(error, "check type", DPI_ERR_INVALID_ORACLE_TYPE, typeNum); return NULL; } //----------------------------------------------------------------------------- // dpiOracleType__populateTypeInfo() [INTERNAL] // Populate dpiDataTypeInfo structure given an Oracle descriptor. Note that // no error is raised by this function if the data type is not supported. This // method is called for both implicit and explicit describes (which behave // slightly differently). //----------------------------------------------------------------------------- int dpiOracleType__populateTypeInfo(dpiConn *conn, void *handle, uint32_t handleType, dpiDataTypeInfo *info, dpiError *error) { uint32_t dataTypeAttribute, i, tempFlags; const dpiOracleType *oracleType = NULL; uint8_t charsetForm, isJson, isOson; dpiNativeTypeNum nativeTypeNum; void *listParam, *itemParam; dpiAnnotation *annotation; uint16_t ociSize; // acquire data type if (handleType == DPI_OCI_DTYPE_PARAM) dataTypeAttribute = DPI_OCI_ATTR_TYPECODE; else dataTypeAttribute = DPI_OCI_ATTR_DATA_TYPE; if (dpiOci__attrGet(handle, handleType, (void*) &info->ociTypeCode, 0, dataTypeAttribute, "get data type", error) < 0) return DPI_FAILURE; // acquire character set form if (info->ociTypeCode != DPI_SQLT_CHR && info->ociTypeCode != DPI_SQLT_AFC && info->ociTypeCode != DPI_SQLT_VCS && info->ociTypeCode != DPI_SQLT_CLOB) charsetForm = DPI_SQLCS_IMPLICIT; else if (dpiOci__attrGet(handle, handleType, (void*) &charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, "get charset form", error) < 0) return DPI_FAILURE; // convert Oracle type to ODPI-C enumerations, if possible info->oracleTypeNum = dpiOracleType__convertFromOracle(info->ociTypeCode, charsetForm); if (!info->oracleTypeNum) info->defaultNativeTypeNum = (dpiNativeTypeNum) 0; else { oracleType = dpiOracleType__getFromNum(info->oracleTypeNum, error); if (!oracleType) return DPI_FAILURE; info->defaultNativeTypeNum = oracleType->defaultNativeTypeNum; } // determine precision/scale nativeTypeNum = info->defaultNativeTypeNum; switch (nativeTypeNum) { case DPI_NATIVE_TYPE_DOUBLE: case DPI_NATIVE_TYPE_FLOAT: case DPI_NATIVE_TYPE_INT64: case DPI_NATIVE_TYPE_TIMESTAMP: case DPI_NATIVE_TYPE_INTERVAL_YM: case DPI_NATIVE_TYPE_INTERVAL_DS: if (dpiOci__attrGet(handle, handleType, (void*) &info->scale, 0, DPI_OCI_ATTR_SCALE, "get scale", error) < 0) return DPI_FAILURE; if (dpiOci__attrGet(handle, handleType, (void*) &info->precision, 0, DPI_OCI_ATTR_PRECISION, "get precision", error) < 0) return DPI_FAILURE; if (nativeTypeNum == DPI_NATIVE_TYPE_TIMESTAMP || nativeTypeNum == DPI_NATIVE_TYPE_INTERVAL_DS) { info->fsPrecision = (uint8_t) info->scale; info->scale = 0; } break; default: info->precision = 0; info->fsPrecision = 0; info->scale = 0; break; } // change default type to integer if precision/scale supports it if (info->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER && info->scale == 0 && info->precision > 0 && info->precision <= DPI_MAX_INT64_PRECISION) info->defaultNativeTypeNum = DPI_NATIVE_TYPE_INT64; // acquire size (in bytes) of item info->sizeInChars = 0; if (oracleType && oracleType->sizeInBytes == 0) { if (dpiOci__attrGet(handle, handleType, (void*) &ociSize, 0, DPI_OCI_ATTR_DATA_SIZE, "get size (bytes)", error) < 0) return DPI_FAILURE; info->dbSizeInBytes = ociSize; info->clientSizeInBytes = ociSize; } else { info->dbSizeInBytes = 0; info->clientSizeInBytes = 0; } // acquire size (in characters) of item, if applicable if (oracleType && oracleType->isCharacterData && oracleType->sizeInBytes == 0) { if (dpiOci__attrGet(handle, handleType, (void*) &ociSize, 0, DPI_OCI_ATTR_CHAR_SIZE, "get size (chars)", error) < 0) return DPI_FAILURE; info->sizeInChars = ociSize; if (charsetForm == DPI_SQLCS_NCHAR) info->clientSizeInBytes = info->sizeInChars * conn->env->nmaxBytesPerCharacter; else if (conn->charsetId != conn->env->charsetId) info->clientSizeInBytes = info->sizeInChars * conn->env->maxBytesPerCharacter; } // acquire object type, if applicable if (info->oracleTypeNum == DPI_ORACLE_TYPE_OBJECT) { if (dpiObjectType__allocate(conn, handle, handleType, &info->objectType, error) < 0) return DPI_FAILURE; if (dpiObjectType__isXmlType(info->objectType)) { dpiObjectType__free(info->objectType, error); info->objectType = NULL; info->ociTypeCode = DPI_SQLT_CHR; info->oracleTypeNum = DPI_ORACLE_TYPE_XMLTYPE; info->defaultNativeTypeNum = DPI_NATIVE_TYPE_BYTES; } } // determine if the data refers to a JSON column if (handleType == DPI_OCI_HTYPE_DESCRIBE && conn->env->versionInfo->versionNum >= 19) { if (dpiOci__attrGet(handle, handleType, (void*) &isJson, 0, DPI_OCI_ATTR_JSON_COL, "get is JSON column", error) < 0) return DPI_FAILURE; info->isJson = isJson; } // determine if the data refers to an OSON column if (handleType == DPI_OCI_HTYPE_DESCRIBE && conn->env->versionInfo->versionNum >= 21) { if (dpiOci__attrGet(handle, handleType, (void*) &isOson, 0, DPI_OCI_ATTR_OSON_COL, "get is OSON column", error) < 0) return DPI_FAILURE; info->isOson = isOson; } // get domain and annotations, if applicable if (handleType == DPI_OCI_HTYPE_DESCRIBE && conn->env->versionInfo->versionNum >= 23) { // check for domain if (dpiOci__attrGet(handle, handleType, (void*) &info->domainSchema, &info->domainSchemaLength, DPI_OCI_ATTR_DOMAIN_SCHEMA, "get domain schema", error) < 0) return DPI_FAILURE; if (dpiOci__attrGet(handle, handleType, (void*) &info->domainName, &info->domainNameLength, DPI_OCI_ATTR_DOMAIN_NAME, "get domain name", error) < 0) return DPI_FAILURE; // check for annotations if (dpiOci__attrGet(handle, handleType, (void*) &info->numAnnotations, 0, DPI_OCI_ATTR_NUM_ANNOTATIONS, "get number of annotations", error) < 0) return DPI_FAILURE; if (info->numAnnotations > 0) { // allocate memory for the array if (dpiUtils__allocateMemory(info->numAnnotations, sizeof(dpiAnnotation), 1, "allocate annotation array", (void**) &info->annotations, error) < 0) return DPI_FAILURE; // get the list parameter if (dpiOci__attrGet(handle, handleType, (void*) &listParam, 0, DPI_OCI_ATTR_LIST_ANNOTATIONS, "get annotation list param", error) < 0) return DPI_FAILURE; // populate the arrays for (i = 0 ; i < info->numAnnotations; i++) { annotation = &info->annotations[i]; if (dpiOci__paramGet(listParam, DPI_OCI_DTYPE_PARAM, &itemParam, (uint32_t) i + 1, "get annotation", error) < 0) return DPI_FAILURE; if (dpiOci__attrGet(itemParam, DPI_OCI_DTYPE_PARAM, (void*) &annotation->key, &annotation->keyLength, DPI_OCI_ATTR_ANNOTATION_KEY, "get annotation key", error) < 0) return DPI_FAILURE; if (dpiOci__attrGet(itemParam, DPI_OCI_DTYPE_PARAM, (void*) &annotation->value, &annotation->valueLength, DPI_OCI_ATTR_ANNOTATION_VALUE, "get annotation value", error) < 0) return DPI_FAILURE; } } } // get vector metadata, if applicable if (info->oracleTypeNum == DPI_ORACLE_TYPE_VECTOR) { // get vector format if (dpiOci__attrGet(handle, handleType, &info->vectorFormat, 0, DPI_OCI_ATTR_VECTOR_DATA_FORMAT, "get vector column format", error) < 0) return DPI_FAILURE; // get number of dimensions if (dpiOci__attrGet(handle, handleType, &info->vectorDimensions, 0, DPI_OCI_ATTR_VECTOR_DIMENSION, "get number of vector dimensions in column", error) < 0) return DPI_FAILURE; // get vector column flags // NOTE: all of the values for the vector column flags fit within a // single byte, but the Oracle Client libraries still expect a pointer // to a four byte value and failing to do so causes a segfault on some // platforms if (dpiOci__attrGet(handle, handleType, &tempFlags, 0, DPI_OCI_ATTR_VECTOR_PROPERTY, "get vector column flags", error) < 0) return DPI_FAILURE; info->vectorFlags = (uint8_t) tempFlags; } return DPI_SUCCESS; } odpi-5.6.4/src/dpiPool.c000066400000000000000000001004561510466437300150410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiPool.c // Implementation of session pools. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiPool__acquireConnection() [INTERNAL] // Internal method used for acquiring a connection from a pool. //----------------------------------------------------------------------------- int dpiPool__acquireConnection(dpiPool *pool, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, dpiConnCreateParams *params, dpiConn **conn, dpiError *error) { dpiConn *tempConn; // allocate new connection if (dpiGen__allocate(DPI_HTYPE_CONN, pool->env, (void**) &tempConn, error) < 0) return DPI_FAILURE; error->env = pool->env; // create the connection if (dpiConn__create(tempConn, pool->env->context, userName, userNameLength, password, passwordLength, pool->name, pool->nameLength, pool, NULL, params, error) < 0) { dpiConn__free(tempConn, error); return DPI_FAILURE; } *conn = tempConn; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiPool__checkConnected() [INTERNAL] // Determine if the session pool is connected to the database. If not, an // error is raised. //----------------------------------------------------------------------------- static int dpiPool__checkConnected(dpiPool *pool, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(pool, DPI_HTYPE_POOL, fnName, error) < 0) return DPI_FAILURE; if (!pool->handle) return dpiError__set(error, "check pool", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //---------------------------------------------------------------------------- // dpiPool__accessTokenCallback() [INTERNAL] // Callback used to execute the registered callback when the authentication // token expires and the connection pool needs to create a new connection. // ----------------------------------------------------------------------------- int dpiPool__accessTokenCallback(dpiPool *pool, void *authInfo, UNUSED uint32_t mode) { dpiAccessToken accessToken; dpiError error; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); memset(&accessToken, 0, sizeof(dpiAccessToken)); if ((*pool->accessTokenCallback)(pool->accessTokenCallbackContext, &accessToken) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiUtils__setAccessTokenAttributes(authInfo, &accessToken, pool->env->versionInfo, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool__create() [INTERNAL] // Internal method for creating a session pool. //----------------------------------------------------------------------------- static int dpiPool__create(dpiPool *pool, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiPoolCreateParams *createParams, dpiError *error) { int32_t pingInterval; uint32_t poolMode; uint8_t getMode; void *authInfo; // validate parameters if (createParams->externalAuth && ((userName && userNameLength > 0) || (password && passwordLength > 0))) return dpiError__set(error, "check mixed credentials", DPI_ERR_EXT_AUTH_WITH_CREDENTIALS); // create the session pool handle if (dpiOci__handleAlloc(pool->env->handle, &pool->handle, DPI_OCI_HTYPE_SPOOL, "allocate pool handle", error) < 0) return DPI_FAILURE; // prepare pool mode poolMode = DPI_OCI_SPC_STMTCACHE; if (createParams->homogeneous) poolMode |= DPI_OCI_SPC_HOMOGENEOUS; // create authorization handle if (dpiOci__handleAlloc(pool->env->handle, &authInfo, DPI_OCI_HTYPE_AUTHINFO, "allocate authinfo handle", error) < 0) return DPI_FAILURE; // set context attributes if (dpiUtils__setAttributesFromCommonCreateParams(authInfo, DPI_OCI_HTYPE_AUTHINFO, commonParams, error) < 0) return DPI_FAILURE; // set token based authentication attributes if (commonParams->accessToken) { // homogeneous must be set to true for token based authentication if (!createParams->homogeneous || !createParams->externalAuth) return dpiError__set(error, "check homogeneous and externalAuth", DPI_ERR_POOL_TOKEN_BASED_AUTH); if (dpiUtils__setAccessTokenAttributes(authInfo, commonParams->accessToken, pool->env->versionInfo, error) < 0) return DPI_FAILURE; if (createParams->accessTokenCallback) { // set token based auth context callback on session handle if (dpiOci__attrSet(authInfo, DPI_OCI_HTYPE_SESSION, (void*) pool, 0, DPI_OCI_ATTR_TOKEN_CBKCTX, "set token callback context", error) < 0) return DPI_FAILURE; // set token based auth callback on session handle if (dpiOci__attrSet(authInfo, DPI_OCI_HTYPE_SESSION, (void*) dpiPool__accessTokenCallback, 0, DPI_OCI_ATTR_TOKEN_CBK, "set token callback", error) < 0) return DPI_FAILURE; } } // set PL/SQL session state fixup callback, if applicable if (createParams->plsqlFixupCallback && createParams->plsqlFixupCallbackLength > 0) { if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 2, error) < 0) return DPI_FAILURE; if (dpiOci__attrSet(authInfo, DPI_OCI_HTYPE_AUTHINFO, (void*) createParams->plsqlFixupCallback, createParams->plsqlFixupCallbackLength, DPI_OCI_ATTR_FIXUP_CALLBACK, "set PL/SQL session state fixup callback", error) < 0) return DPI_FAILURE; } // set authorization info on session pool if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) authInfo, 0, DPI_OCI_ATTR_SPOOL_AUTH, "set auth info", error) < 0) return DPI_FAILURE; // set the get mode on the pool getMode = (uint8_t) createParams->getMode; if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &getMode, 0, DPI_OCI_ATTR_SPOOL_GETMODE, "set get mode", error) < 0) return DPI_FAILURE; // set the session timeout on the pool if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &createParams->timeout, 0, DPI_OCI_ATTR_SPOOL_TIMEOUT, "set timeout", error) < 0) return DPI_FAILURE; // set the wait timeout on the pool (valid in 12.2 and higher) if (pool->env->versionInfo->versionNum > 12 || (pool->env->versionInfo->versionNum == 12 && pool->env->versionInfo->releaseNum >= 2)) { if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &createParams->waitTimeout, 0, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, "set wait timeout", error) < 0) return DPI_FAILURE; } // set the maximum lifetime session on the pool (valid in 12.1 and higher) if (pool->env->versionInfo->versionNum >= 12) { if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &createParams->maxLifetimeSession, 0, DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, "set max lifetime session", error) < 0) return DPI_FAILURE; } // set the maximum number of sessions per shard (valid in 18.3 and higher) if (pool->env->versionInfo->versionNum > 18 || (pool->env->versionInfo->versionNum == 18 && pool->env->versionInfo->releaseNum >= 3)) { if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &createParams->maxSessionsPerShard, 0, DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD, "set max sessions per shard", error) < 0) return DPI_FAILURE; } // create pool if (dpiOci__sessionPoolCreate(pool, connectString, connectStringLength, createParams->minSessions, createParams->maxSessions, createParams->sessionIncrement, userName, userNameLength, password, passwordLength, poolMode, error) < 0) return DPI_FAILURE; // set the statement cache size if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &commonParams->stmtCacheSize, 0, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, "set stmt cache size", error) < 0) return DPI_FAILURE; // disable ping interval in Oracle Database 23ai since it does not handle // ping timeout yet if (pool->env->versionInfo->versionNum >= 23) { pingInterval = -1; if (dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void*) &pingInterval, 0, DPI_OCI_ATTR_PING_INTERVAL, "disable ping interval", error) < 0) return DPI_FAILURE; } // set remaining attributes directly pool->homogeneous = createParams->homogeneous; pool->externalAuth = createParams->externalAuth; pool->pingInterval = createParams->pingInterval; pool->pingTimeout = createParams->pingTimeout; pool->stmtCacheSize = commonParams->stmtCacheSize; if (commonParams->accessToken) { pool->accessTokenCallback = createParams->accessTokenCallback; pool->accessTokenCallbackContext = createParams->accessTokenCallbackContext; // force externalAuth to false for token based authentication pool->externalAuth = 0; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiPool__free() [INTERNAL] // Free any memory associated with the pool. //----------------------------------------------------------------------------- void dpiPool__free(dpiPool *pool, dpiError *error) { if (pool->handle) { dpiOci__sessionPoolDestroy(pool, DPI_OCI_SPD_FORCE, 0, error); pool->handle = NULL; } if (pool->env) { dpiEnv__free(pool->env, error); pool->env = NULL; } dpiUtils__freeMemory(pool); } //----------------------------------------------------------------------------- // dpiPool__getAttributeUint() [INTERNAL] // Return the value of the attribute as an unsigned integer. //----------------------------------------------------------------------------- static int dpiPool__getAttributeUint(dpiPool *pool, uint32_t attribute, uint32_t *value, const char *fnName) { dpiError error; int status; if (dpiPool__checkConnected(pool, fnName, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(pool, value) switch (attribute) { case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION: if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 1, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); break; case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT: if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 2, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); break; case DPI_OCI_ATTR_SPOOL_BUSY_COUNT: case DPI_OCI_ATTR_SPOOL_OPEN_COUNT: case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE: case DPI_OCI_ATTR_SPOOL_TIMEOUT: break; case DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD: if (dpiUtils__checkClientVersion(pool->env->versionInfo, 18, 3, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); break; default: dpiError__set(&error, "get attribute value", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); } status = dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value, NULL, attribute, "get attribute value", &error); return dpiGen__endPublicFn(pool, status, &error); } //----------------------------------------------------------------------------- // dpiPool__setAttributeUint() [INTERNAL] // Set the value of the OCI attribute as an unsigned integer. //----------------------------------------------------------------------------- static int dpiPool__setAttributeUint(dpiPool *pool, uint32_t attribute, uint32_t value, const char *fnName) { void *ociValue = &value; uint8_t shortValue; dpiError error; int status; // make sure session pool is connected if (dpiPool__checkConnected(pool, fnName, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); // determine pointer to pass (OCI uses different sizes) switch (attribute) { case DPI_OCI_ATTR_SPOOL_GETMODE: shortValue = (uint8_t) value; ociValue = &shortValue; break; case DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION: if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 1, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); break; case DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT: if (dpiUtils__checkClientVersion(pool->env->versionInfo, 12, 2, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); break; case DPI_OCI_ATTR_SPOOL_STMTCACHESIZE: case DPI_OCI_ATTR_SPOOL_TIMEOUT: break; case DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD: if (dpiUtils__checkClientVersion(pool->env->versionInfo, 18, 3, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); break; default: dpiError__set(&error, "set attribute value", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); } // set value in the OCI status = dpiOci__attrSet(pool->handle, DPI_OCI_HTYPE_SPOOL, ociValue, 0, attribute, "set attribute value", &error); return dpiGen__endPublicFn(pool, status, &error); } //----------------------------------------------------------------------------- // dpiPool_acquireConnection() [PUBLIC] // Acquire a connection from the pool. //----------------------------------------------------------------------------- int dpiPool_acquireConnection(dpiPool *pool, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, dpiConnCreateParams *params, dpiConn **conn) { dpiConnCreateParams localParams; dpiError error; int status; // validate parameters if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(pool, userName) DPI_CHECK_PTR_AND_LENGTH(pool, password) DPI_CHECK_PTR_NOT_NULL(pool, conn) // use default parameters if none provided if (!params) { dpiContext__initConnCreateParams(&localParams); params = &localParams; } // the username must be enclosed within [] if external authentication // with proxy is desired if (pool->externalAuth && userName && userNameLength > 0 && (userName[0] != '[' || userName[userNameLength - 1] != ']')) { dpiError__set(&error, "verify proxy user name with external auth", DPI_ERR_EXT_AUTH_INVALID_PROXY); return dpiGen__endPublicFn(pool, DPI_FAILURE, &error ); } status = dpiPool__acquireConnection(pool, userName, userNameLength, password, passwordLength, params, conn, &error); return dpiGen__endPublicFn(pool, status, &error); } //----------------------------------------------------------------------------- // dpiPool_addRef() [PUBLIC] // Add a reference to the pool. //----------------------------------------------------------------------------- int dpiPool_addRef(dpiPool *pool) { return dpiGen__addRef(pool, DPI_HTYPE_POOL, __func__); } //----------------------------------------------------------------------------- // dpiPool_close() [PUBLIC] // Destroy the pool now, not when the reference count reaches zero. //----------------------------------------------------------------------------- int dpiPool_close(dpiPool *pool, dpiPoolCloseMode mode) { dpiError error; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiOci__sessionPoolDestroy(pool, mode, 1, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_create() [PUBLIC] // Create a new session pool and return it. //----------------------------------------------------------------------------- int dpiPool_create(const dpiContext *context, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *connectString, uint32_t connectStringLength, const dpiCommonCreateParams *commonParams, dpiPoolCreateParams *createParams, dpiPool **pool) { dpiCommonCreateParams localCommonParams; dpiPoolCreateParams localCreateParams; dpiPool *tempPool; dpiError error; // validate parameters if (dpiGen__startPublicFn(context, DPI_HTYPE_CONTEXT, __func__, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(context, userName) DPI_CHECK_PTR_AND_LENGTH(context, password) DPI_CHECK_PTR_AND_LENGTH(context, connectString) DPI_CHECK_PTR_NOT_NULL(context, pool) // use default parameters if none provided if (!commonParams) { dpiContext__initCommonCreateParams(context, &localCommonParams); commonParams = &localCommonParams; } if (!createParams) { dpiContext__initPoolCreateParams(&localCreateParams); createParams = &localCreateParams; } // allocate memory for pool if (dpiGen__allocate(DPI_HTYPE_POOL, NULL, (void**) &tempPool, &error) < 0) return dpiGen__endPublicFn(context, DPI_FAILURE, &error); // initialize environment if (dpiEnv__init(tempPool->env, context, commonParams, NULL, commonParams->createMode | DPI_MODE_CREATE_THREADED, &error) < 0) { dpiPool__free(tempPool, &error); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } // perform remaining steps required to create pool if (dpiPool__create(tempPool, userName, userNameLength, password, passwordLength, connectString, connectStringLength, commonParams, createParams, &error) < 0) { dpiPool__free(tempPool, &error); return dpiGen__endPublicFn(context, DPI_FAILURE, &error); } createParams->outPoolName = tempPool->name; createParams->outPoolNameLength = tempPool->nameLength; *pool = tempPool; dpiHandlePool__release(tempPool->env->errorHandles, &error.handle); return dpiGen__endPublicFn(context, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_getBusyCount() [PUBLIC] // Return the pool's busy count. //----------------------------------------------------------------------------- int dpiPool_getBusyCount(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_BUSY_COUNT, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getEncodingInfo() [PUBLIC] // Get the encoding information from the pool. //----------------------------------------------------------------------------- int dpiPool_getEncodingInfo(dpiPool *pool, dpiEncodingInfo *info) { dpiError error; int status; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(pool, info) status = dpiEnv__getEncodingInfo(pool->env, info); return dpiGen__endPublicFn(pool, status, &error); } //----------------------------------------------------------------------------- // dpiPool_getGetMode() [PUBLIC] // Return the pool's "get" mode. //----------------------------------------------------------------------------- int dpiPool_getGetMode(dpiPool *pool, dpiPoolGetMode *value) { dpiError error; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(pool, value) if (dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, value, NULL, DPI_OCI_ATTR_SPOOL_GETMODE, "get attribute value", &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_getMaxLifetimeSession() [PUBLIC] // Return the pool's maximum lifetime session. //----------------------------------------------------------------------------- int dpiPool_getMaxLifetimeSession(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getMaxSessionsPerShard() [PUBLIC] // Return the pool's maximum sessions per shard. //----------------------------------------------------------------------------- int dpiPool_getMaxSessionsPerShard(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getOpenCount() [PUBLIC] // Return the pool's open count. //----------------------------------------------------------------------------- int dpiPool_getOpenCount(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_OPEN_COUNT, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getSodaMetadataCache() [PUBLIC] // Return whether the SODA metadata cache is enabled or not. //----------------------------------------------------------------------------- int dpiPool_getSodaMetadataCache(dpiPool *pool, int *enabled) { dpiError error; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(pool, enabled) if (dpiUtils__checkClientVersionMulti(pool->env->versionInfo, 19, 11, 21, 3, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiOci__attrGet(pool->env->handle, DPI_OCI_HTYPE_ENV, enabled, NULL, DPI_OCI_ATTR_SODA_METADATA_CACHE, "get SODA metadata cache", &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_getStmtCacheSize() [PUBLIC] // Return the pool's default statement cache size. //----------------------------------------------------------------------------- int dpiPool_getStmtCacheSize(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getTimeout() [PUBLIC] // Return the pool's timeout value. //----------------------------------------------------------------------------- int dpiPool_getTimeout(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_TIMEOUT, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getWaitTimeout() [PUBLIC] // Return the pool's wait timeout value. //----------------------------------------------------------------------------- int dpiPool_getWaitTimeout(dpiPool *pool, uint32_t *value) { return dpiPool__getAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_getPingInterval() [PUBLIC] // Return the pool's ping-interval value. //----------------------------------------------------------------------------- int dpiPool_getPingInterval(dpiPool *pool, int *value) { dpiError error; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(pool, value); *value = pool->pingInterval; return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_release() [PUBLIC] // Release a reference to the pool. //----------------------------------------------------------------------------- int dpiPool_release(dpiPool *pool) { return dpiGen__release(pool, DPI_HTYPE_POOL, __func__); } //----------------------------------------------------------------------------- // dpiPool_reconfigure() [PUBLIC] // Reconfigure the pool - OCI only allows poolMin, poolMax, poolIncr // properties //----------------------------------------------------------------------------- int dpiPool_reconfigure(dpiPool *pool, uint32_t minSessions, uint32_t maxSessions, uint32_t sessionIncrement) { dpiError error; uint32_t mode = DPI_OCI_SPC_REINITIALIZE; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiOci__sessionPoolCreate(pool, NULL, 0, minSessions, maxSessions, sessionIncrement, NULL, 0, NULL, 0, mode, &error) < 0) return DPI_FAILURE; return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_setGetMode() [PUBLIC] // Set the pool's "get" mode. //----------------------------------------------------------------------------- int dpiPool_setGetMode(dpiPool *pool, dpiPoolGetMode value) { return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_GETMODE, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_setAccessToken() [PUBLIC] // Sets the token and private key for token based authentication //----------------------------------------------------------------------------- int dpiPool_setAccessToken(dpiPool *pool, dpiAccessToken *accessToken) { dpiError error; void * authInfo; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(pool, accessToken) if (dpiOci__attrGet(pool->handle, DPI_OCI_HTYPE_SPOOL, (void *)&authInfo, NULL, DPI_OCI_ATTR_SPOOL_AUTH, "get attribute value", &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiUtils__setAccessTokenAttributes(authInfo, accessToken, pool->env->versionInfo, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_setMaxLifetimeSession() [PUBLIC] // Set the pool's maximum lifetime session. //----------------------------------------------------------------------------- int dpiPool_setMaxLifetimeSession(dpiPool *pool, uint32_t value) { return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_MAX_LIFETIME_SESSION, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_setMaxSessionsPerShard() [PUBLIC] // Set the pool's maximum sessions per shard. //----------------------------------------------------------------------------- int dpiPool_setMaxSessionsPerShard(dpiPool *pool, uint32_t value) { return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_MAX_PER_SHARD, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_setSodaMetadataCache() [PUBLIC] // Set whether the SODA metadata cache is enabled or not. //----------------------------------------------------------------------------- int dpiPool_setSodaMetadataCache(dpiPool *pool, int enabled) { dpiError error; if (dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiUtils__checkClientVersionMulti(pool->env->versionInfo, 19, 11, 21, 3, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); if (dpiOci__attrSet(pool->env->handle, DPI_OCI_HTYPE_ENV, &enabled, 0, DPI_OCI_ATTR_SODA_METADATA_CACHE, "set SODA metadata cache", &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiPool_setStmtCacheSize() [PUBLIC] // Set the pool's default statement cache size. //----------------------------------------------------------------------------- int dpiPool_setStmtCacheSize(dpiPool *pool, uint32_t value) { pool->stmtCacheSize = value; return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_STMTCACHESIZE, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_setTimeout() [PUBLIC] // Set the pool's timeout value. //----------------------------------------------------------------------------- int dpiPool_setTimeout(dpiPool *pool, uint32_t value) { return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_TIMEOUT, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_setWaitTimeout() [PUBLIC] // Set the pool's wait timeout value. //----------------------------------------------------------------------------- int dpiPool_setWaitTimeout(dpiPool *pool, uint32_t value) { return dpiPool__setAttributeUint(pool, DPI_OCI_ATTR_SPOOL_WAIT_TIMEOUT, value, __func__); } //----------------------------------------------------------------------------- // dpiPool_setPingInterval() [PUBLIC] // Set the pool-ping-interval value. //----------------------------------------------------------------------------- int dpiPool_setPingInterval(dpiPool *pool, int value) { dpiError error; if(dpiPool__checkConnected(pool, __func__, &error) < 0) return dpiGen__endPublicFn(pool, DPI_FAILURE, &error); pool->pingInterval = value; return dpiGen__endPublicFn(pool, DPI_SUCCESS, &error); } odpi-5.6.4/src/dpiQueue.c000066400000000000000000000562301510466437300152140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiQueue.c // Implementation of AQ queues. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static int dpiQueue__allocateBuffer(dpiQueue *queue, uint32_t numElements, dpiError *error); static int dpiQueue__deq(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props, dpiError *error); static void dpiQueue__freeBuffer(dpiQueue *queue, dpiError *error); static int dpiQueue__getPayloadTDO(dpiQueue *queue, void **tdo, dpiError *error); //----------------------------------------------------------------------------- // dpiQueue__allocate() [INTERNAL] // Allocate and initialize a queue. //----------------------------------------------------------------------------- int dpiQueue__allocate(dpiConn *conn, const char *name, uint32_t nameLength, dpiObjectType *payloadType, dpiQueue **queue, int isJson, dpiError *error) { dpiQueue *tempQueue; char *buffer; // allocate handle; store reference to the connection that created it if (dpiGen__allocate(DPI_HTYPE_QUEUE, conn->env, (void**) &tempQueue, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempQueue->conn = conn; tempQueue->isJson = isJson; // store payload type, which is either an object type or NULL (meaning that // RAW or JSON payloads are being enqueued and dequeued) if (payloadType) { dpiGen__setRefCount(payloadType, error, 1); tempQueue->payloadType = payloadType; } // allocate space for the name of the queue; OCI requires a NULL-terminated // string so allocate enough space to store the NULL terminator; UTF-16 // encoded strings are not currently supported if (dpiUtils__allocateMemory(1, nameLength + 1, 0, "queue name", (void**) &buffer, error) < 0) { dpiQueue__free(tempQueue, error); return DPI_FAILURE; } memcpy(buffer, name, nameLength); buffer[nameLength] = '\0'; tempQueue->name = buffer; *queue = tempQueue; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__allocateBuffer() [INTERNAL] // Ensure there is enough space in the buffer for the specified number of // elements. //----------------------------------------------------------------------------- static int dpiQueue__allocateBuffer(dpiQueue *queue, uint32_t numElements, dpiError *error) { dpiQueue__freeBuffer(queue, error); queue->buffer.numElements = numElements; if (dpiUtils__allocateMemory(numElements, sizeof(dpiMsgProps*), 1, "allocate msg props array", (void**) &queue->buffer.props, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, "allocate OCI handles array", (void**) &queue->buffer.handles, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, "allocate OCI instances array", (void**) &queue->buffer.instances, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, "allocate OCI indicators array", (void**) &queue->buffer.indicators, error) < 0) return DPI_FAILURE; if (!queue->payloadType) { if (dpiUtils__allocateMemory(numElements, sizeof(int16_t), 1, "allocate array of OCI scalar indicator buffers", (void**) &queue->buffer.scalarIndicators, error) < 0) return DPI_FAILURE; } if (dpiUtils__allocateMemory(numElements, sizeof(void*), 1, "allocate message ids array", (void**) &queue->buffer.msgIds, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__check() [INTERNAL] // Determine if the queue is available to use. //----------------------------------------------------------------------------- static int dpiQueue__check(dpiQueue *queue, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, fnName, error) < 0) return DPI_FAILURE; if (!queue->conn->handle || queue->conn->closing) return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__createDeqOptions() [INTERNAL] // Create the dequeue options object that will be used for performing // dequeues against the queue. //----------------------------------------------------------------------------- static int dpiQueue__createDeqOptions(dpiQueue *queue, dpiError *error) { dpiDeqOptions *tempOptions; if (dpiGen__allocate(DPI_HTYPE_DEQ_OPTIONS, queue->env, (void**) &tempOptions, error) < 0) return DPI_FAILURE; if (dpiDeqOptions__create(tempOptions, queue->conn, error) < 0) { dpiDeqOptions__free(tempOptions, error); return DPI_FAILURE; } queue->deqOptions = tempOptions; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__createEnqOptions() [INTERNAL] // Create the dequeue options object that will be used for performing // dequeues against the queue. //----------------------------------------------------------------------------- static int dpiQueue__createEnqOptions(dpiQueue *queue, dpiError *error) { dpiEnqOptions *tempOptions; if (dpiGen__allocate(DPI_HTYPE_ENQ_OPTIONS, queue->env, (void**) &tempOptions, error) < 0) return DPI_FAILURE; if (dpiEnqOptions__create(tempOptions, queue->conn, error) < 0) { dpiEnqOptions__free(tempOptions, error); return DPI_FAILURE; } queue->enqOptions = tempOptions; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__deq() [INTERNAL] // Perform a dequeue of up to the specified number of properties. //----------------------------------------------------------------------------- static int dpiQueue__deq(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props, dpiError *error) { dpiMsgProps *prop; void *payloadTDO; uint32_t i; int status; // create dequeue options, if necessary if (!queue->deqOptions && dpiQueue__createDeqOptions(queue, error) < 0) return DPI_FAILURE; // allocate buffer, if necessary if (queue->buffer.numElements < *numProps && dpiQueue__allocateBuffer(queue, *numProps, error) < 0) return DPI_FAILURE; // populate buffer for (i = 0; i < *numProps; i++) { prop = queue->buffer.props[i]; // create new message properties, if applicable if (!prop) { if (dpiMsgProps__allocate(queue->conn, &prop, error) < 0) return DPI_FAILURE; queue->buffer.props[i] = prop; } // create payload object, if applicable if (queue->payloadType && !prop->payloadObj && dpiObject__allocate(queue->payloadType, NULL, NULL, NULL, &prop->payloadObj, error) < 0) return DPI_FAILURE; // create JSON payload object, if applicable if (queue->isJson) { if (dpiJson__allocate(queue->conn, NULL, &prop->payloadJson, error) < 0) return DPI_FAILURE; } // set OCI arrays queue->buffer.handles[i] = prop->handle; if (queue->payloadType) { queue->buffer.instances[i] = prop->payloadObj->instance; queue->buffer.indicators[i] = prop->payloadObj->indicator; } else if (queue->isJson) { queue->buffer.instances[i] = prop->payloadJson->handle; queue->buffer.indicators[i] = &queue->buffer.scalarIndicators[i]; } else { queue->buffer.instances[i] = prop->payloadRaw; queue->buffer.indicators[i] = &queue->buffer.scalarIndicators[i]; } queue->buffer.msgIds[i] = prop->msgIdRaw; } // perform dequeue if (dpiQueue__getPayloadTDO(queue, &payloadTDO, error) < 0) return DPI_FAILURE; if (*numProps == 1) { status = dpiOci__aqDeq(queue->conn, queue->name, queue->deqOptions->handle, queue->buffer.handles[0], payloadTDO, queue->buffer.instances, queue->buffer.indicators, queue->buffer.msgIds, error); if (status < 0) *numProps = 0; } else if (queue->isJson) { status = DPI_SUCCESS; for (i = 0; i < *numProps; i++) { status = dpiOci__aqDeq(queue->conn, queue->name, queue->deqOptions->handle, queue->buffer.handles[i], payloadTDO, &queue->buffer.instances[i], &queue->buffer.indicators[i], &queue->buffer.msgIds[i], error); if (status < 0) { *numProps = i; break; } } } else { status = dpiOci__aqDeqArray(queue->conn, queue->name, queue->deqOptions->handle, numProps, queue->buffer.handles, payloadTDO, queue->buffer.instances, queue->buffer.indicators, queue->buffer.msgIds, error); } if (status < 0 && error->buffer->code != 25228) { error->buffer->offset = *numProps; return DPI_FAILURE; } // transfer message properties to destination array for (i = 0; i < *numProps; i++) { props[i] = queue->buffer.props[i]; queue->buffer.props[i] = NULL; if (queue->isJson) { props[i]->payloadJson->handle = queue->buffer.instances[i]; } else if (!queue->payloadType) { props[i]->payloadRaw = queue->buffer.instances[i]; } props[i]->msgIdRaw = queue->buffer.msgIds[i]; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__enq() [INTERNAL] // Perform an enqueue of the specified properties. //----------------------------------------------------------------------------- static int dpiQueue__enq(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props, dpiError *error) { void *payloadTDO; uint32_t i; // if no messages are being enqueued, nothing to do! if (numProps == 0) return DPI_SUCCESS; // create enqueue options, if necessary if (!queue->enqOptions && dpiQueue__createEnqOptions(queue, error) < 0) return DPI_FAILURE; // allocate buffer, if necessary if (queue->buffer.numElements < numProps && dpiQueue__allocateBuffer(queue, numProps, error) < 0) return DPI_FAILURE; // populate buffer for (i = 0; i < numProps; i++) { // perform checks if (!props[i]->payloadObj && !props[i]->payloadRaw && !props[i]->payloadJson) return dpiError__set(error, "check payload", DPI_ERR_QUEUE_NO_PAYLOAD); if ((queue->isJson && !props[i]->payloadJson) || (queue->payloadType && !props[i]->payloadObj) || (!queue->isJson && !queue->payloadType && !props[i]->payloadRaw)) return dpiError__set(error, "check payload", DPI_ERR_QUEUE_WRONG_PAYLOAD_TYPE); if (queue->payloadType && props[i]->payloadObj && queue->payloadType->tdo != props[i]->payloadObj->type->tdo) return dpiError__set(error, "check payload", DPI_ERR_WRONG_TYPE, props[i]->payloadObj->type->schemaLength, props[i]->payloadObj->type->schema, props[i]->payloadObj->type->nameLength, props[i]->payloadObj->type->name, queue->payloadType->schemaLength, queue->payloadType->schema, queue->payloadType->nameLength, queue->payloadType->name); // set OCI arrays queue->buffer.handles[i] = props[i]->handle; if (queue->payloadType) { queue->buffer.instances[i] = props[i]->payloadObj->instance; queue->buffer.indicators[i] = props[i]->payloadObj->indicator; } else if (props[i]->payloadJson) { queue->buffer.instances[i] = props[i]->payloadJson->handle; queue->buffer.indicators[i] = &queue->buffer.scalarIndicators[i]; } else { queue->buffer.instances[i] = props[i]->payloadRaw; queue->buffer.indicators[i] = &queue->buffer.scalarIndicators[i]; } queue->buffer.msgIds[i] = props[i]->msgIdRaw; } // perform enqueue if (dpiQueue__getPayloadTDO(queue, &payloadTDO, error) < 0) return DPI_FAILURE; if (numProps == 1) { if (dpiOci__aqEnq(queue->conn, queue->name, queue->enqOptions->handle, queue->buffer.handles[0], payloadTDO, queue->buffer.instances, queue->buffer.indicators, queue->buffer.msgIds, error) < 0) return DPI_FAILURE; } else { if (dpiOci__aqEnqArray(queue->conn, queue->name, queue->enqOptions->handle, &numProps, queue->buffer.handles, payloadTDO, queue->buffer.instances, queue->buffer.indicators, queue->buffer.msgIds, error) < 0) { error->buffer->offset = numProps; return DPI_FAILURE; } } // transfer message ids back to message properties for (i = 0; i < numProps; i++) props[i]->msgIdRaw = queue->buffer.msgIds[i]; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue__free() [INTERNAL] // Free the memory for a queue. //----------------------------------------------------------------------------- void dpiQueue__free(dpiQueue *queue, dpiError *error) { if (queue->conn) { dpiGen__setRefCount(queue->conn, error, -1); queue->conn = NULL; } if (queue->payloadType) { dpiGen__setRefCount(queue->payloadType, error, -1); queue->payloadType = NULL; } if (queue->name) { dpiUtils__freeMemory((void*) queue->name); queue->name = NULL; } if (queue->deqOptions) { dpiGen__setRefCount(queue->deqOptions, error, -1); queue->deqOptions = NULL; } if (queue->enqOptions) { dpiGen__setRefCount(queue->enqOptions, error, -1); queue->enqOptions = NULL; } dpiQueue__freeBuffer(queue, error); dpiUtils__freeMemory(queue); } //----------------------------------------------------------------------------- // dpiQueue__freeBuffer() [INTERNAL] // Free the memory areas in the queue buffer. //----------------------------------------------------------------------------- static void dpiQueue__freeBuffer(dpiQueue *queue, dpiError *error) { dpiQueueBuffer *buffer = &queue->buffer; uint32_t i; if (buffer->props) { for (i = 0; i < buffer->numElements; i++) { if (buffer->props[i]) { dpiGen__setRefCount(buffer->props[i], error, -1); buffer->props[i] = NULL; } } dpiUtils__freeMemory(buffer->props); buffer->props = NULL; } if (buffer->handles) { dpiUtils__freeMemory(buffer->handles); buffer->handles = NULL; } if (buffer->instances) { dpiUtils__freeMemory(buffer->instances); buffer->instances = NULL; } if (buffer->indicators) { dpiUtils__freeMemory(buffer->indicators); buffer->indicators = NULL; } if (buffer->scalarIndicators) { dpiUtils__freeMemory(buffer->scalarIndicators); buffer->indicators = NULL; } if (buffer->msgIds) { dpiUtils__freeMemory(buffer->msgIds); buffer->msgIds = NULL; } } //----------------------------------------------------------------------------- // dpiQueue__getPayloadTDO() [INTERNAL] // Acquire the TDO to use for the payload. This will either be the TDO of the // object type (if one was specified when the queue was created), the RAW TDO // cached on the connection (for RAW queues) or the JSON TDO cached on the // connection (for JSON queues). //----------------------------------------------------------------------------- static int dpiQueue__getPayloadTDO(dpiQueue *queue, void **tdo, dpiError *error) { if (queue->payloadType) { *tdo = queue->payloadType->tdo; } else if (queue->isJson) { if (dpiConn__getJsonTDO(queue->conn, error) < 0) return DPI_FAILURE; *tdo = queue->conn->jsonTDO; } else { if (dpiConn__getRawTDO(queue->conn, error) < 0) return DPI_FAILURE; *tdo = queue->conn->rawTDO; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiQueue_addRef() [PUBLIC] // Add a reference to the queue. //----------------------------------------------------------------------------- int dpiQueue_addRef(dpiQueue *queue) { return dpiGen__addRef(queue, DPI_HTYPE_QUEUE, __func__); } //----------------------------------------------------------------------------- // dpiQueue_deqMany() [PUBLIC] // Dequeue multiple messages from the queue. //----------------------------------------------------------------------------- int dpiQueue_deqMany(dpiQueue *queue, uint32_t *numProps, dpiMsgProps **props) { dpiError error; int status; if (dpiQueue__check(queue, __func__, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(queue, numProps) DPI_CHECK_PTR_NOT_NULL(queue, props) status = dpiQueue__deq(queue, numProps, props, &error); return dpiGen__endPublicFn(queue, status, &error); } //----------------------------------------------------------------------------- // dpiQueue_deqOne() [PUBLIC] // Dequeue a single message from the queue. //----------------------------------------------------------------------------- int dpiQueue_deqOne(dpiQueue *queue, dpiMsgProps **props) { uint32_t numProps = 1; dpiError error; if (dpiQueue__check(queue, __func__, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(queue, props) if (dpiQueue__deq(queue, &numProps, props, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); if (numProps == 0) *props = NULL; return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiQueue_enqMany() [PUBLIC] // Enqueue multiple message to the queue. //----------------------------------------------------------------------------- int dpiQueue_enqMany(dpiQueue *queue, uint32_t numProps, dpiMsgProps **props) { dpiError error; uint32_t i; int status; // validate parameters if (dpiQueue__check(queue, __func__, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(queue, props) for (i = 0; i < numProps; i++) { if (dpiGen__checkHandle(props[i], DPI_HTYPE_MSG_PROPS, "check message properties", &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); } status = dpiQueue__enq(queue, numProps, props, &error); return dpiGen__endPublicFn(queue, status, &error); } //----------------------------------------------------------------------------- // dpiQueue_enqOne() [PUBLIC] // Enqueue a single message to the queue. //----------------------------------------------------------------------------- int dpiQueue_enqOne(dpiQueue *queue, dpiMsgProps *props) { dpiError error; int status; if (dpiQueue__check(queue, __func__, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); if (dpiGen__checkHandle(props, DPI_HTYPE_MSG_PROPS, "check message properties", &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); status = dpiQueue__enq(queue, 1, &props, &error); return dpiGen__endPublicFn(queue, status, &error); } //----------------------------------------------------------------------------- // dpiQueue_getDeqOptions() [PUBLIC] // Return the dequeue options associated with the queue. If no dequeue // options are currently associated with the queue, create them first. //----------------------------------------------------------------------------- int dpiQueue_getDeqOptions(dpiQueue *queue, dpiDeqOptions **options) { dpiError error; if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(queue, options) if (!queue->deqOptions && dpiQueue__createDeqOptions(queue, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); *options = queue->deqOptions; return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiQueue_getEnqOptions() [PUBLIC] // Return the enqueue options associated with the queue. If no enqueue // options are currently associated with the queue, create them first. //----------------------------------------------------------------------------- int dpiQueue_getEnqOptions(dpiQueue *queue, dpiEnqOptions **options) { dpiError error; if (dpiGen__startPublicFn(queue, DPI_HTYPE_QUEUE, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(queue, options) if (!queue->enqOptions && dpiQueue__createEnqOptions(queue, &error) < 0) return dpiGen__endPublicFn(queue, DPI_FAILURE, &error); *options = queue->enqOptions; return dpiGen__endPublicFn(queue, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiQueue_release() [PUBLIC] // Release a reference to the queue. //----------------------------------------------------------------------------- int dpiQueue_release(dpiQueue *queue) { return dpiGen__release(queue, DPI_HTYPE_QUEUE, __func__); } odpi-5.6.4/src/dpiRowid.c000066400000000000000000000131201510466437300152030ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiRowid.c // Implementation of rowids. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiRowid__allocate() [INTERNAL] // Allocate and initialize a rowid object. //----------------------------------------------------------------------------- int dpiRowid__allocate(dpiConn *conn, dpiRowid **rowid, dpiError *error) { dpiRowid *tempRowid; if (dpiGen__allocate(DPI_HTYPE_ROWID, conn->env, (void**) &tempRowid, error) < 0) return DPI_FAILURE; if (dpiOci__descriptorAlloc(conn->env->handle, &tempRowid->handle, DPI_OCI_DTYPE_ROWID, "allocate descriptor", error) < 0) { dpiRowid__free(tempRowid, error); return DPI_FAILURE; } *rowid = tempRowid; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiRowid__free() [INTERNAL] // Free the memory for a rowid. //----------------------------------------------------------------------------- void dpiRowid__free(dpiRowid *rowid, UNUSED dpiError *error) { if (rowid->handle) { dpiOci__descriptorFree(rowid->handle, DPI_OCI_DTYPE_ROWID); rowid->handle = NULL; } if (rowid->buffer) { dpiUtils__freeMemory(rowid->buffer); rowid->buffer = NULL; } dpiUtils__freeMemory(rowid); } //----------------------------------------------------------------------------- // dpiRowid_addRef() [PUBLIC] // Add a reference to the rowid. //----------------------------------------------------------------------------- int dpiRowid_addRef(dpiRowid *rowid) { return dpiGen__addRef(rowid, DPI_HTYPE_ROWID, __func__); } //----------------------------------------------------------------------------- // dpiRowid_getStringValue() [PUBLIC] // Get the string representation of the rowid. //----------------------------------------------------------------------------- int dpiRowid_getStringValue(dpiRowid *rowid, const char **value, uint32_t *valueLength) { char temp, *adjustedBuffer, *sourcePtr; uint16_t *targetPtr; dpiError error; uint16_t i; if (dpiGen__startPublicFn(rowid, DPI_HTYPE_ROWID, __func__, &error) < 0) return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(rowid, value) DPI_CHECK_PTR_NOT_NULL(rowid, valueLength) if (!rowid->buffer) { // determine length of rowid rowid->bufferLength = 0; dpiOci__rowidToChar(rowid, &temp, &rowid->bufferLength, &error); // allocate and populate buffer containing string representation if (dpiUtils__allocateMemory(1, rowid->bufferLength, 0, "allocate rowid buffer", (void**) &rowid->buffer, &error) < 0) return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); if (dpiOci__rowidToChar(rowid, rowid->buffer, &rowid->bufferLength, &error) < 0) return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); // UTF-16 is not handled properly (data is returned as ASCII instead) // adjust the buffer to use the correct encoding if (rowid->env->charsetId == DPI_CHARSET_ID_UTF16) { if (dpiUtils__allocateMemory(2, rowid->bufferLength, 0, "allocate rowid buffer", (void**) &adjustedBuffer, &error) < 0) { dpiUtils__freeMemory(rowid->buffer); rowid->bufferLength = 0; rowid->buffer = NULL; return dpiGen__endPublicFn(rowid, DPI_FAILURE, &error); } sourcePtr = rowid->buffer; targetPtr = (uint16_t*) adjustedBuffer; for (i = 0; i < rowid->bufferLength; i++) *targetPtr++ = (uint16_t) *sourcePtr++; dpiUtils__freeMemory(rowid->buffer); rowid->buffer = adjustedBuffer; rowid->bufferLength *= 2; } } *value = rowid->buffer; *valueLength = rowid->bufferLength; return dpiGen__endPublicFn(rowid, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiRowid_release() [PUBLIC] // Release a reference to the rowid. //----------------------------------------------------------------------------- int dpiRowid_release(dpiRowid *rowid) { return dpiGen__release(rowid, DPI_HTYPE_ROWID, __func__); } odpi-5.6.4/src/dpiSodaColl.c000066400000000000000000001225071510466437300156310ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiSodaColl.c // Implementation of SODA collections. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static int dpiSodaColl__populateOperOptions(dpiSodaColl *coll, const dpiSodaOperOptions *options, void *handle, dpiError *error); //----------------------------------------------------------------------------- // dpiSodaColl__allocate() [INTERNAL] // Allocate and initialize a SODA collection structure. //----------------------------------------------------------------------------- int dpiSodaColl__allocate(dpiSodaDb *db, void *handle, dpiSodaColl **coll, dpiError *error) { uint8_t sqlType, contentType; dpiSodaColl *tempColl; if (dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_COLLECTION, (void*) &sqlType, 0, DPI_OCI_ATTR_SODA_CTNT_SQL_TYPE, "get content sql type", error) < 0) return DPI_FAILURE; if (dpiGen__allocate(DPI_HTYPE_SODA_COLL, db->env, (void**) &tempColl, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(db, error, 1); tempColl->db = db; tempColl->handle = handle; if (sqlType == DPI_SQLT_BLOB) { tempColl->binaryContent = 1; contentType = 0; dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_COLLECTION, (void*) &contentType, 0, DPI_OCI_ATTR_SODA_CTNT_FORMAT, NULL, error); if (contentType == DPI_OCI_JSON_FORMAT_OSON) tempColl->binaryContent = 0; } *coll = tempColl; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaColl__check() [INTERNAL] // Determine if the SODA collection is available to use. //----------------------------------------------------------------------------- static int dpiSodaColl__check(dpiSodaColl *coll, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(coll, DPI_HTYPE_SODA_COLL, fnName, error) < 0) return DPI_FAILURE; if (!coll->db->conn->handle || coll->db->conn->closing) return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaColl__createOperOptions() [INTERNAL] // Create a SODA operation options handle with the specified information. //----------------------------------------------------------------------------- static int dpiSodaColl__createOperOptions(dpiSodaColl *coll, const dpiSodaOperOptions *options, void **handle, dpiError *error) { dpiSodaOperOptions localOptions; // if no options specified, use default values if (!options) { dpiContext__initSodaOperOptions(&localOptions); options = &localOptions; } // allocate new handle if (dpiOci__handleAlloc(coll->env->handle, handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, "allocate SODA operation options handle", error) < 0) return DPI_FAILURE; // populate handle attributes if (dpiSodaColl__populateOperOptions(coll, options, *handle, error) < 0) { dpiOci__handleFree(*handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaColl__find() [INTERNAL] // Perform a find of SODA documents by creating an operation options handle // and populating it with the requested options. Once the find is complete, // return either a cursor or a document. //----------------------------------------------------------------------------- static int dpiSodaColl__find(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, dpiSodaDocCursor **cursor, dpiSodaDoc **doc, dpiError *error) { uint32_t ociMode, returnHandleType, ociFlags; void *optionsHandle, *ociReturnHandle; int status; // determine OCI mode to pass ociMode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) ociMode |= DPI_OCI_SODA_ATOMIC_COMMIT; // create new OCI operation options handle if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, error) < 0) return DPI_FAILURE; // determine OCI flags to use if (coll->binaryContent || coll->env->context->sodaUseJsonDesc) { ociFlags = DPI_OCI_SODA_AS_STORED; } else { ociFlags = DPI_OCI_SODA_AS_AL32UTF8; } // perform actual find if (cursor) { *cursor = NULL; status = dpiOci__sodaFind(coll, optionsHandle, ociFlags, ociMode, &ociReturnHandle, error); } else { *doc = NULL; status = dpiOci__sodaFindOne(coll, optionsHandle, ociFlags, ociMode, &ociReturnHandle, error); } dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); if (status < 0) return DPI_FAILURE; // return cursor or document, as appropriate if (cursor) { status = dpiSodaDocCursor__allocate(coll, ociReturnHandle, cursor, error); returnHandleType = DPI_OCI_HTYPE_SODA_DOC_CURSOR; } else if (ociReturnHandle) { status = dpiSodaDoc__allocate(coll->db, ociReturnHandle, doc, error); returnHandleType = DPI_OCI_HTYPE_SODA_DOCUMENT; } if (status < 0) dpiOci__handleFree(ociReturnHandle, returnHandleType); return status; } //----------------------------------------------------------------------------- // dpiSodaColl__free() [INTERNAL] // Free the memory for a SODA collection. Note that the reference to the // database must remain until after the handle is freed; otherwise, a segfault // can take place. //----------------------------------------------------------------------------- void dpiSodaColl__free(dpiSodaColl *coll, dpiError *error) { if (coll->handle) { dpiOci__handleFree(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION); coll->handle = NULL; } if (coll->db) { dpiGen__setRefCount(coll->db, error, -1); coll->db = NULL; } dpiUtils__freeMemory(coll); } //----------------------------------------------------------------------------- // dpiSodaColl__getDocCount() [INTERNAL] // Internal method for getting document count. //----------------------------------------------------------------------------- static int dpiSodaColl__getDocCount(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count, dpiError *error) { void *optionsHandle; uint32_t ociMode; int status; // determine OCI mode to pass ociMode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) ociMode |= DPI_OCI_SODA_ATOMIC_COMMIT; // create new OCI operation options handle if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, error) < 0) return DPI_FAILURE; // perform actual document count status = dpiOci__sodaDocCount(coll, optionsHandle, ociMode, count, error); dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); return status; } //----------------------------------------------------------------------------- // dpiSodaColl__insertMany() [INTERNAL] // Insert multiple documents into the collection and return handles to the // newly created documents, if desired. //----------------------------------------------------------------------------- static int dpiSodaColl__insertMany(dpiSodaColl *coll, uint32_t numDocs, void **docHandles, uint32_t flags, dpiSodaDoc **insertedDocs, void *operOptionsHandle, dpiError *error) { void *outputOptionsHandle; uint32_t i, j, mode; uint64_t docCount; int status; // create OCI output options handle if (dpiOci__handleAlloc(coll->env->handle, &outputOptionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS, "allocate SODA output options handle", error) < 0) return DPI_FAILURE; // determine mode to pass mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // perform actual bulk insert if (operOptionsHandle) { status = dpiOci__sodaBulkInsertAndGetWithOpts(coll, docHandles, numDocs, operOptionsHandle, outputOptionsHandle, mode, error); dpiOci__handleFree(operOptionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); } else if (insertedDocs) { status = dpiOci__sodaBulkInsertAndGet(coll, docHandles, numDocs, outputOptionsHandle, mode, error); } else { status = dpiOci__sodaBulkInsert(coll, docHandles, numDocs, outputOptionsHandle, mode, error); } // on failure, determine the number of documents that were successfully // inserted and store that information in the error buffer if (status < 0) { dpiOci__attrGet(outputOptionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS, (void*) &docCount, 0, DPI_OCI_ATTR_SODA_DOC_COUNT, NULL, error); error->buffer->offset = (uint32_t) docCount; } dpiOci__handleFree(outputOptionsHandle, DPI_OCI_HTYPE_SODA_OUTPUT_OPTIONS); // on failure, if using the "AndGet" variant, any document handles that // were created need to be freed if (insertedDocs && status < 0) { for (i = 0; i < numDocs; i++) { if (docHandles[i]) { dpiOci__handleFree(docHandles[i], DPI_OCI_HTYPE_SODA_DOCUMENT); docHandles[i] = NULL; } } } if (status < 0) return DPI_FAILURE; // return document handles, if desired if (insertedDocs) { for (i = 0; i < numDocs; i++) { if (dpiSodaDoc__allocate(coll->db, docHandles[i], &insertedDocs[i], error) < 0) { for (j = 0; j < i; j++) { dpiSodaDoc__free(insertedDocs[j], error); insertedDocs[j] = NULL; } for (j = i; j < numDocs; j++) { dpiOci__handleFree(docHandles[i], DPI_OCI_HTYPE_SODA_DOCUMENT); } return DPI_FAILURE; } } } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaColl__listIndexes() [INTERNAL] // Return the list of indexes associated with the collection. //----------------------------------------------------------------------------- int dpiSodaColl__listIndexes(dpiSodaColl *coll, uint32_t flags, dpiStringList *list, dpiError *error) { uint32_t ptrLen, numAllocatedStrings = 0; void *listHandle = NULL; void **elem, *elemInd; int32_t i, listLen; int exists, status; char *ptr; if (dpiUtils__checkClientVersionMulti(coll->env->versionInfo, 19, 13, 21, 3, error) < 0) return DPI_FAILURE; if (dpiOci__sodaIndexList(coll, flags, &listHandle, error) < 0) return DPI_FAILURE; status = dpiOci__collSize(coll->db->conn, listHandle, &listLen, error); for (i = 0; i < listLen && status == DPI_SUCCESS; i++) { status = dpiOci__collGetElem(coll->db->conn, listHandle, i, &exists, (void**) &elem, &elemInd, error); if (status < 0) break; status = dpiOci__stringPtr(coll->env->handle, *elem, &ptr); if (status < 0) break; status = dpiOci__stringSize(coll->env->handle, *elem, &ptrLen); if (status < 0) break; status = dpiStringList__addElement(list, ptr, ptrLen, &numAllocatedStrings, error); } if (listHandle) dpiOci__objectFree(coll->env->handle, listHandle, 0, error); return status; } //----------------------------------------------------------------------------- // dpiSodaColl__populateOperOptions() [INTERNAL] // Populate the SODA operation options handle with the information found in // the supplied structure. //----------------------------------------------------------------------------- static int dpiSodaColl__populateOperOptions(dpiSodaColl *coll, const dpiSodaOperOptions *options, void *handle, dpiError *error) { // set multiple keys, if applicable if (options->numKeys > 0) { if (dpiOci__sodaOperKeysSet(options, handle, error) < 0) return DPI_FAILURE; } // set single key, if applicable if (options->keyLength > 0) { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) options->key, options->keyLength, DPI_OCI_ATTR_SODA_KEY, "set key", error) < 0) return DPI_FAILURE; } // set single version, if applicable if (options->versionLength > 0) { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) options->version, options->versionLength, DPI_OCI_ATTR_SODA_VERSION, "set version", error) < 0) return DPI_FAILURE; } // set filter, if applicable if (options->filterLength > 0) { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) options->filter, options->filterLength, DPI_OCI_ATTR_SODA_FILTER, "set filter", error) < 0) return DPI_FAILURE; } // set skip count, if applicable if (options->skip > 0) { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) &options->skip, 0, DPI_OCI_ATTR_SODA_SKIP, "set skip count", error) < 0) return DPI_FAILURE; } // set limit, if applicable if (options->limit > 0) { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) &options->limit, 0, DPI_OCI_ATTR_SODA_LIMIT, "set limit", error) < 0) return DPI_FAILURE; } // set fetch array size, if applicable (only available in 19.5+ client) if (options->fetchArraySize > 0) { if (dpiUtils__checkClientVersion(coll->env->versionInfo, 19, 5, error) < 0) return DPI_FAILURE; if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) &options->fetchArraySize, 0, DPI_OCI_ATTR_SODA_FETCH_ARRAY_SIZE, "set fetch array size", error) < 0) return DPI_FAILURE; } // set hint, if applicable (only available in 19.11+/21.3+ client) if (options->hintLength > 0) { if (dpiUtils__checkClientVersionMulti(coll->env->versionInfo, 19, 11, 21, 3, error) < 0) return DPI_FAILURE; if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) options->hint, options->hintLength, DPI_OCI_ATTR_SODA_HINT, "set hint", error) < 0) return DPI_FAILURE; } // set lock, if applicable (only available in 19.11+/21.3+ client) if (options->lock) { if (dpiUtils__checkClientVersionMulti(coll->env->versionInfo, 19, 11, 21, 3, error) < 0) return DPI_FAILURE; if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS, (void*) &options->lock, 0, DPI_OCI_ATTR_SODA_LOCK, "set lock", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaColl__remove() [INTERNAL] // Internal method for removing documents from a collection. //----------------------------------------------------------------------------- static int dpiSodaColl__remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count, dpiError *error) { void *optionsHandle; uint32_t mode; int status; // determine OCI mode to pass mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // create new OCI operation options handle if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, error) < 0) return DPI_FAILURE; // remove documents from collection status = dpiOci__sodaRemove(coll, optionsHandle, mode, count, error); dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); return status; } //----------------------------------------------------------------------------- // dpiSodaColl__replace() [INTERNAL] // Internal method for replacing a document in the collection. //----------------------------------------------------------------------------- static int dpiSodaColl__replace(dpiSodaColl *coll, const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, int *replaced, dpiSodaDoc **replacedDoc, dpiError *error) { void *docHandle, *optionsHandle; int status, dummyIsReplaced; uint32_t mode; // use dummy value if the replaced flag is not desired if (!replaced) replaced = &dummyIsReplaced; // determine OCI mode to pass mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // create new OCI operation options handle if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, error) < 0) return DPI_FAILURE; // replace document in collection // use "AndGet" variant if the replaced document is requested docHandle = doc->handle; if (!replacedDoc) { status = dpiOci__sodaReplOne(coll, optionsHandle, docHandle, mode, replaced, error); } else { *replacedDoc = NULL; status = dpiOci__sodaReplOneAndGet(coll, optionsHandle, &docHandle, mode, replaced, error); if (status == 0 && docHandle) { status = dpiSodaDoc__allocate(coll->db, docHandle, replacedDoc, error); if (status < 0) dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); } } dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); return status; } //----------------------------------------------------------------------------- // dpiSodaColl__save() [INTERNAL] // Internal method for saving a document in the collection. //----------------------------------------------------------------------------- static int dpiSodaColl__save(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, dpiSodaDoc **savedDoc, void *optionsHandle, dpiError *error) { void *docHandle; uint32_t mode; int status; // determine OCI mode to pass mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // save document in collection // use "AndGet" variant if the saved document is requested docHandle = doc->handle; if (!savedDoc) { status = dpiOci__sodaSave(coll, docHandle, mode, error); } else { *savedDoc = NULL; if (optionsHandle) { status = dpiOci__sodaSaveAndGetWithOpts(coll, &docHandle, optionsHandle, mode, error); dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); } else { status = dpiOci__sodaSaveAndGet(coll, &docHandle, mode, error); } if (status == 0 && docHandle) { status = dpiSodaDoc__allocate(coll->db, docHandle, savedDoc, error); if (status < 0) dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); } } return status; } //----------------------------------------------------------------------------- // dpiSodaColl_addRef() [PUBLIC] // Add a reference to the SODA collection. //----------------------------------------------------------------------------- int dpiSodaColl_addRef(dpiSodaColl *coll) { return dpiGen__addRef(coll, DPI_HTYPE_SODA_COLL, __func__); } //----------------------------------------------------------------------------- // dpiSodaColl_createIndex() [PUBLIC] // Create an index on the collection. //----------------------------------------------------------------------------- int dpiSodaColl_createIndex(dpiSodaColl *coll, const char *indexSpec, uint32_t indexSpecLength, uint32_t flags) { dpiError error; uint32_t mode; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(coll, indexSpec) // determine mode to pass to OCI mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // create index status = dpiOci__sodaIndexCreate(coll, indexSpec, indexSpecLength, mode, &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_drop() [PUBLIC] // Drop the collection. //----------------------------------------------------------------------------- int dpiSodaColl_drop(dpiSodaColl *coll, uint32_t flags, int *isDropped) { int status, dummyIsDropped; dpiError error; uint32_t mode; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // isDropped is not a mandatory parameter, but it is for OCI if (!isDropped) isDropped = &dummyIsDropped; // determine mode to pass to OCI mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // drop collection status = dpiOci__sodaCollDrop(coll, isDropped, mode, &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_dropIndex() [PUBLIC] // Drop the index on the collection. //----------------------------------------------------------------------------- int dpiSodaColl_dropIndex(dpiSodaColl *coll, const char *name, uint32_t nameLength, uint32_t flags, int *isDropped) { int status, dummyIsDropped; dpiError error; uint32_t mode; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(coll, name) // isDropped is not a mandatory parameter, but it is for OCI if (!isDropped) isDropped = &dummyIsDropped; // determine mode to pass to OCI mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; if (flags & DPI_SODA_FLAGS_INDEX_DROP_FORCE) mode |= DPI_OCI_SODA_INDEX_DROP_FORCE; // drop index status = dpiOci__sodaIndexDrop(coll, name, nameLength, mode, isDropped, &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_find() [PUBLIC] // Find documents in a collection and return a cursor. //----------------------------------------------------------------------------- int dpiSodaColl_find(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, dpiSodaDocCursor **cursor) { dpiError error; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, cursor) // perform find and return a cursor if (dpiSodaColl__find(coll, options, flags, cursor, NULL, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_findOne() [PUBLIC] // Find a single document in a collection and return it. //----------------------------------------------------------------------------- int dpiSodaColl_findOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **doc) { dpiError error; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, doc) // perform find and return a document if (dpiSodaColl__find(coll, options, flags, NULL, doc, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_getDataGuide() [PUBLIC] // Return the data guide document for the collection. //----------------------------------------------------------------------------- int dpiSodaColl_getDataGuide(dpiSodaColl *coll, uint32_t flags, dpiSodaDoc **doc) { void *docHandle; dpiError error; uint32_t mode; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, doc) // determine mode to pass mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // get data guide if (dpiOci__sodaDataGuideGet(coll, &docHandle, mode, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (!docHandle) { *doc = NULL; } else if (dpiSodaDoc__allocate(coll->db, docHandle, doc, &error) < 0) { dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_getDocCount() [PUBLIC] // Return the number of documents in the collection that match the specified // criteria. //----------------------------------------------------------------------------- int dpiSodaColl_getDocCount(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count) { dpiError error; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, count) // get document count if (dpiSodaColl__getDocCount(coll, options, flags, count, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_getMetadata() [PUBLIC] // Return the metadata for the collection. //----------------------------------------------------------------------------- int dpiSodaColl_getMetadata(dpiSodaColl *coll, const char **value, uint32_t *valueLength) { dpiError error; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, value) DPI_CHECK_PTR_NOT_NULL(coll, valueLength) // get attribute value status = dpiOci__attrGet(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION, (void*) value, valueLength, DPI_OCI_ATTR_SODA_COLL_DESCRIPTOR, "get value", &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_getName() [PUBLIC] // Return the name of the collection. //----------------------------------------------------------------------------- int dpiSodaColl_getName(dpiSodaColl *coll, const char **value, uint32_t *valueLength) { dpiError error; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, value) DPI_CHECK_PTR_NOT_NULL(coll, valueLength) // get attribute value status = dpiOci__attrGet(coll->handle, DPI_OCI_HTYPE_SODA_COLLECTION, (void*) value, valueLength, DPI_OCI_ATTR_SODA_COLL_NAME, "get value", &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_insertMany() [PUBLIC] // Similar to dpiSodaColl_insertManyWithOptions() but passing NULL options. //----------------------------------------------------------------------------- int dpiSodaColl_insertMany(dpiSodaColl *coll, uint32_t numDocs, dpiSodaDoc **docs, uint32_t flags, dpiSodaDoc **insertedDocs) { return dpiSodaColl_insertManyWithOptions(coll, numDocs, docs, NULL, flags, insertedDocs); } //----------------------------------------------------------------------------- // dpiSodaColl_insertManyWithOptions() [PUBLIC] // Insert multiple documents into the collection and return handles to the // newly created documents, if desired. //----------------------------------------------------------------------------- int dpiSodaColl_insertManyWithOptions(dpiSodaColl *coll, uint32_t numDocs, dpiSodaDoc **docs, dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **insertedDocs) { void **docHandles, *optionsHandle = NULL; dpiError error; uint32_t i; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, docs) if (numDocs == 0) { dpiError__set(&error, "check num documents", DPI_ERR_ARRAY_SIZE_ZERO); return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } for (i = 0; i < numDocs; i++) { if (dpiGen__checkHandle(docs[i], DPI_HTYPE_SODA_DOC, "check document", &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } // bulk insert is only supported with Oracle Client 18.5+ if (dpiUtils__checkClientVersion(coll->env->versionInfo, 18, 5, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // if options specified and the newly created document is to be returned, // create the operation options handle if (insertedDocs && options) { if (dpiUtils__checkClientVersionMulti(coll->env->versionInfo, 19, 11, 21, 3, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } // create and populate array to hold document handles if (dpiUtils__allocateMemory(numDocs, sizeof(void*), 1, "allocate document handles", (void**) &docHandles, &error) < 0) { if (optionsHandle) dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } for (i = 0; i < numDocs; i++) docHandles[i] = docs[i]->handle; // perform bulk insert status = dpiSodaColl__insertMany(coll, numDocs, docHandles, flags, insertedDocs, optionsHandle, &error); dpiUtils__freeMemory(docHandles); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_insertOne() [PUBLIC] // Similar to dpiSodaColl_insertOneWithOptions() but passing NULL options. //----------------------------------------------------------------------------- int dpiSodaColl_insertOne(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, dpiSodaDoc **insertedDoc) { return dpiSodaColl_insertOneWithOptions(coll, doc, NULL, flags, insertedDoc); } //----------------------------------------------------------------------------- // dpiSodaColl_insertOneWithOptions() [PUBLIC] // Insert a document into the collection and return a handle to the newly // created document, if desired. //----------------------------------------------------------------------------- int dpiSodaColl_insertOneWithOptions(dpiSodaColl *coll, dpiSodaDoc *doc, dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **insertedDoc) { void *docHandle, *optionsHandle = NULL; dpiError error; uint32_t mode; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // if options specified and the newly created document is to be returned, // create the operation options handle if (insertedDoc && options) { if (dpiUtils__checkClientVersionMulti(coll->env->versionInfo, 19, 11, 21, 3, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } // determine OCI mode to use mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // insert document into collection // use "AndGet" variants if the inserted document is requested docHandle = doc->handle; if (!insertedDoc) status = dpiOci__sodaInsert(coll, docHandle, mode, &error); else { if (options) { status = dpiOci__sodaInsertAndGetWithOpts(coll, &docHandle, optionsHandle, mode, &error); dpiOci__handleFree(optionsHandle, DPI_OCI_HTYPE_SODA_OPER_OPTIONS); } else { status = dpiOci__sodaInsertAndGet(coll, &docHandle, mode, &error); } if (status == 0) { status = dpiSodaDoc__allocate(coll->db, docHandle, insertedDoc, &error); if (status < 0) dpiOci__handleFree(docHandle, DPI_OCI_HTYPE_SODA_DOCUMENT); } } return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_listIndexes() [PUBLIC] // Return the list of indexes associated with the collection. //----------------------------------------------------------------------------- int dpiSodaColl_listIndexes(dpiSodaColl *coll, uint32_t flags, dpiStringList *list) { dpiError error; uint32_t mode; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, list) // get indexes memset(list, 0, sizeof(dpiStringList)); mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; status = dpiSodaColl__listIndexes(coll, mode, list, &error); if (status < 0) dpiStringList__free(list); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_release() [PUBLIC] // Release a reference to the SODA collection. //----------------------------------------------------------------------------- int dpiSodaColl_release(dpiSodaColl *coll) { return dpiGen__release(coll, DPI_HTYPE_SODA_COLL, __func__); } //----------------------------------------------------------------------------- // dpiSodaColl_remove() [PUBLIC] // Remove the documents from the collection that match the given criteria. //----------------------------------------------------------------------------- int dpiSodaColl_remove(dpiSodaColl *coll, const dpiSodaOperOptions *options, uint32_t flags, uint64_t *count) { dpiError error; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(coll, count) // perform removal if (dpiSodaColl__remove(coll, options, flags, count, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); return dpiGen__endPublicFn(coll, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_replaceOne() [PUBLIC] // Replace the first document in the collection that matches the given // criteria. Returns a handle to the newly replaced document, if desired. //----------------------------------------------------------------------------- int dpiSodaColl_replaceOne(dpiSodaColl *coll, const dpiSodaOperOptions *options, dpiSodaDoc *doc, uint32_t flags, int *replaced, dpiSodaDoc **replacedDoc) { dpiError error; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // perform replace status = dpiSodaColl__replace(coll, options, doc, flags, replaced, replacedDoc, &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_save() [PUBLIC] // Similar to dpiSodaColl_saveWithOptions() but passing NULL options. //----------------------------------------------------------------------------- int dpiSodaColl_save(dpiSodaColl *coll, dpiSodaDoc *doc, uint32_t flags, dpiSodaDoc **savedDoc) { return dpiSodaColl_saveWithOptions(coll, doc, NULL, flags, savedDoc); } //----------------------------------------------------------------------------- // dpiSodaColl_saveWithOptions() [PUBLIC] // Save the document into the collection. This method is equivalent to // dpiSodaColl_insertOne() except that if client-assigned keys are used, and // the document with the specified key already exists in the collection, it // will be replaced with the input document. Returns a handle to the new // document, if desired. //----------------------------------------------------------------------------- int dpiSodaColl_saveWithOptions(dpiSodaColl *coll, dpiSodaDoc *doc, dpiSodaOperOptions *options, uint32_t flags, dpiSodaDoc **savedDoc) { void *optionsHandle = NULL; dpiError error; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (dpiGen__checkHandle(doc, DPI_HTYPE_SODA_DOC, "check document", &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // save is only supported with Oracle Client 19.9+ if (dpiUtils__checkClientVersion(coll->env->versionInfo, 19, 9, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // if options specified and the newly created document is to be returned, // create the operation options handle if (savedDoc && options) { if (dpiUtils__checkClientVersionMulti(coll->env->versionInfo, 19, 11, 21, 3, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); if (dpiSodaColl__createOperOptions(coll, options, &optionsHandle, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); } // perform save status = dpiSodaColl__save(coll, doc, flags, savedDoc, optionsHandle, &error); return dpiGen__endPublicFn(coll, status, &error); } //----------------------------------------------------------------------------- // dpiSodaColl_truncate() [PUBLIC] // Remove all of the documents in the collection. //----------------------------------------------------------------------------- int dpiSodaColl_truncate(dpiSodaColl *coll) { dpiError error; int status; // validate parameters if (dpiSodaColl__check(coll, __func__, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // truncate is only supported with Oracle Client 20+ if (dpiUtils__checkClientVersion(coll->env->versionInfo, 20, 1, &error) < 0) return dpiGen__endPublicFn(coll, DPI_FAILURE, &error); // perform truncate status = dpiOci__sodaCollTruncate(coll, &error); return dpiGen__endPublicFn(coll, status, &error); } odpi-5.6.4/src/dpiSodaCollCursor.c000066400000000000000000000137631510466437300170320ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiSodaCollCursor.c // Implementation of SODA collection cursors. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiSodaCollCursor__allocate() [INTERNAL] // Allocate and initialize a SODA collection cursor structure. //----------------------------------------------------------------------------- int dpiSodaCollCursor__allocate(dpiSodaDb *db, void *handle, dpiSodaCollCursor **cursor, dpiError *error) { dpiSodaCollCursor *tempCursor; if (dpiGen__allocate(DPI_HTYPE_SODA_COLL_CURSOR, db->env, (void**) &tempCursor, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(db, error, 1); tempCursor->db = db; tempCursor->handle = handle; *cursor = tempCursor; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaCollCursor__check() [INTERNAL] // Determine if the SODA collection cursor is available to use. //----------------------------------------------------------------------------- static int dpiSodaCollCursor__check(dpiSodaCollCursor *cursor, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(cursor, DPI_HTYPE_SODA_COLL_CURSOR, fnName, error) < 0) return DPI_FAILURE; if (!cursor->handle) return dpiError__set(error, "check closed", DPI_ERR_SODA_CURSOR_CLOSED); if (!cursor->db->conn->handle || cursor->db->conn->closing) return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaCollCursor__free() [INTERNAL] // Free the memory for a SODA collection cursor. Note that the reference to // the database must remain until after the handle is freed; otherwise, a // segfault can take place. //----------------------------------------------------------------------------- void dpiSodaCollCursor__free(dpiSodaCollCursor *cursor, dpiError *error) { if (cursor->handle) { dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); cursor->handle = NULL; } if (cursor->db) { dpiGen__setRefCount(cursor->db, error, -1); cursor->db = NULL; } dpiUtils__freeMemory(cursor); } //----------------------------------------------------------------------------- // dpiSodaCollCursor_addRef() [PUBLIC] // Add a reference to the SODA collection cursor. //----------------------------------------------------------------------------- int dpiSodaCollCursor_addRef(dpiSodaCollCursor *cursor) { return dpiGen__addRef(cursor, DPI_HTYPE_SODA_COLL_CURSOR, __func__); } //----------------------------------------------------------------------------- // dpiSodaCollCursor_close() [PUBLIC] // Close the cursor. //----------------------------------------------------------------------------- int dpiSodaCollCursor_close(dpiSodaCollCursor *cursor) { dpiError error; if (dpiSodaCollCursor__check(cursor, __func__, &error) < 0) return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); if (cursor->handle) { dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); cursor->handle = NULL; } return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaCollCursor_getNext() [PUBLIC] // Return the next collection available from the cursor. //----------------------------------------------------------------------------- int dpiSodaCollCursor_getNext(dpiSodaCollCursor *cursor, UNUSED uint32_t flags, dpiSodaColl **coll) { dpiError error; void *handle; if (dpiSodaCollCursor__check(cursor, __func__, &error) < 0) return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(cursor, coll) if (dpiOci__sodaCollGetNext(cursor->db->conn, cursor->handle, &handle, &error) < 0) return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); *coll = NULL; if (handle) { if (dpiSodaColl__allocate(cursor->db, handle, coll, &error) < 0) { dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); } } return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaCollCursor_release() [PUBLIC] // Release a reference to the SODA collection cursor. //----------------------------------------------------------------------------- int dpiSodaCollCursor_release(dpiSodaCollCursor *cursor) { return dpiGen__release(cursor, DPI_HTYPE_SODA_COLL_CURSOR, __func__); } odpi-5.6.4/src/dpiSodaDb.c000066400000000000000000000406421510466437300152640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiSodaDb.c // Implementation of SODA database methods. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiSodaDb__checkConnected() [INTERNAL] // Check to see that the connection to the database is available for use. //----------------------------------------------------------------------------- static int dpiSodaDb__checkConnected(dpiSodaDb *db, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(db, DPI_HTYPE_SODA_DB, fnName, error) < 0) return DPI_FAILURE; if (!db->conn->handle || db->conn->closing) return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDb__createDocument() [INTERNAL] // Create a document and set the supplied values, if applicable. //----------------------------------------------------------------------------- static int dpiSodaDb__createDocument(dpiSodaDb *db, const char *key, uint32_t keyLength, const char *content, uint32_t contentLength, const char *mediaType, uint32_t mediaTypeLength, dpiSodaDoc **doc, dpiError *error) { dpiSodaDoc *tempDoc; int detectEncoding; // allocate SODA document structure if (dpiSodaDoc__allocate(db, NULL, &tempDoc, error) < 0) return DPI_FAILURE; // set key, if applicable if (key && keyLength > 0) { if (dpiOci__attrSet(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) key, keyLength, DPI_OCI_ATTR_SODA_KEY, "set key", error) < 0) { dpiSodaDoc__free(tempDoc, error); return DPI_FAILURE; } } // set binary or encoded text content, if applicable if (content && contentLength > 0) { tempDoc->binaryContent = 1; detectEncoding = 1; if (dpiOci__attrSet(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) &detectEncoding, 0, DPI_OCI_ATTR_SODA_DETECT_JSON_ENC, "set detect encoding", error) < 0) { dpiSodaDoc__free(tempDoc, error); return DPI_FAILURE; } if (dpiOci__attrSet(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) content, contentLength, DPI_OCI_ATTR_SODA_CONTENT, "set content", error) < 0) { dpiSodaDoc__free(tempDoc, error); return DPI_FAILURE; } } // set media type, if applicable if (mediaType && mediaTypeLength > 0) { if (dpiOci__attrSet(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) mediaType, mediaTypeLength, DPI_OCI_ATTR_SODA_MEDIA_TYPE, "set media type", error) < 0) { dpiSodaDoc__free(tempDoc, error); return DPI_FAILURE; } } *doc = tempDoc; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDb__getCollectionNames() [PUBLIC] // Internal method used for getting all collection names from the database. // The provided cursor handle is iterated until either the limit is reached // or there are no more collections to find. //----------------------------------------------------------------------------- static int dpiSodaDb__getCollectionNames(dpiSodaDb *db, void *cursorHandle, uint32_t limit, dpiStringList *names, dpiError *error) { uint32_t numAllocatedStrings = 0, nameLength; void *collectionHandle; char *name; while (names->numStrings < limit || limit == 0) { // get next collection from cursor if (dpiOci__sodaCollGetNext(db->conn, cursorHandle, &collectionHandle, error) < 0) return DPI_FAILURE; if (!collectionHandle) break; // get name from collection if (dpiOci__attrGet(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION, (void*) &name, &nameLength, DPI_OCI_ATTR_SODA_COLL_NAME, "get collection name", error) < 0) { dpiOci__handleFree(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION); return DPI_FAILURE; } // add element to list if (dpiStringList__addElement(names, name, nameLength, &numAllocatedStrings, error) < 0) { dpiOci__handleFree(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION); return DPI_FAILURE; } // free collection now that we have processed it successfully dpiOci__handleFree(collectionHandle, DPI_OCI_HTYPE_SODA_COLLECTION); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDb__free() [INTERNAL] // Free the memory for a SODA database. //----------------------------------------------------------------------------- void dpiSodaDb__free(dpiSodaDb *db, dpiError *error) { if (db->conn) { dpiGen__setRefCount(db->conn, error, -1); db->conn = NULL; } dpiUtils__freeMemory(db); } //----------------------------------------------------------------------------- // dpiSodaDb_addRef() [PUBLIC] // Add a reference to the SODA database. //----------------------------------------------------------------------------- int dpiSodaDb_addRef(dpiSodaDb *db) { return dpiGen__addRef(db, DPI_HTYPE_SODA_DB, __func__); } //----------------------------------------------------------------------------- // dpiSodaDb_createCollection() [PUBLIC] // Create a new SODA collection with the given name and metadata. //----------------------------------------------------------------------------- int dpiSodaDb_createCollection(dpiSodaDb *db, const char *name, uint32_t nameLength, const char *metadata, uint32_t metadataLength, uint32_t flags, dpiSodaColl **coll) { dpiError error; uint32_t mode; void *handle; // validate parameters if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(db, name) DPI_CHECK_PTR_AND_LENGTH(db, metadata) DPI_CHECK_PTR_NOT_NULL(db, coll) // determine OCI mode to use mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; if (flags & DPI_SODA_FLAGS_CREATE_COLL_MAP) mode |= DPI_OCI_SODA_COLL_CREATE_MAP; // create collection if (dpiOci__sodaCollCreateWithMetadata(db, name, nameLength, metadata, metadataLength, mode, &handle, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); if (dpiSodaColl__allocate(db, handle, coll, &error) < 0) { dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); return dpiGen__endPublicFn(db, DPI_FAILURE, &error); } return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_createDocument() [PUBLIC] // Create a SODA document with binary or encoded text content that can be // inserted in the collection or can be used to replace an existing document in // the collection. //----------------------------------------------------------------------------- int dpiSodaDb_createDocument(dpiSodaDb *db, const char *key, uint32_t keyLength, const char *content, uint32_t contentLength, const char *mediaType, uint32_t mediaTypeLength, UNUSED uint32_t flags, dpiSodaDoc **doc) { dpiError error; int status; // validate parameters if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(db, key) DPI_CHECK_PTR_AND_LENGTH(db, content) DPI_CHECK_PTR_AND_LENGTH(db, mediaType) DPI_CHECK_PTR_NOT_NULL(db, doc) // create document status = dpiSodaDb__createDocument(db, key, keyLength, content, contentLength, mediaType, mediaTypeLength, doc, &error); return dpiGen__endPublicFn(db, status, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_createJsonDocument() [PUBLIC] // Create a SODA document with JSON content that can be inserted in the // collection or can be used to replace an existing document in the collection. // This is only supported with Oracle Client 23ai and higher. //----------------------------------------------------------------------------- int dpiSodaDb_createJsonDocument(dpiSodaDb *db, const char *key, uint32_t keyLength, const dpiJsonNode *content, UNUSED uint32_t flags, dpiSodaDoc **doc) { int status, jsonDesc; uint32_t tempLength; dpiSodaDoc *tempDoc; void *jsonHandle; dpiError error; // validate parameters if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(db, key) DPI_CHECK_PTR_NOT_NULL(db, doc) // only supported in Oracle Client 23ai+ if (dpiUtils__checkClientVersion(db->env->versionInfo, 23, 4, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); // create document if (dpiSodaDb__createDocument(db, key, keyLength, NULL, 0, NULL, 0, &tempDoc, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); // populate content, if applicable if (content) { jsonDesc = 1; status = dpiOci__attrSet(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, &jsonDesc, 0, DPI_OCI_ATTR_SODA_JSON_DESC, "set JSON descriptor flag", &error); if (status == DPI_SUCCESS) { status = dpiOci__attrGet(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) &jsonHandle, &tempLength, DPI_OCI_ATTR_SODA_CONTENT, "get JSON descriptor", &error); } if (status == DPI_SUCCESS) status = dpiJson__allocate(db->conn, jsonHandle, &tempDoc->json, &error); if (status == DPI_SUCCESS) status = dpiJson__setValue(tempDoc->json, content, &error); if (status != DPI_SUCCESS) { dpiSodaDoc__free(tempDoc, &error); return dpiGen__endPublicFn(db, DPI_FAILURE, &error); } } *doc = tempDoc; return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_freeCollectionNames() [PUBLIC] // Free the names of the collections allocated earlier with a call to // dpiSodaDb_getCollectionNames(). This method is deprecated and should be // replaced with a call to dpiContext_freeStringList(). //----------------------------------------------------------------------------- int dpiSodaDb_freeCollectionNames(dpiSodaDb *db, dpiStringList *names) { dpiError error; // validate parameters if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(db, names) dpiStringList__free(names); return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_getCollections() [PUBLIC] // Return a cursor to iterate over the SODA collections in the database. //----------------------------------------------------------------------------- int dpiSodaDb_getCollections(dpiSodaDb *db, const char *startName, uint32_t startNameLength, uint32_t flags, dpiSodaCollCursor **cursor) { dpiError error; uint32_t mode; void *handle; if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(db, startName) DPI_CHECK_PTR_NOT_NULL(db, cursor) mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; if (dpiOci__sodaCollList(db, startName, startNameLength, &handle, mode, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); if (dpiSodaCollCursor__allocate(db, handle, cursor, &error) < 0) { dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); return dpiGen__endPublicFn(db, DPI_FAILURE, &error); } return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_getCollectionNames() [PUBLIC] // Return the names of all collections in the provided array. //----------------------------------------------------------------------------- int dpiSodaDb_getCollectionNames(dpiSodaDb *db, const char *startName, uint32_t startNameLength, uint32_t limit, uint32_t flags, dpiStringList *names) { dpiError error; uint32_t mode; void *handle; int status; // validate parameters if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(db, startName) DPI_CHECK_PTR_NOT_NULL(db, names) // determine OCI mode to use mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; // acquire collection cursor if (dpiOci__sodaCollList(db, startName, startNameLength, &handle, mode, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); // iterate over cursor to acquire collection names memset(names, 0, sizeof(dpiStringList)); status = dpiSodaDb__getCollectionNames(db, handle, limit, names, &error); dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLL_CURSOR); if (status < 0) dpiStringList__free(names); return dpiGen__endPublicFn(db, status, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_openCollection() [PUBLIC] // Open an existing SODA collection and return a handle to it. //----------------------------------------------------------------------------- int dpiSodaDb_openCollection(dpiSodaDb *db, const char *name, uint32_t nameLength, uint32_t flags, dpiSodaColl **coll) { dpiError error; uint32_t mode; void *handle; if (dpiSodaDb__checkConnected(db, __func__, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(db, name) DPI_CHECK_PTR_NOT_NULL(db, coll) mode = DPI_OCI_DEFAULT; if (flags & DPI_SODA_FLAGS_ATOMIC_COMMIT) mode |= DPI_OCI_SODA_ATOMIC_COMMIT; if (dpiOci__sodaCollOpen(db, name, nameLength, mode, &handle, &error) < 0) return dpiGen__endPublicFn(db, DPI_FAILURE, &error); *coll = NULL; if (handle) { if (dpiSodaColl__allocate(db, handle, coll, &error) < 0) { dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_COLLECTION); return dpiGen__endPublicFn(db, DPI_FAILURE, &error); } } return dpiGen__endPublicFn(db, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDb_release() [PUBLIC] // Release a reference to the SODA database. //----------------------------------------------------------------------------- int dpiSodaDb_release(dpiSodaDb *db) { return dpiGen__release(db, DPI_HTYPE_SODA_DB, __func__); } odpi-5.6.4/src/dpiSodaDoc.c000066400000000000000000000306001510466437300154350ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiSodaDoc.c // Implementation of SODA documents. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiSodaDoc__allocate() [INTERNAL] // Allocate and initialize a SODA document structure. //----------------------------------------------------------------------------- int dpiSodaDoc__allocate(dpiSodaDb *db, void *handle, dpiSodaDoc **doc, dpiError *error) { int isJson, status = DPI_SUCCESS; dpiSodaDoc *tempDoc; uint32_t tempLen; void *jsonHandle; // allocate SODA document structure if (dpiGen__allocate(DPI_HTYPE_SODA_DOC, db->env, (void**) &tempDoc, error) < 0) { if (handle) dpiOci__handleFree(tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT); return DPI_FAILURE; } // if no handle was provided, allocate one if (!handle) { status = dpiOci__handleAlloc(db->env->handle, &tempDoc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, "allocate SODA document handle", error); // otherwise, for Oracle 23ai and higher, acquire JSON, if applicable } else { tempDoc->handle = handle; if (db->env->context->sodaUseJsonDesc) { status = dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) &isJson, 0, DPI_OCI_ATTR_SODA_JSON_DESC, "get is JSON", error); if (status == DPI_SUCCESS && isJson) { status = dpiOci__attrGet(handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) &jsonHandle, &tempLen, DPI_OCI_ATTR_SODA_CONTENT, "get JSON descriptor", error); if (status == DPI_SUCCESS) status = dpiJson__allocate(db->conn, jsonHandle, &tempDoc->json, error); } } } if (status < 0) { dpiSodaDoc__free(tempDoc, error); return DPI_FAILURE; } dpiGen__setRefCount(db, error, 1); tempDoc->db = db; *doc = tempDoc; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDoc__check() [INTERNAL] // Determine if the SODA document is available to use. //----------------------------------------------------------------------------- static int dpiSodaDoc__check(dpiSodaDoc *doc, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(doc, DPI_HTYPE_SODA_DOC, fnName, error) < 0) return DPI_FAILURE; if (!doc->db->conn->handle || doc->db->conn->closing) return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDoc__free() [INTERNAL] // Free the memory for a SODA document. Note that the reference to the // database must remain until after the handle is freed; otherwise, a segfault // can take place. //----------------------------------------------------------------------------- void dpiSodaDoc__free(dpiSodaDoc *doc, dpiError *error) { if (doc->json) { dpiGen__setRefCount(doc->json, error, -1); doc->json = NULL; } if (doc->handle) { dpiOci__handleFree(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT); doc->handle = NULL; } if (doc->db) { dpiGen__setRefCount(doc->db, error, -1); doc->db = NULL; } dpiUtils__freeMemory(doc); } //----------------------------------------------------------------------------- // dpiSodaDoc__getAttributeText() [INTERNAL] // Get the value of the OCI attribute as a text string. //----------------------------------------------------------------------------- static int dpiSodaDoc__getAttributeText(dpiSodaDoc *doc, uint32_t attribute, const char **value, uint32_t *valueLength, const char *fnName) { dpiError error; int status; // validate parameters if (dpiSodaDoc__check(doc, fnName, &error) < 0) return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(doc, value) DPI_CHECK_PTR_NOT_NULL(doc, valueLength) // get attribute value status = dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) value, valueLength, attribute, "get value", &error); return dpiGen__endPublicFn(doc, status, &error); } //----------------------------------------------------------------------------- // dpiSodaDoc_addRef() [PUBLIC] // Add a reference to the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_addRef(dpiSodaDoc *doc) { return dpiGen__addRef(doc, DPI_HTYPE_SODA_DOC, __func__); } //----------------------------------------------------------------------------- // dpiSodaDoc_getContent() [PUBLIC] // Return the content of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getContent(dpiSodaDoc *doc, const char **value, uint32_t *valueLength, const char **encoding) { uint16_t charsetId; dpiError error; // validate parameters if (dpiSodaDoc__check(doc, __func__, &error) < 0) return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(doc, value) DPI_CHECK_PTR_NOT_NULL(doc, valueLength) DPI_CHECK_PTR_NOT_NULL(doc, encoding) if (doc->json) { dpiError__set(&error, "check content of SODA document", DPI_ERR_SODA_DOC_IS_JSON); return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); } // get content if (dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) value, valueLength, DPI_OCI_ATTR_SODA_CONTENT, "get content", &error) < 0) return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); // if content is not in binary form, always use UTF-8 if (!doc->binaryContent) *encoding = DPI_CHARSET_NAME_UTF8; // otherwise, determine the encoding from OCI else { if (dpiOci__attrGet(doc->handle, DPI_OCI_HTYPE_SODA_DOCUMENT, (void*) &charsetId, 0, DPI_OCI_ATTR_SODA_JSON_CHARSET_ID, "get charset", &error) < 0) return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); switch (charsetId) { case 0: *encoding = NULL; break; case DPI_CHARSET_ID_UTF8: *encoding = DPI_CHARSET_NAME_UTF8; break; case DPI_CHARSET_ID_UTF16BE: *encoding = DPI_CHARSET_NAME_UTF16BE; break; case DPI_CHARSET_ID_UTF16LE: *encoding = DPI_CHARSET_NAME_UTF16LE; break; default: dpiError__set(&error, "check charset", DPI_ERR_INVALID_CHARSET_ID, charsetId); return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); } } return dpiGen__endPublicFn(doc, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDoc_getCreatedOn() [PUBLIC] // Return the created timestamp of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getCreatedOn(dpiSodaDoc *doc, const char **value, uint32_t *valueLength) { return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_CREATE_TIMESTAMP, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiSodaDoc_getIsJson() [PUBLIC] // Return a boolean value indicating if the document contains JSON or not. // If the value contains JSON, the method dpiSodaDoc_getJsonContent() should be // called; otherwise, dpiSodaDoc_getContent() should be called. //----------------------------------------------------------------------------- int dpiSodaDoc_getIsJson(dpiSodaDoc *doc, int *isJson) { dpiError error; // validate parameters if (dpiSodaDoc__check(doc, __func__, &error) < 0) return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(doc, isJson) // calculate value *isJson = (doc->json) ? 1 : 0; return dpiGen__endPublicFn(doc, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDoc_getJsonContent() [PUBLIC] // Return the JSON content of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getJsonContent(dpiSodaDoc *doc, dpiJson **json) { dpiError error; // validate parameters if (dpiSodaDoc__check(doc, __func__, &error) < 0) return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(doc, json) if (!doc->json) { dpiError__set(&error, "check content of SODA document", DPI_ERR_SODA_DOC_IS_NOT_JSON); return dpiGen__endPublicFn(doc, DPI_FAILURE, &error); } // get content *json = doc->json; return dpiGen__endPublicFn(doc, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDoc_getKey() [PUBLIC] // Return the key of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getKey(dpiSodaDoc *doc, const char **value, uint32_t *valueLength) { return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_KEY, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiSodaDoc_getLastModified() [PUBLIC] // Return the last modified timestamp of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getLastModified(dpiSodaDoc *doc, const char **value, uint32_t *valueLength) { return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_LASTMOD_TIMESTAMP, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiSodaDoc_getMediaType() [PUBLIC] // Return the media type of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getMediaType(dpiSodaDoc *doc, const char **value, uint32_t *valueLength) { return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_MEDIA_TYPE, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiSodaDoc_getVersion() [PUBLIC] // Return the version of the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_getVersion(dpiSodaDoc *doc, const char **value, uint32_t *valueLength) { return dpiSodaDoc__getAttributeText(doc, DPI_OCI_ATTR_SODA_VERSION, value, valueLength, __func__); } //----------------------------------------------------------------------------- // dpiSodaDoc_release() [PUBLIC] // Release a reference to the SODA document. //----------------------------------------------------------------------------- int dpiSodaDoc_release(dpiSodaDoc *doc) { return dpiGen__release(doc, DPI_HTYPE_SODA_DOC, __func__); } odpi-5.6.4/src/dpiSodaDocCursor.c000066400000000000000000000137661510466437300166510ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiSodaDocCursor.c // Implementation of SODA document cursors. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiSodaDocCursor__allocate() [INTERNAL] // Allocate and initialize a SODA document cursor structure. //----------------------------------------------------------------------------- int dpiSodaDocCursor__allocate(dpiSodaColl *coll, void *handle, dpiSodaDocCursor **cursor, dpiError *error) { dpiSodaDocCursor *tempCursor; if (dpiGen__allocate(DPI_HTYPE_SODA_DOC_CURSOR, coll->env, (void**) &tempCursor, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(coll, error, 1); tempCursor->coll = coll; tempCursor->handle = handle; *cursor = tempCursor; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDocCursor__check() [INTERNAL] // Determine if the SODA document cursor is available to use. //----------------------------------------------------------------------------- static int dpiSodaDocCursor__check(dpiSodaDocCursor *cursor, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(cursor, DPI_HTYPE_SODA_DOC_CURSOR, fnName, error) < 0) return DPI_FAILURE; if (!cursor->handle) return dpiError__set(error, "check closed", DPI_ERR_SODA_CURSOR_CLOSED); if (!cursor->coll->db->conn->handle || cursor->coll->db->conn->closing) return dpiError__set(error, "check connection", DPI_ERR_NOT_CONNECTED); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSodaDocCursor__free() [INTERNAL] // Free the memory for a SODA document cursor. Note that the reference to the // collection must remain until after the handle is freed; otherwise, a // segfault can take place. //----------------------------------------------------------------------------- void dpiSodaDocCursor__free(dpiSodaDocCursor *cursor, dpiError *error) { if (cursor->handle) { dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_DOC_CURSOR); cursor->handle = NULL; } if (cursor->coll) { dpiGen__setRefCount(cursor->coll, error, -1); cursor->coll = NULL; } dpiUtils__freeMemory(cursor); } //----------------------------------------------------------------------------- // dpiSodaDocCursor_addRef() [PUBLIC] // Add a reference to the SODA document cursor. //----------------------------------------------------------------------------- int dpiSodaDocCursor_addRef(dpiSodaDocCursor *cursor) { return dpiGen__addRef(cursor, DPI_HTYPE_SODA_DOC_CURSOR, __func__); } //----------------------------------------------------------------------------- // dpiSodaDocCursor_close() [PUBLIC] // Close the cursor. //----------------------------------------------------------------------------- int dpiSodaDocCursor_close(dpiSodaDocCursor *cursor) { dpiError error; if (dpiSodaDocCursor__check(cursor, __func__, &error) < 0) return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); if (cursor->handle) { dpiOci__handleFree(cursor->handle, DPI_OCI_HTYPE_SODA_DOC_CURSOR); cursor->handle = NULL; } return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDocCursor_getNext() [PUBLIC] // Return the next document available from the cursor. //----------------------------------------------------------------------------- int dpiSodaDocCursor_getNext(dpiSodaDocCursor *cursor, UNUSED uint32_t flags, dpiSodaDoc **doc) { dpiError error; void *handle; if (dpiSodaDocCursor__check(cursor, __func__, &error) < 0) return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(cursor, doc) if (dpiOci__sodaDocGetNext(cursor, &handle, &error) < 0) return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); *doc = NULL; if (handle) { if (dpiSodaDoc__allocate(cursor->coll->db, handle, doc, &error) < 0) { dpiOci__handleFree(handle, DPI_OCI_HTYPE_SODA_DOCUMENT); return dpiGen__endPublicFn(cursor, DPI_FAILURE, &error); } (*doc)->binaryContent = cursor->coll->binaryContent; } return dpiGen__endPublicFn(cursor, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSodaDocCursor_release() [PUBLIC] // Release a reference to the SODA document cursor. //----------------------------------------------------------------------------- int dpiSodaDocCursor_release(dpiSodaDocCursor *cursor) { return dpiGen__release(cursor, DPI_HTYPE_SODA_DOC_CURSOR, __func__); } odpi-5.6.4/src/dpiStmt.c000066400000000000000000002365241510466437300150650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiStmt.c // Implementation of statements (cursors). //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info, dpiError *error); static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param, dpiQueryInfo *info, dpiError *error); static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error); static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error); static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, dpiError *error); //----------------------------------------------------------------------------- // dpiStmt__allocate() [INTERNAL] // Create a new statement object and return it. In case of error NULL is // returned. //----------------------------------------------------------------------------- int dpiStmt__allocate(dpiConn *conn, int scrollable, dpiStmt **stmt, dpiError *error) { dpiStmt *tempStmt; *stmt = NULL; if (dpiGen__allocate(DPI_HTYPE_STMT, conn->env, (void**) &tempStmt, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempStmt->conn = conn; tempStmt->fetchArraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE; tempStmt->prefetchRows = DPI_DEFAULT_PREFETCH_ROWS; tempStmt->scrollable = scrollable; *stmt = tempStmt; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__bind() [INTERNAL] // Bind the variable to the statement using either a position or a name. A // reference to the variable will be retained. //----------------------------------------------------------------------------- static int dpiStmt__bind(dpiStmt *stmt, dpiVar *var, uint32_t pos, const char *name, uint32_t nameLength, dpiError *error) { dpiBindVar *bindVars, *entry = NULL; int found, dynamicBind, status; void *bindHandle = NULL; uint32_t i; // a zero length name is not supported if (pos == 0 && nameLength == 0) return dpiError__set(error, "bind zero length name", DPI_ERR_NOT_SUPPORTED); // prevent attempts to bind a statement to itself if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_STMT) { for (i = 0; i < var->buffer.maxArraySize; i++) { if (var->buffer.externalData[i].value.asStmt == stmt) { return dpiError__set(error, "bind to self", DPI_ERR_NOT_SUPPORTED); } } } // check to see if the bind position or name has already been bound found = 0; for (i = 0; i < stmt->numBindVars; i++) { entry = &stmt->bindVars[i]; if (entry->pos == pos && entry->nameLength == nameLength) { if (nameLength > 0 && strncmp(entry->name, name, nameLength) != 0) continue; found = 1; break; } } // if already found, use that entry if (found) { // if already bound, no need to bind a second time if (entry->var == var) return DPI_SUCCESS; // otherwise, release previously bound variable, if applicable else if (entry->var) { dpiGen__setRefCount(entry->var, error, -1); entry->var = NULL; } // if not found, add to the list of bind variables } else { // allocate memory for additional bind variables, if needed if (stmt->numBindVars == stmt->allocatedBindVars) { if (dpiUtils__allocateMemory(stmt->allocatedBindVars + 8, sizeof(dpiBindVar), 1, "allocate bind vars", (void**) &bindVars, error) < 0) return DPI_FAILURE; if (stmt->bindVars) { for (i = 0; i < stmt->numBindVars; i++) bindVars[i] = stmt->bindVars[i]; dpiUtils__freeMemory(stmt->bindVars); } stmt->bindVars = bindVars; stmt->allocatedBindVars += 8; } // add to the list of bind variables entry = &stmt->bindVars[stmt->numBindVars]; entry->var = NULL; entry->pos = pos; if (name) { if (dpiUtils__allocateMemory(1, nameLength, 0, "allocate memory for name", (void**) &entry->name, error) < 0) return DPI_FAILURE; entry->nameLength = nameLength; memcpy( (void*) entry->name, name, nameLength); } stmt->numBindVars++; } // for PL/SQL where the maxSize is greater than 32K, adjust the variable // so that LOBs are used internally if (var->isDynamic && (stmt->statementType == DPI_STMT_TYPE_BEGIN || stmt->statementType == DPI_STMT_TYPE_DECLARE || stmt->statementType == DPI_STMT_TYPE_CALL)) { if (dpiVar__convertToLob(var, error) < 0) return DPI_FAILURE; } // perform actual bind dpiGen__setRefCount(var, error, 1); entry->var = var; dynamicBind = stmt->isReturning || var->isDynamic; if (pos > 0) { if (stmt->env->versionInfo->versionNum < 12) status = dpiOci__bindByPos(stmt, &bindHandle, pos, dynamicBind, var, error); else status = dpiOci__bindByPos2(stmt, &bindHandle, pos, dynamicBind, var, error); } else { if (stmt->env->versionInfo->versionNum < 12) status = dpiOci__bindByName(stmt, &bindHandle, name, (int32_t) nameLength, dynamicBind, var, error); else status = dpiOci__bindByName2(stmt, &bindHandle, name, (int32_t) nameLength, dynamicBind, var, error); } // attempt to improve message "ORA-01036: illegal variable name/number" if (status < 0) { if (error->buffer->code == 1036) { if (stmt->statementType == DPI_STMT_TYPE_CREATE || stmt->statementType == DPI_STMT_TYPE_DROP || stmt->statementType == DPI_STMT_TYPE_ALTER) dpiError__set(error, error->buffer->action, DPI_ERR_NO_BIND_VARS_IN_DDL); } return DPI_FAILURE; } // set the charset form if applicable if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) { if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND, (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, "set charset form", error) < 0) return DPI_FAILURE; } // set the max data size, if applicable if (var->type->sizeInBytes == 0 && !var->isDynamic) { if (dpiOci__attrSet(bindHandle, DPI_OCI_HTYPE_BIND, (void*) &var->sizeInBytes, 0, DPI_OCI_ATTR_MAXDATA_SIZE, "set max data size", error) < 0) return DPI_FAILURE; } // bind object, if applicable if (var->buffer.objectIndicator && dpiOci__bindObject(var, bindHandle, error) < 0) return DPI_FAILURE; // setup dynamic bind, if applicable if (dynamicBind && dpiOci__bindDynamic(var, bindHandle, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__check() [INTERNAL] // Determine if the statement is open and available for use. //----------------------------------------------------------------------------- static int dpiStmt__check(dpiStmt *stmt, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(stmt, DPI_HTYPE_STMT, fnName, error) < 0) return DPI_FAILURE; if (!stmt->handle || (stmt->parentStmt && !stmt->parentStmt->handle)) return dpiError__set(error, "check closed", DPI_ERR_STMT_CLOSED); if (dpiConn__checkConnected(stmt->conn, error) < 0) return DPI_FAILURE; if (stmt->statementType == 0 && dpiStmt__init(stmt, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__clearBatchErrors() [INTERNAL] // Clear the batch errors associated with the statement. //----------------------------------------------------------------------------- static void dpiStmt__clearBatchErrors(dpiStmt *stmt) { if (stmt->batchErrors) { dpiUtils__freeMemory(stmt->batchErrors); stmt->batchErrors = NULL; } stmt->numBatchErrors = 0; } //----------------------------------------------------------------------------- // dpiStmt__clearBindVars() [INTERNAL] // Clear the bind variables associated with the statement. //----------------------------------------------------------------------------- static void dpiStmt__clearBindVars(dpiStmt *stmt, dpiError *error) { uint32_t i; if (stmt->bindVars) { for (i = 0; i < stmt->numBindVars; i++) { if (stmt->bindVars[i].var) dpiGen__setRefCount(stmt->bindVars[i].var, error, -1); if (stmt->bindVars[i].name) dpiUtils__freeMemory( (void*) stmt->bindVars[i].name); } dpiUtils__freeMemory(stmt->bindVars); stmt->bindVars = NULL; } stmt->numBindVars = 0; stmt->allocatedBindVars = 0; } //----------------------------------------------------------------------------- // dpiStmt__clearQueryVars() [INTERNAL] // Clear the query variables associated with the statement. //----------------------------------------------------------------------------- static void dpiStmt__clearQueryVars(dpiStmt *stmt, dpiError *error) { dpiDataTypeInfo *typeInfo; uint32_t i; if (stmt->queryVars) { for (i = 0; i < stmt->numQueryVars; i++) { if (stmt->queryVars[i]) { dpiGen__setRefCount(stmt->queryVars[i], error, -1); stmt->queryVars[i] = NULL; } typeInfo = &stmt->queryInfo[i].typeInfo; if (typeInfo->objectType) { dpiGen__setRefCount(typeInfo->objectType, error, -1); typeInfo->objectType = NULL; } if (typeInfo->annotations) { dpiUtils__freeMemory(typeInfo->annotations); typeInfo->annotations = NULL; } } dpiUtils__freeMemory(stmt->queryVars); stmt->queryVars = NULL; } if (stmt->queryInfo) { dpiUtils__freeMemory(stmt->queryInfo); stmt->queryInfo = NULL; } stmt->numQueryVars = 0; } //----------------------------------------------------------------------------- // dpiStmt__close() [INTERNAL] // Internal method used for closing the statement. If the statement is marked // as needing to be dropped from the statement cache that is done as well. This // is called from dpiStmt_close() where errors are expected to be propagated // and from dpiStmt__free() where errors are ignored. //----------------------------------------------------------------------------- int dpiStmt__close(dpiStmt *stmt, const char *tag, uint32_t tagLength, int propagateErrors, dpiError *error) { int closing, status = DPI_SUCCESS; // determine whether statement is already being closed and if not, mark // statement as being closed; this MUST be done while holding the lock (if // in threaded mode) to avoid race conditions! if (stmt->env->threaded) dpiMutex__acquire(stmt->env->mutex); closing = stmt->closing; stmt->closing = 1; if (stmt->env->threaded) dpiMutex__release(stmt->env->mutex); // if statement is already being closed, nothing needs to be done if (closing) return DPI_SUCCESS; // perform actual work of closing statement dpiStmt__clearBatchErrors(stmt); dpiStmt__clearBindVars(stmt, error); dpiStmt__clearQueryVars(stmt, error); if (stmt->lastRowid) dpiGen__setRefCount(stmt->lastRowid, error, -1); if (stmt->handle) { if (stmt->parentStmt) { dpiGen__setRefCount(stmt->parentStmt, error, -1); stmt->parentStmt = NULL; } else if (!stmt->conn->deadSession && stmt->conn->handle) { if (stmt->isOwned) dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT); else status = dpiOci__stmtRelease(stmt, tag, tagLength, propagateErrors, error); } stmt->handle = NULL; } // if actual close fails, reset closing flag; again, this must be done // while holding the lock (if in threaded mode) in order to avoid race // conditions! if (status < 0) { if (stmt->env->threaded) dpiMutex__acquire(stmt->env->mutex); stmt->closing = 0; if (stmt->env->threaded) dpiMutex__release(stmt->env->mutex); } return status; } //----------------------------------------------------------------------------- // dpiStmt__createBindVar() [INTERNAL] // Create a bind variable given a value to bind. //----------------------------------------------------------------------------- static int dpiStmt__createBindVar(dpiStmt *stmt, dpiNativeTypeNum nativeTypeNum, dpiData *data, dpiVar **var, uint32_t pos, const char *name, uint32_t nameLength, dpiError *error) { dpiOracleTypeNum oracleTypeNum; dpiObjectType *objType; dpiData *varData; dpiVar *tempVar; uint32_t size; int status; // determine the type (and size) of bind variable to create size = 0; objType = NULL; switch (nativeTypeNum) { case DPI_NATIVE_TYPE_INT64: case DPI_NATIVE_TYPE_UINT64: case DPI_NATIVE_TYPE_FLOAT: case DPI_NATIVE_TYPE_DOUBLE: oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; break; case DPI_NATIVE_TYPE_BYTES: oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; size = data->value.asBytes.length; break; case DPI_NATIVE_TYPE_TIMESTAMP: oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP; break; case DPI_NATIVE_TYPE_INTERVAL_DS: oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_DS; break; case DPI_NATIVE_TYPE_INTERVAL_YM: oracleTypeNum = DPI_ORACLE_TYPE_INTERVAL_YM; break; case DPI_NATIVE_TYPE_OBJECT: oracleTypeNum = DPI_ORACLE_TYPE_OBJECT; if (data->value.asObject) objType = data->value.asObject->type; break; case DPI_NATIVE_TYPE_ROWID: oracleTypeNum = DPI_ORACLE_TYPE_ROWID; break; case DPI_NATIVE_TYPE_BOOLEAN: oracleTypeNum = DPI_ORACLE_TYPE_BOOLEAN; break; default: return dpiError__set(error, "create bind var", DPI_ERR_UNHANDLED_CONVERSION, 0, nativeTypeNum); } // create the variable and set its value if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, 1, size, 1, 0, objType, &tempVar, &varData, error) < 0) return DPI_FAILURE; // copy value from source to target data if (dpiVar__copyData(tempVar, 0, data, error) < 0) return DPI_FAILURE; // bind variable to statement status = dpiStmt__bind(stmt, tempVar, pos, name, nameLength, error); dpiGen__setRefCount(tempVar, error, -1); if (status == DPI_SUCCESS) *var = tempVar; return status; } //----------------------------------------------------------------------------- // dpiStmt__createQueryVars() [INTERNAL] // Create space for the number of query variables required to support the // query. //----------------------------------------------------------------------------- static int dpiStmt__createQueryVars(dpiStmt *stmt, dpiError *error) { uint32_t numQueryVars, i; // determine number of query variables if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &numQueryVars, 0, DPI_OCI_ATTR_PARAM_COUNT, "get parameter count", error) < 0) return DPI_FAILURE; // clear the previous query vars if the number has changed if (stmt->numQueryVars > 0 && stmt->numQueryVars != numQueryVars) dpiStmt__clearQueryVars(stmt, error); // allocate space for the query vars, if needed if (numQueryVars != stmt->numQueryVars) { if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiVar*), 1, "allocate query vars", (void**) &stmt->queryVars, error) < 0) return DPI_FAILURE; if (dpiUtils__allocateMemory(numQueryVars, sizeof(dpiQueryInfo), 1, "allocate query info", (void**) &stmt->queryInfo, error) < 0) { dpiStmt__clearQueryVars(stmt, error); return DPI_FAILURE; } stmt->numQueryVars = numQueryVars; for (i = 0; i < numQueryVars; i++) { if (dpiStmt__getQueryInfo(stmt, i + 1, &stmt->queryInfo[i], error) < 0) { dpiStmt__clearQueryVars(stmt, error); return DPI_FAILURE; } } } // indicate start of fetch stmt->bufferRowIndex = stmt->fetchArraySize; stmt->hasRowsToFetch = 1; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__define() [INTERNAL] // Define the variable that will accept output from the statement in the // specified column. At this point the statement, position and variable are all // assumed to be valid. //----------------------------------------------------------------------------- static int dpiStmt__define(dpiStmt *stmt, uint32_t pos, dpiVar *var, dpiError *error) { void *defineHandle = NULL; dpiQueryInfo *queryInfo; int tempBool; // no need to perform define if variable is unchanged if (stmt->queryVars[pos - 1] == var) return DPI_SUCCESS; // for objects, the type specified must match the type in the database queryInfo = &stmt->queryInfo[pos - 1]; if (var->objectType && queryInfo->typeInfo.objectType && var->objectType->tdo != queryInfo->typeInfo.objectType->tdo) return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, var->objectType->schemaLength, var->objectType->schema, var->objectType->nameLength, var->objectType->name, queryInfo->typeInfo.objectType->schemaLength, queryInfo->typeInfo.objectType->schema, queryInfo->typeInfo.objectType->nameLength, queryInfo->typeInfo.objectType->name); // perform the define if (stmt->env->versionInfo->versionNum < 12) { if (dpiOci__defineByPos(stmt, &defineHandle, pos, var, error) < 0) return DPI_FAILURE; } else { if (dpiOci__defineByPos2(stmt, &defineHandle, pos, var, error) < 0) return DPI_FAILURE; } // set the charset form if applicable if (var->type->charsetForm != DPI_SQLCS_IMPLICIT) { if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE, (void*) &var->type->charsetForm, 0, DPI_OCI_ATTR_CHARSET_FORM, "set charset form", error) < 0) return DPI_FAILURE; } // specify that the LOB length should be prefetched if (var->nativeTypeNum == DPI_NATIVE_TYPE_LOB) { tempBool = 1; if (dpiOci__attrSet(defineHandle, DPI_OCI_HTYPE_DEFINE, (void*) &tempBool, 0, DPI_OCI_ATTR_LOBPREFETCH_LENGTH, "set lob prefetch length", error) < 0) return DPI_FAILURE; } // define objects, if applicable if (var->buffer.objectIndicator && dpiOci__defineObject(var, defineHandle, error) < 0) return DPI_FAILURE; // register callback for dynamic defines if (var->isDynamic && dpiOci__defineDynamic(var, defineHandle, error) < 0) return DPI_FAILURE; // remove previous variable and retain new one if (stmt->queryVars[pos - 1]) dpiGen__setRefCount(stmt->queryVars[pos - 1], error, -1); dpiGen__setRefCount(var, error, 1); stmt->queryVars[pos - 1] = var; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__execute() [INTERNAL] // Internal execution of statement. //----------------------------------------------------------------------------- static int dpiStmt__execute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, int reExecute, dpiError *error) { uint32_t i, j, temp, sqlIdLength; uint16_t tempOffset; dpiData *data; dpiVar *var; char *sqlId; // for all bound variables, transfer data from dpiData structure to Oracle // buffer structures for (i = 0; i < stmt->numBindVars; i++) { var = stmt->bindVars[i].var; if (var->isArray && numIters > 1) return dpiError__set(error, "bind array var", DPI_ERR_ARRAY_VAR_NOT_SUPPORTED); for (j = 0; j < var->buffer.maxArraySize; j++) { data = &var->buffer.externalData[j]; if (dpiVar__setValue(var, &var->buffer, j, data, error) < 0) return DPI_FAILURE; if (var->dynBindBuffers) var->dynBindBuffers[j].actualArraySize = 0; } if (stmt->isReturning || var->isDynamic) var->error = error; } // for queries, set the OCI prefetch; the default value prevents an // additional round trip for single row fetches while avoiding the overhead // of copying from the OCI prefetch buffer to our own buffers for larger // fetches if (stmt->statementType == DPI_STMT_TYPE_SELECT) { if (dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, &stmt->prefetchRows, sizeof(stmt->prefetchRows), DPI_OCI_ATTR_PREFETCH_ROWS, "set prefetch rows", error) < 0) return DPI_FAILURE; } // clear batch errors from any previous execution dpiStmt__clearBatchErrors(stmt); // adjust mode for scrollable cursors, but not if performing a describe // only (or a malformed TTC packet from client exception is thrown) if (stmt->scrollable && !(mode & DPI_MODE_EXEC_DESCRIBE_ONLY)) mode |= DPI_OCI_STMT_SCROLLABLE_READONLY; // if requested, suspend the sessionless transaction after the call // completes successfully if (mode & DPI_MODE_EXEC_SUSPEND_ON_SUCCESS) { if (dpiConn__suspendSessionlessTransaction(stmt->conn, DPI_OCI_SUSPEND_POST_CALL, error) < 0) return DPI_FAILURE; } // perform execution // re-execute statement for ORA-01007: variable not in select list and // ORA-00932: inconsistent data types; drop statement from cache for all // errors (except those which are due to invalid data which may be fixed in // subsequent execution) if (dpiOci__stmtExecute(stmt, numIters, mode, error) < 0) { dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &tempOffset, 0, DPI_OCI_ATTR_PARSE_ERROR_OFFSET, "set parse offset", error); error->buffer->offset = tempOffset; switch (error->buffer->code) { case 932: case 1007: if (reExecute && stmt->statementType == DPI_STMT_TYPE_SELECT) return dpiStmt__reExecute(stmt, numIters, mode, error); stmt->deleteFromCache = 1; break; case 1: case 1400: case 1438: case 1461: case 2290: case 2291: case 2292: case 21525: break; default: stmt->deleteFromCache = 1; } return DPI_FAILURE; } // if requested, the sessionless transaction would have been suspended so // clear the transaction now if (mode & DPI_MODE_EXEC_SUSPEND_ON_SUCCESS) { if (dpiConn__clearTransaction(stmt->conn, error) < 0) return DPI_FAILURE; } // fetch SQL_ID, if applicable if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 2, NULL) == DPI_SUCCESS) { if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &sqlId, &sqlIdLength, DPI_OCI_ATTR_SQL_ID, "get SQL_ID", error) < 0) return DPI_FAILURE; if (sqlIdLength > sizeof(stmt->sqlId)) sqlIdLength = sizeof(stmt->sqlId); memcpy(stmt->sqlId, sqlId, sqlIdLength); stmt->sqlIdLength = sqlIdLength; } // for queries, disable prefetch for subsequent fetches in order to avoid // the overhead of copying from prefetch buffers to our own buffers if (stmt->statementType == DPI_STMT_TYPE_SELECT) { temp = 0; if (dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, &temp, sizeof(temp), DPI_OCI_ATTR_PREFETCH_ROWS, "reset prefetch rows", error) < 0) return DPI_FAILURE; } // for all bound variables, transfer data from Oracle buffer structures to // dpiData structures; OCI doesn't provide a way of knowing if a variable // is an out variable so do this for all of them when this is a possibility if (stmt->isReturning || stmt->statementType == DPI_STMT_TYPE_BEGIN || stmt->statementType == DPI_STMT_TYPE_DECLARE || stmt->statementType == DPI_STMT_TYPE_CALL) { for (i = 0; i < stmt->numBindVars; i++) { var = stmt->bindVars[i].var; for (j = 0; j < var->buffer.maxArraySize; j++) { if (dpiVar__getValue(var, &var->buffer, j, 0, error) < 0) return DPI_FAILURE; } var->error = NULL; } } // create query variables (if applicable) and reset row count to zero if (stmt->statementType == DPI_STMT_TYPE_SELECT) { stmt->rowCount = 0; if (!(mode & DPI_MODE_EXEC_PARSE_ONLY) && dpiStmt__createQueryVars(stmt, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__fetch() [INTERNAL] // Performs the actual fetch from Oracle. //----------------------------------------------------------------------------- static int dpiStmt__fetch(dpiStmt *stmt, dpiError *error) { // perform any pre-fetch activities required if (dpiStmt__beforeFetch(stmt, error) < 0) return DPI_FAILURE; // perform fetch if (dpiOci__stmtFetch2(stmt, stmt->fetchArraySize, DPI_MODE_FETCH_NEXT, 0, error) < 0) return DPI_FAILURE; // determine the number of rows fetched into buffers if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED, "get rows fetched", error) < 0) return DPI_FAILURE; // set buffer row info stmt->bufferMinRow = stmt->rowCount + 1; stmt->bufferRowIndex = 0; // perform post-fetch activities required if (dpiStmt__postFetch(stmt, error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__free() [INTERNAL] // Free the memory associated with the statement. //----------------------------------------------------------------------------- void dpiStmt__free(dpiStmt *stmt, dpiError *error) { dpiStmt__close(stmt, NULL, 0, 0, error); if (stmt->parentStmt) { dpiGen__setRefCount(stmt->parentStmt, error, -1); stmt->parentStmt = NULL; } if (stmt->conn) { dpiHandleList__removeHandle(stmt->conn->openStmts, stmt->openSlotNum); dpiGen__setRefCount(stmt->conn, error, -1); stmt->conn = NULL; } dpiUtils__freeMemory(stmt); } //----------------------------------------------------------------------------- // dpiStmt__getBatchErrors() [INTERNAL] // Get batch errors after statement executed with batch errors enabled. //----------------------------------------------------------------------------- static int dpiStmt__getBatchErrors(dpiStmt *stmt, dpiError *error) { void *batchErrorHandle, *localErrorHandle; dpiError localError; int overallStatus; int32_t rowOffset; uint32_t i; // determine the number of batch errors that were found if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &stmt->numBatchErrors, 0, DPI_OCI_ATTR_NUM_DML_ERRORS, "get batch error count", error) < 0) return DPI_FAILURE; // allocate memory for the batch errors if (dpiUtils__allocateMemory(stmt->numBatchErrors, sizeof(dpiErrorBuffer), 1, "allocate errors", (void**) &stmt->batchErrors, error) < 0) { stmt->numBatchErrors = 0; return DPI_FAILURE; } // allocate error handle used for OCIParamGet() if (dpiOci__handleAlloc(stmt->env->handle, &localErrorHandle, DPI_OCI_HTYPE_ERROR, "allocate parameter error handle", error) < 0) { dpiStmt__clearBatchErrors(stmt); return DPI_FAILURE; } // allocate error handle used for batch errors if (dpiOci__handleAlloc(stmt->env->handle, &batchErrorHandle, DPI_OCI_HTYPE_ERROR, "allocate batch error handle", error) < 0) { dpiStmt__clearBatchErrors(stmt); dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR); return DPI_FAILURE; } // process each error overallStatus = DPI_SUCCESS; localError.buffer = error->buffer; localError.env = error->env; for (i = 0; i < stmt->numBatchErrors; i++) { // get error handle for iteration if (dpiOci__paramGet(error->handle, DPI_OCI_HTYPE_ERROR, &batchErrorHandle, i, "get batch error", error) < 0) { overallStatus = dpiError__set(error, "get batch error", DPI_ERR_INVALID_INDEX, i); break; } // determine row offset localError.handle = localErrorHandle; if (dpiOci__attrGet(batchErrorHandle, DPI_OCI_HTYPE_ERROR, &rowOffset, 0, DPI_OCI_ATTR_DML_ROW_OFFSET, "get row offset", &localError) < 0) { overallStatus = dpiError__set(error, "get row offset", DPI_ERR_CANNOT_GET_ROW_OFFSET); break; } // get error message localError.buffer = &stmt->batchErrors[i]; localError.handle = batchErrorHandle; dpiError__setFromOCI(&localError, DPI_OCI_ERROR, stmt->conn, "get batch error"); if (error->buffer->errorNum) { overallStatus = DPI_FAILURE; break; } localError.buffer->fnName = error->buffer->fnName; localError.buffer->offset = (uint32_t) rowOffset; } // cleanup dpiOci__handleFree(localErrorHandle, DPI_OCI_HTYPE_ERROR); dpiOci__handleFree(batchErrorHandle, DPI_OCI_HTYPE_ERROR); if (overallStatus < 0) dpiStmt__clearBatchErrors(stmt); return overallStatus; } //----------------------------------------------------------------------------- // dpiStmt__getRowCount() [INTERNAL] // Return the number of rows affected by the last DML executed (for insert, // update, delete and merge) or the number of rows fetched (for queries). In // all other cases, 0 is returned. //----------------------------------------------------------------------------- static int dpiStmt__getRowCount(dpiStmt *stmt, uint64_t *count, dpiError *error) { uint32_t rowCount32; if (stmt->statementType == DPI_STMT_TYPE_SELECT) *count = stmt->rowCount; else if (stmt->statementType != DPI_STMT_TYPE_INSERT && stmt->statementType != DPI_STMT_TYPE_UPDATE && stmt->statementType != DPI_STMT_TYPE_DELETE && stmt->statementType != DPI_STMT_TYPE_MERGE && stmt->statementType != DPI_STMT_TYPE_CALL && stmt->statementType != DPI_STMT_TYPE_BEGIN && stmt->statementType != DPI_STMT_TYPE_DECLARE) { *count = 0; } else if (stmt->env->versionInfo->versionNum < 12) { if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &rowCount32, 0, DPI_OCI_ATTR_ROW_COUNT, "get row count", error) < 0) return DPI_FAILURE; *count = rowCount32; } else { if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, count, 0, DPI_OCI_ATTR_UB8_ROW_COUNT, "get row count", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__getQueryInfo() [INTERNAL] // Get query information for the position in question. //----------------------------------------------------------------------------- static int dpiStmt__getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info, dpiError *error) { void *param; int status; // acquire parameter descriptor if (dpiOci__paramGet(stmt->handle, DPI_OCI_HTYPE_STMT, ¶m, pos, "get parameter", error) < 0) return DPI_FAILURE; // acquire information from the parameter descriptor status = dpiStmt__getQueryInfoFromParam(stmt, param, info, error); dpiOci__descriptorFree(param, DPI_OCI_DTYPE_PARAM); return status; } //----------------------------------------------------------------------------- // dpiStmt__getQueryInfoFromParam() [INTERNAL] // Get query information from the parameter. //----------------------------------------------------------------------------- static int dpiStmt__getQueryInfoFromParam(dpiStmt *stmt, void *param, dpiQueryInfo *info, dpiError *error) { uint8_t ociNullOk; // aquire name of item if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &info->name, &info->nameLength, DPI_OCI_ATTR_NAME, "get name", error) < 0) return DPI_FAILURE; // acquire type information if (dpiOracleType__populateTypeInfo(stmt->conn, param, DPI_OCI_HTYPE_DESCRIBE, &info->typeInfo, error) < 0) return DPI_FAILURE; // acquire if column is permitted to be null if (dpiOci__attrGet(param, DPI_OCI_HTYPE_DESCRIBE, (void*) &ociNullOk, 0, DPI_OCI_ATTR_IS_NULL, "get null ok", error) < 0) return DPI_FAILURE; info->nullOk = ociNullOk; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__init() [INTERNAL] // Initialize the statement for use. This is needed when preparing a // statement for use and when returning a REF cursor. //----------------------------------------------------------------------------- int dpiStmt__init(dpiStmt *stmt, dpiError *error) { // get statement type if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &stmt->statementType, 0, DPI_OCI_ATTR_STMT_TYPE, "get statement type", error) < 0) return DPI_FAILURE; // for queries, mark statement as having rows to fetch if (stmt->statementType == DPI_STMT_TYPE_SELECT) stmt->hasRowsToFetch = 1; // otherwise, check if this is a RETURNING statement else if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &stmt->isReturning, 0, DPI_OCI_ATTR_STMT_IS_RETURNING, "get is returning", error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__postFetch() [INTERNAL] // Performs the transformations required to convert Oracle data values into // C data values. //----------------------------------------------------------------------------- static int dpiStmt__postFetch(dpiStmt *stmt, dpiError *error) { uint32_t i, j; dpiVar *var; for (i = 0; i < stmt->numQueryVars; i++) { var = stmt->queryVars[i]; for (j = 0; j < stmt->bufferRowCount; j++) { if (dpiVar__getValue(var, &var->buffer, j, 1, error) < 0) return DPI_FAILURE; if (var->type->requiresPreFetch) var->requiresPreFetch = 1; } var->error = NULL; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__beforeFetch() [INTERNAL] // Performs work that needs to be done prior to fetch for each variable. In // addition, variables are created if they do not already exist. A check is // also made to ensure that the variable has enough space to support a fetch // of the requested size. //----------------------------------------------------------------------------- static int dpiStmt__beforeFetch(dpiStmt *stmt, dpiError *error) { dpiQueryInfo *queryInfo; dpiData *data; dpiVar *var; uint32_t i; if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, error) < 0) return DPI_FAILURE; for (i = 0; i < stmt->numQueryVars; i++) { var = stmt->queryVars[i]; if (!var) { queryInfo = &stmt->queryInfo[i]; if (dpiVar__allocate(stmt->conn, queryInfo->typeInfo.oracleTypeNum, queryInfo->typeInfo.defaultNativeTypeNum, stmt->fetchArraySize, queryInfo->typeInfo.clientSizeInBytes, 1, 0, queryInfo->typeInfo.objectType, &var, &data, error) < 0) return DPI_FAILURE; if (dpiStmt__define(stmt, i + 1, var, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(var, error, -1); } var->error = error; if (stmt->fetchArraySize > var->buffer.maxArraySize) return dpiError__set(error, "check array size", DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize); if (var->requiresPreFetch && dpiVar__extendedPreFetch(var, &var->buffer, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiStmt__prepare() [INTERNAL] // Prepare a statement for execution. //----------------------------------------------------------------------------- int dpiStmt__prepare(dpiStmt *stmt, const char *sql, uint32_t sqlLength, const char *tag, uint32_t tagLength, dpiError *error) { if (sql && dpiDebugLevel & DPI_DEBUG_LEVEL_SQL) dpiDebug__print("SQL %.*s\n", sqlLength, sql); if (dpiOci__stmtPrepare2(stmt, sql, sqlLength, tag, tagLength, error) < 0) return DPI_FAILURE; if (dpiHandleList__addHandle(stmt->conn->openStmts, stmt, &stmt->openSlotNum, error) < 0) { dpiOci__stmtRelease(stmt, NULL, 0, 0, error); stmt->handle = NULL; return DPI_FAILURE; } return dpiStmt__init(stmt, error); } //----------------------------------------------------------------------------- // dpiStmt__reExecute() [INTERNAL] // Re-execute the statement after receiving the error ORA-01007: variable not // in select list. This takes place when one of the columns in a query is // dropped, but the original metadata is still being used because the query // statement was found in the statement cache. //----------------------------------------------------------------------------- static int dpiStmt__reExecute(dpiStmt *stmt, uint32_t numIters, uint32_t mode, dpiError *error) { void *origHandle, *newHandle; uint32_t sqlLength, i; dpiError localError; dpiBindVar *bindVar; dpiVar *var; int status; char *sql; // acquire the statement that was previously prepared; if this cannot be // determined, let the original error propagate localError.buffer = error->buffer; localError.env = error->env; localError.handle = error->handle; if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) &sql, &sqlLength, DPI_OCI_ATTR_STATEMENT, "get statement", &localError) < 0) return DPI_FAILURE; // prepare statement a second time before releasing the original statement; // release the original statement and delete it from the statement cache // so that it does not return with the invalid metadata; again, if this // cannot be done, let the original error propagate origHandle = stmt->handle; status = dpiOci__stmtPrepare2(stmt, sql, sqlLength, NULL, 0, &localError); newHandle = stmt->handle; stmt->handle = origHandle; stmt->deleteFromCache = 1; if (dpiOci__stmtRelease(stmt, NULL, 0, 1, &localError) < 0 || status < 0) return DPI_FAILURE; stmt->handle = newHandle; dpiStmt__clearBatchErrors(stmt); dpiStmt__clearQueryVars(stmt, error); // perform binds for (i = 0; i < stmt->numBindVars; i++) { bindVar = &stmt->bindVars[i]; if (!bindVar->var) continue; var = bindVar->var; bindVar->var = NULL; if (dpiStmt__bind(stmt, var, bindVar->pos, bindVar->name, bindVar->nameLength, error) < 0) { dpiGen__setRefCount(var, error, -1); return DPI_FAILURE; } } // now re-execute the statement return dpiStmt__execute(stmt, numIters, mode, 0, error); } //----------------------------------------------------------------------------- // dpiStmt_addRef() [PUBLIC] // Add a reference to the statement. //----------------------------------------------------------------------------- int dpiStmt_addRef(dpiStmt *stmt) { return dpiGen__addRef(stmt, DPI_HTYPE_STMT, __func__); } //----------------------------------------------------------------------------- // dpiStmt_bindByName() [PUBLIC] // Bind the variable by name. //----------------------------------------------------------------------------- int dpiStmt_bindByName(dpiStmt *stmt, const char *name, uint32_t nameLength, dpiVar *var) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, name) if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by name", &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); status = dpiStmt__bind(stmt, var, 0, name, nameLength, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_bindByPos() [PUBLIC] // Bind the variable by position. //----------------------------------------------------------------------------- int dpiStmt_bindByPos(dpiStmt *stmt, uint32_t pos, dpiVar *var) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "bind by pos", &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); status = dpiStmt__bind(stmt, var, pos, NULL, 0, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_bindValueByName() [PUBLIC] // Create a variable and bind it by name. //----------------------------------------------------------------------------- int dpiStmt_bindValueByName(dpiStmt *stmt, const char *name, uint32_t nameLength, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiVar *var = NULL; dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, name) DPI_CHECK_PTR_NOT_NULL(stmt, data) status = dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, 0, name, nameLength, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_bindValueByPos() [PUBLIC] // Create a variable and bind it by position. //----------------------------------------------------------------------------- int dpiStmt_bindValueByPos(dpiStmt *stmt, uint32_t pos, dpiNativeTypeNum nativeTypeNum, dpiData *data) { dpiVar *var = NULL; dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, data) status = dpiStmt__createBindVar(stmt, nativeTypeNum, data, &var, pos, NULL, 0, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_close() [PUBLIC] // Close the statement so that it is no longer usable and all resources have // been released. //----------------------------------------------------------------------------- int dpiStmt_close(dpiStmt *stmt, const char *tag, uint32_t tagLength) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(stmt, tag) status = dpiStmt__close(stmt, tag, tagLength, 1, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_define() [PUBLIC] // Define the variable that will accept output from the cursor in the // specified column. //----------------------------------------------------------------------------- int dpiStmt_define(dpiStmt *stmt, uint32_t pos, dpiVar *var) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (pos == 0 || pos > stmt->numQueryVars) { dpiError__set(&error, "check query position", DPI_ERR_QUERY_POSITION_INVALID, pos); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } if (dpiGen__checkHandle(var, DPI_HTYPE_VAR, "check variable", &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); status = dpiStmt__define(stmt, pos, var, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_defineValue() [PUBLIC] // Define the type of data to use for output from the cursor in the specified // column. This implicitly creates a variable of the specified type and is // intended for subsequent use by dpiStmt_getQueryValue(), which makes use of // implicitly created variables. //----------------------------------------------------------------------------- int dpiStmt_defineValue(dpiStmt *stmt, uint32_t pos, dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, uint32_t size, int sizeIsBytes, dpiObjectType *objType) { dpiError error; dpiData *data; dpiVar *var; // verify parameters if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (pos == 0 || pos > stmt->numQueryVars) { dpiError__set(&error, "check query position", DPI_ERR_QUERY_POSITION_INVALID, pos); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } // create a new variable of the specified type if (dpiVar__allocate(stmt->conn, oracleTypeNum, nativeTypeNum, stmt->fetchArraySize, size, sizeIsBytes, 0, objType, &var, &data, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (dpiStmt__define(stmt, pos, var, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); dpiGen__setRefCount(var, &error, -1); return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_execute() [PUBLIC] // Execute a statement. If the statement has been executed before, however, // and this is a query, the describe information is already available so defer // execution until the first fetch. //----------------------------------------------------------------------------- int dpiStmt_execute(dpiStmt *stmt, dpiExecMode mode, uint32_t *numQueryColumns) { uint32_t numIters; dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); numIters = (stmt->statementType == DPI_STMT_TYPE_SELECT) ? 0 : 1; if (dpiStmt__execute(stmt, numIters, mode, 1, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (numQueryColumns) *numQueryColumns = stmt->numQueryVars; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_executeMany() [PUBLIC] // Execute a statement multiple times. Queries are not supported. The bind // variables are checked to ensure that their maxArraySize is sufficient to // support this. //----------------------------------------------------------------------------- int dpiStmt_executeMany(dpiStmt *stmt, dpiExecMode mode, uint32_t numIters) { dpiError error; uint32_t i; // verify statement is open if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // queries are not supported if (stmt->statementType == DPI_STMT_TYPE_SELECT) { dpiError__set(&error, "check statement type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } // batch errors and array DML row counts are only supported with DML // statements (insert, update, delete and merge) if ((mode & DPI_MODE_EXEC_BATCH_ERRORS || mode & DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS) && stmt->statementType != DPI_STMT_TYPE_INSERT && stmt->statementType != DPI_STMT_TYPE_UPDATE && stmt->statementType != DPI_STMT_TYPE_DELETE && stmt->statementType != DPI_STMT_TYPE_MERGE) { dpiError__set(&error, "check mode", DPI_ERR_EXEC_MODE_ONLY_FOR_DML); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } // ensure that all bind variables have a big enough maxArraySize to // support this operation for (i = 0; i < stmt->numBindVars; i++) { if (stmt->bindVars[i].var->buffer.maxArraySize < numIters) { dpiError__set(&error, "check array size", DPI_ERR_ARRAY_SIZE_TOO_SMALL, stmt->bindVars[i].var->buffer.maxArraySize); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } } // perform execution dpiStmt__clearBatchErrors(stmt); if (dpiStmt__execute(stmt, numIters, mode, 0, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // handle batch errors if mode was specified if (mode & DPI_MODE_EXEC_BATCH_ERRORS) { if (dpiStmt__getBatchErrors(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_fetch() [PUBLIC] // Fetch a row from the database. //----------------------------------------------------------------------------- int dpiStmt_fetch(dpiStmt *stmt, int *found, uint32_t *bufferRowIndex) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, found) DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex) if (stmt->bufferRowIndex >= stmt->bufferRowCount) { if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (stmt->bufferRowIndex >= stmt->bufferRowCount) { *found = 0; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } } *found = 1; *bufferRowIndex = stmt->bufferRowIndex; stmt->bufferRowIndex++; stmt->rowCount++; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_fetchRows() [PUBLIC] // Fetch rows into buffers and return the number of rows that were so // fetched. If there are still rows available in the buffer, no additional // fetch will take place. //----------------------------------------------------------------------------- int dpiStmt_fetchRows(dpiStmt *stmt, uint32_t maxRows, uint32_t *bufferRowIndex, uint32_t *numRowsFetched, int *moreRows) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, bufferRowIndex) DPI_CHECK_PTR_NOT_NULL(stmt, numRowsFetched) DPI_CHECK_PTR_NOT_NULL(stmt, moreRows) if (stmt->bufferRowIndex >= stmt->bufferRowCount) { if (stmt->hasRowsToFetch && dpiStmt__fetch(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (stmt->bufferRowIndex >= stmt->bufferRowCount) { *moreRows = 0; *bufferRowIndex = 0; *numRowsFetched = 0; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } } *bufferRowIndex = stmt->bufferRowIndex; *numRowsFetched = stmt->bufferRowCount - stmt->bufferRowIndex; *moreRows = stmt->hasRowsToFetch; if (*numRowsFetched > maxRows) { *numRowsFetched = maxRows; *moreRows = 1; } stmt->bufferRowIndex += *numRowsFetched; stmt->rowCount += *numRowsFetched; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getBatchErrorCount() [PUBLIC] // Return the number of batch errors that took place during the last // execution of the statement. //----------------------------------------------------------------------------- int dpiStmt_getBatchErrorCount(dpiStmt *stmt, uint32_t *count) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, count) *count = stmt->numBatchErrors; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getBatchErrors() [PUBLIC] // Return the batch errors that took place during the last execution of the // statement. //----------------------------------------------------------------------------- int dpiStmt_getBatchErrors(dpiStmt *stmt, uint32_t numErrors, dpiErrorInfo *errors) { dpiError error, tempError; uint32_t i; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, errors) if (numErrors < stmt->numBatchErrors) { dpiError__set(&error, "check num errors", DPI_ERR_ARRAY_SIZE_TOO_SMALL, numErrors); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } for (i = 0; i < stmt->numBatchErrors; i++) { tempError.buffer = &stmt->batchErrors[i]; dpiError__getInfo(&tempError, &errors[i]); } return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getBindCount() [PUBLIC] // Return the number of bind variables referenced in the prepared SQL. In // SQL statements this counts all bind variables but in PL/SQL statements // this counts only uniquely named bind variables. //----------------------------------------------------------------------------- int dpiStmt_getBindCount(dpiStmt *stmt, uint32_t *count) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, count) status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, (void*) count, 0, DPI_OCI_ATTR_BIND_COUNT, "get bind count", &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_getBindNames() [PUBLIC] // Return the unique names of the bind variables referenced in the prepared // SQL. //----------------------------------------------------------------------------- int dpiStmt_getBindNames(dpiStmt *stmt, uint32_t *numBindNames, const char **bindNames, uint32_t *bindNameLengths) { uint8_t bindNameLengthsBuffer[8], indNameLengthsBuffer[8], isDuplicate[8]; uint32_t startLoc, i, numThisPass, numActualBindNames; char *bindNamesBuffer[8], *indNamesBuffer[8]; void *bindHandles[8]; int32_t numFound; dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, numBindNames) DPI_CHECK_PTR_NOT_NULL(stmt, bindNames) DPI_CHECK_PTR_NOT_NULL(stmt, bindNameLengths) startLoc = 1; numActualBindNames = 0; while (1) { if (dpiOci__stmtGetBindInfo(stmt, 8, startLoc, &numFound, bindNamesBuffer, bindNameLengthsBuffer, indNamesBuffer, indNameLengthsBuffer, isDuplicate, bindHandles, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (numFound == 0) break; numThisPass = abs(numFound) - startLoc + 1; if (numThisPass > 8) numThisPass = 8; for (i = 0; i < numThisPass; i++) { startLoc++; if (isDuplicate[i]) continue; if (numActualBindNames == *numBindNames) { dpiError__set(&error, "check num bind names", DPI_ERR_ARRAY_SIZE_TOO_SMALL, *numBindNames); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } bindNames[numActualBindNames] = bindNamesBuffer[i]; bindNameLengths[numActualBindNames] = bindNameLengthsBuffer[i]; numActualBindNames++; } if (numFound > 0) break; } *numBindNames = numActualBindNames; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getFetchArraySize() [PUBLIC] // Get the array size used for fetches. //----------------------------------------------------------------------------- int dpiStmt_getFetchArraySize(dpiStmt *stmt, uint32_t *arraySize) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, arraySize) *arraySize = stmt->fetchArraySize; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getImplicitResult() [PUBLIC] // Return the next implicit result from the previously executed statement. If // no more implicit results exist, NULL is returned. //----------------------------------------------------------------------------- int dpiStmt_getImplicitResult(dpiStmt *stmt, dpiStmt **implicitResult) { dpiStmt *tempStmt; dpiError error; void *handle; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, implicitResult) if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (dpiOci__stmtGetNextResult(stmt, &handle, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); *implicitResult = NULL; if (handle) { if (dpiStmt__allocate(stmt->conn, 0, &tempStmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); tempStmt->handle = handle; dpiGen__setRefCount(stmt, &error, 1); tempStmt->parentStmt = stmt; if (dpiStmt__createQueryVars(tempStmt, &error) < 0) { dpiStmt__free(tempStmt, &error); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } *implicitResult = tempStmt; } return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getInfo() [PUBLIC] // Return information about the statement in the provided structure. //----------------------------------------------------------------------------- int dpiStmt_getInfo(dpiStmt *stmt, dpiStmtInfo *info) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, info) info->isQuery = (stmt->statementType == DPI_STMT_TYPE_SELECT); info->isPLSQL = (stmt->statementType == DPI_STMT_TYPE_BEGIN || stmt->statementType == DPI_STMT_TYPE_DECLARE || stmt->statementType == DPI_STMT_TYPE_CALL); info->isDDL = (stmt->statementType == DPI_STMT_TYPE_CREATE || stmt->statementType == DPI_STMT_TYPE_DROP || stmt->statementType == DPI_STMT_TYPE_ALTER); info->isDML = (stmt->statementType == DPI_STMT_TYPE_INSERT || stmt->statementType == DPI_STMT_TYPE_UPDATE || stmt->statementType == DPI_STMT_TYPE_DELETE || stmt->statementType == DPI_STMT_TYPE_MERGE); info->statementType = stmt->statementType; info->isReturning = stmt->isReturning; if (stmt->env->context->dpiMinorVersion > 5) { info->sqlId = stmt->sqlId; info->sqlIdLength = stmt->sqlIdLength; } else { info->sqlId = NULL; info->sqlIdLength = 0; } return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getLastRowid() [PUBLIC] // Returns the rowid of the last row that was affected by a DML statement. If // no rows were affected by the last statement executed or the last statement // executed was not a DML statement, NULL is returned. //----------------------------------------------------------------------------- int dpiStmt_getLastRowid(dpiStmt *stmt, dpiRowid **rowid) { uint64_t rowCount; uint32_t tempSize; dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, rowid) *rowid = NULL; if (stmt->statementType == DPI_STMT_TYPE_INSERT || stmt->statementType == DPI_STMT_TYPE_UPDATE || stmt->statementType == DPI_STMT_TYPE_DELETE || stmt->statementType == DPI_STMT_TYPE_MERGE) { if (dpiStmt__getRowCount(stmt, &rowCount, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (rowCount > 0) { if (stmt->lastRowid) { dpiGen__setRefCount(stmt->lastRowid, &error, -1); stmt->lastRowid = NULL; } if (dpiRowid__allocate(stmt->conn, &stmt->lastRowid, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, stmt->lastRowid->handle, &tempSize, DPI_OCI_ATTR_ROWID, "get last rowid", &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (tempSize) *rowid = stmt->lastRowid; } } return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getNumQueryColumns() [PUBLIC] // Returns the number of query columns associated with a statement. If the // statement does not refer to a query, 0 is returned. //----------------------------------------------------------------------------- int dpiStmt_getNumQueryColumns(dpiStmt *stmt, uint32_t *numQueryColumns) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, numQueryColumns) if (stmt->statementType == DPI_STMT_TYPE_SELECT && stmt->numQueryVars == 0 && dpiStmt__createQueryVars(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); *numQueryColumns = stmt->numQueryVars; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getOciAttr() [PUBLIC] // Get the OCI attribute directly. This is intended for testing of attributes // not currently exposed by ODPI-C and should only be used for that purpose. //----------------------------------------------------------------------------- int dpiStmt_getOciAttr(dpiStmt *stmt, uint32_t attribute, dpiDataBuffer *value, uint32_t *valueLength) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, value) DPI_CHECK_PTR_NOT_NULL(stmt, valueLength) status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &value->asRaw, valueLength, attribute, "generic get OCI attribute", &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_getPrefetchRows() [PUBLIC] // Returns the number of rows that will be prefetched when a query is // executed. //----------------------------------------------------------------------------- int dpiStmt_getPrefetchRows(dpiStmt *stmt, uint32_t *numRows) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, numRows) *numRows = stmt->prefetchRows; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getQueryInfo() [PUBLIC] // Get query information for the position in question. //----------------------------------------------------------------------------- int dpiStmt_getQueryInfo(dpiStmt *stmt, uint32_t pos, dpiQueryInfo *info) { dpiError error; // validate parameters if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, info) if (!stmt->queryInfo && dpiStmt__createQueryVars(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (pos == 0 || pos > stmt->numQueryVars) { dpiError__set(&error, "check query position", DPI_ERR_QUERY_POSITION_INVALID, pos); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } // copy query information from internal cache // the size of the dpiDataTypeInfo structure changed in version 5.1 and // again in 5.2; this check and memcpy() for older versions can be removed // once 6.0 is released if (stmt->env->context->dpiMinorVersion > 1) { memcpy(info, &stmt->queryInfo[pos - 1], sizeof(dpiQueryInfo)); } else if (stmt->env->context->dpiMinorVersion == 1) { memcpy(info, &stmt->queryInfo[pos - 1], sizeof(dpiQueryInfo__v51)); } else { memcpy(info, &stmt->queryInfo[pos - 1], sizeof(dpiQueryInfo__v50)); } return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getQueryValue() [PUBLIC] // Get value from query at specified position. //----------------------------------------------------------------------------- int dpiStmt_getQueryValue(dpiStmt *stmt, uint32_t pos, dpiNativeTypeNum *nativeTypeNum, dpiData **data) { dpiError error; dpiVar *var; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, nativeTypeNum) DPI_CHECK_PTR_NOT_NULL(stmt, data) if (!stmt->queryVars) { dpiError__set(&error, "check query vars", DPI_ERR_QUERY_NOT_EXECUTED); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } if (pos == 0 || pos > stmt->numQueryVars) { dpiError__set(&error, "check query position", DPI_ERR_QUERY_POSITION_INVALID, pos); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } var = stmt->queryVars[pos - 1]; if (!var || stmt->bufferRowIndex == 0 || stmt->bufferRowIndex > stmt->bufferRowCount) { dpiError__set(&error, "check fetched row", DPI_ERR_NO_ROW_FETCHED); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } *nativeTypeNum = var->nativeTypeNum; *data = &var->buffer.externalData[stmt->bufferRowIndex - 1]; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_getRowCount() [PUBLIC] // Return the number of rows affected by the last DML executed (for insert, // update, delete and merge) or the number of rows fetched (for queries). In // all other cases, 0 is returned. //----------------------------------------------------------------------------- int dpiStmt_getRowCount(dpiStmt *stmt, uint64_t *count) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, count) status = dpiStmt__getRowCount(stmt, count, &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_getRowCounts() [PUBLIC] // Return the number of rows affected by each of the iterations executed // using dpiStmt_executeMany(). //----------------------------------------------------------------------------- int dpiStmt_getRowCounts(dpiStmt *stmt, uint32_t *numRowCounts, uint64_t **rowCounts) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, numRowCounts) DPI_CHECK_PTR_NOT_NULL(stmt, rowCounts) if (dpiUtils__checkClientVersion(stmt->env->versionInfo, 12, 1, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, rowCounts, numRowCounts, DPI_OCI_ATTR_DML_ROW_COUNT_ARRAY, "get row counts", &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_getSubscrQueryId() [PUBLIC] // Return the query id for a query registered using this statement. //----------------------------------------------------------------------------- int dpiStmt_getSubscrQueryId(dpiStmt *stmt, uint64_t *queryId) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, queryId) status = dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, queryId, 0, DPI_OCI_ATTR_CQ_QUERYID, "get query id", &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_release() [PUBLIC] // Release a reference to the statement. //----------------------------------------------------------------------------- int dpiStmt_release(dpiStmt *stmt) { return dpiGen__release(stmt, DPI_HTYPE_STMT, __func__); } //----------------------------------------------------------------------------- // dpiStmt_scroll() [PUBLIC] // Scroll to the specified location in the cursor. //----------------------------------------------------------------------------- int dpiStmt_scroll(dpiStmt *stmt, dpiFetchMode mode, int32_t offset, int32_t rowCountOffset) { uint32_t numRows, currentPosition; uint64_t desiredRow = 0; dpiError error; // make sure the cursor is open if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // validate mode; determine desired row to fetch switch (mode) { case DPI_MODE_FETCH_NEXT: desiredRow = stmt->rowCount + rowCountOffset + 1; break; case DPI_MODE_FETCH_PRIOR: desiredRow = stmt->rowCount + rowCountOffset - 1; break; case DPI_MODE_FETCH_FIRST: desiredRow = 1; break; case DPI_MODE_FETCH_LAST: break; case DPI_MODE_FETCH_ABSOLUTE: desiredRow = (uint64_t) offset; break; case DPI_MODE_FETCH_RELATIVE: desiredRow = stmt->rowCount + rowCountOffset + offset; offset = (int32_t) (desiredRow - (stmt->bufferMinRow + stmt->bufferRowCount - 1)); break; default: dpiError__set(&error, "scroll mode", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } // if the desired row is less than 1 we have gone outside the result set if (desiredRow < 1 && mode != DPI_MODE_FETCH_LAST) { stmt->bufferRowCount = 0; dpiError__set(&error, "check result set bounds", DPI_ERR_SCROLL_OUT_OF_RS); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } // determine if a fetch is actually required; "last" is always fetched if (mode != DPI_MODE_FETCH_LAST && desiredRow >= stmt->bufferMinRow && desiredRow < stmt->bufferMinRow + stmt->bufferRowCount) { stmt->bufferRowIndex = (uint32_t) (desiredRow - stmt->bufferMinRow); stmt->rowCount = desiredRow - 1; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } // perform any pre-fetch activities required if (dpiStmt__beforeFetch(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // perform fetch; when fetching the last row, only fetch a single row numRows = (mode == DPI_MODE_FETCH_LAST) ? 1 : stmt->fetchArraySize; if (dpiOci__stmtFetch2(stmt, numRows, mode, offset, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // determine the number of rows actually fetched if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, &stmt->bufferRowCount, 0, DPI_OCI_ATTR_ROWS_FETCHED, "get rows fetched", &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // check that we haven't gone outside of the result set if (stmt->bufferRowCount == 0) { if (mode != DPI_MODE_FETCH_FIRST && mode != DPI_MODE_FETCH_LAST) { dpiError__set(&error, "check result set bounds", DPI_ERR_SCROLL_OUT_OF_RS); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } stmt->hasRowsToFetch = 0; stmt->rowCount = 0; stmt->bufferRowIndex = 0; stmt->bufferMinRow = 0; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } // determine the current position of the cursor if (dpiOci__attrGet(stmt->handle, DPI_OCI_HTYPE_STMT, ¤tPosition, 0, DPI_OCI_ATTR_CURRENT_POSITION, "get current pos", &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); // reset buffer row index and row count stmt->rowCount = currentPosition - stmt->bufferRowCount; stmt->bufferMinRow = stmt->rowCount + 1; stmt->bufferRowIndex = 0; // perform post-fetch activities required if (dpiStmt__postFetch(stmt, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_setFetchArraySize() [PUBLIC] // Set the array size used for fetches. Using a value of zero will select the // default value. A check is made to ensure that all defined variables have // sufficient space to support the array size. //----------------------------------------------------------------------------- int dpiStmt_setFetchArraySize(dpiStmt *stmt, uint32_t arraySize) { dpiError error; dpiVar *var; uint32_t i; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); if (arraySize == 0) arraySize = DPI_DEFAULT_FETCH_ARRAY_SIZE; for (i = 0; i < stmt->numQueryVars; i++) { var = stmt->queryVars[i]; if (var && var->buffer.maxArraySize < arraySize) { dpiError__set(&error, "check array size", DPI_ERR_ARRAY_SIZE_TOO_BIG, arraySize); return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); } } stmt->fetchArraySize = arraySize; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_setOciAttr() [PUBLIC] // Set the OCI attribute directly. This is intended for testing of attributes // not currently exposed by ODPI-C and should only be used for that purpose. //----------------------------------------------------------------------------- int dpiStmt_setOciAttr(dpiStmt *stmt, uint32_t attribute, void *value, uint32_t valueLength) { dpiError error; int status; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(stmt, value) status = dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, value, valueLength, attribute, "generic set OCI attribute", &error); return dpiGen__endPublicFn(stmt, status, &error); } //----------------------------------------------------------------------------- // dpiStmt_setPrefetchRows() [PUBLIC] // Set the number of rows to prefetch when a query is executed. //----------------------------------------------------------------------------- int dpiStmt_setPrefetchRows(dpiStmt *stmt, uint32_t numRows) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); stmt->prefetchRows = numRows; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiStmt_deleteFromCache() [PUBLIC] // Excludes the associated SQL statement from the statement cache. If the SQL // statment was not already in the cache, it will not be added. //----------------------------------------------------------------------------- int dpiStmt_deleteFromCache(dpiStmt *stmt) { dpiError error; if (dpiStmt__check(stmt, __func__, &error) < 0) return dpiGen__endPublicFn(stmt, DPI_FAILURE, &error); stmt->deleteFromCache = 1; return dpiGen__endPublicFn(stmt, DPI_SUCCESS, &error); } odpi-5.6.4/src/dpiStringList.c000066400000000000000000000101751510466437300162300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2023, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiStringList.c // Implementation of a list of strings. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiStringList__free() [INTERNAL] // Frees the memory associated with the string list. Note that the strings // themselves are stored in one contiguous block pointed to by the first // string. //----------------------------------------------------------------------------- void dpiStringList__free(dpiStringList *list) { uint32_t i; if (list->strings) { for (i = 0; i < list->numStrings; i++) dpiUtils__freeMemory((void*) list->strings[i]); dpiUtils__freeMemory((void*) list->strings); list->strings = NULL; } if (list->stringLengths) { dpiUtils__freeMemory(list->stringLengths); list->stringLengths = NULL; } list->numStrings = 0; } //----------------------------------------------------------------------------- // dpiStringList__addElement() [INTERNAL] // Adds an element to the list, allocating additional space if needed. The // memory accounting is done independently so that it does not need to be // present in the public structure. //----------------------------------------------------------------------------- int dpiStringList__addElement(dpiStringList *list, const char *value, uint32_t valueLength, uint32_t *numStringsAllocated, dpiError *error) { uint32_t *tempStringLengths; char **tempStrings; char *ptr; // allocate more space in the array, if needed if (*numStringsAllocated <= list->numStrings) { *numStringsAllocated += 64; if (dpiUtils__allocateMemory(*numStringsAllocated, sizeof(uint32_t), 0, "allocate lengths array", (void**) &tempStringLengths, error) < 0) return DPI_FAILURE; if (list->stringLengths) { memcpy(tempStringLengths, list->stringLengths, list->numStrings * sizeof(uint32_t)); dpiUtils__freeMemory(list->stringLengths); } list->stringLengths = tempStringLengths; if (dpiUtils__allocateMemory(*numStringsAllocated, sizeof(char*), 0, "allocate strings array", (void**) &tempStrings, error) < 0) return DPI_FAILURE; if (list->strings) { memcpy(tempStrings, list->strings, list->numStrings * sizeof(char*)); dpiUtils__freeMemory((void*) list->strings); } list->strings = (const char**) tempStrings; } // add a copy of the string to the list if (dpiUtils__allocateMemory(valueLength, 1, 0, "allocate string", (void**) &ptr, error) < 0) return DPI_FAILURE; memcpy(ptr, value, valueLength); list->strings[list->numStrings] = ptr; list->stringLengths[list->numStrings] = valueLength; list->numStrings++; return DPI_SUCCESS; } odpi-5.6.4/src/dpiSubscr.c000066400000000000000000000711411510466437300153670ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiSubscr.c // Implementation of subscriptions (CQN). //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static void dpiSubscr__freeMessage(dpiSubscrMessage *message); static int dpiSubscr__populateMessage(dpiSubscr *subscr, dpiSubscrMessage *message, void *descriptor, dpiError *error); static int dpiSubscr__populateMessageTable(dpiSubscr *subscr, dpiSubscrMessageTable *table, void *descriptor, dpiError *error); static int dpiSubscr__populateQueryChangeMessage(dpiSubscr *subscr, dpiSubscrMessage *message, void *descriptor, dpiError *error); //----------------------------------------------------------------------------- // dpiSubscr__callback() [INTERNAL] // Callback that is used to execute the callback registered when the // subscription was created. //----------------------------------------------------------------------------- static void dpiSubscr__callback(dpiSubscr *subscr, UNUSED void *handle, UNUSED void *payload, UNUSED uint32_t payloadLength, void *descriptor, UNUSED uint32_t mode) { dpiSubscrMessage message; dpiErrorInfo errorInfo; dpiError error; // ensure that the subscription handle is still valid if (dpiGen__startPublicFn(subscr, DPI_HTYPE_SUBSCR, __func__, &error) < 0) { dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); return; } // if the subscription is no longer registered, nothing further to do dpiMutex__acquire(subscr->mutex); if (!subscr->registered) { dpiMutex__release(subscr->mutex); dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); return; } // populate message memset(&message, 0, sizeof(message)); if (dpiSubscr__populateMessage(subscr, &message, descriptor, &error) < 0) { dpiError__getInfo(&error, &errorInfo); message.errorInfo = &errorInfo; } message.registered = subscr->registered; // invoke user callback; temporarily increase reference count to ensure // that the subscription is not freed during the callback dpiGen__setRefCount(subscr, &error, 1); (*subscr->callback)(subscr->callbackContext, &message); dpiSubscr__freeMessage(&message); dpiMutex__release(subscr->mutex); dpiGen__setRefCount(subscr, &error, -1); dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSubscr__check() [INTERNAL] // Determine if the subscription is open and available for use. //----------------------------------------------------------------------------- static int dpiSubscr__check(dpiSubscr *subscr, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(subscr, DPI_HTYPE_SUBSCR, fnName, error) < 0) return DPI_FAILURE; if (!subscr->handle) return dpiError__set(error, "check closed", DPI_ERR_SUBSCR_CLOSED); return dpiConn__checkConnected(subscr->conn, error); } //----------------------------------------------------------------------------- // dpiSubscr__create() [INTERNAL] // Create a new subscription structure and return it. In case of error NULL // is returned. //----------------------------------------------------------------------------- int dpiSubscr__create(dpiSubscr *subscr, dpiConn *conn, dpiSubscrCreateParams *params, dpiError *error) { uint32_t qosFlags, mode; int32_t int32Val; int rowids; // retain a reference to the connection dpiGen__setRefCount(conn, error, 1); subscr->conn = conn; subscr->callback = params->callback; subscr->callbackContext = params->callbackContext; subscr->subscrNamespace = params->subscrNamespace; subscr->qos = params->qos; subscr->clientInitiated = params->clientInitiated; dpiMutex__initialize(subscr->mutex); // create the subscription handle if (dpiOci__handleAlloc(conn->env->handle, &subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, "create subscr handle", error) < 0) return DPI_FAILURE; // set the namespace if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->subscrNamespace, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_NAMESPACE, "set namespace", error) < 0) return DPI_FAILURE; // set the protocol if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->protocol, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_RECPTPROTO, "set protocol", error) < 0) return DPI_FAILURE; // set the timeout if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->timeout, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_TIMEOUT, "set timeout", error) < 0) return DPI_FAILURE; // set the IP address used on the client to listen for events if (params->ipAddress && params->ipAddressLength > 0 && dpiOci__attrSet(subscr->env->handle, DPI_OCI_HTYPE_ENV, (void*) params->ipAddress, params->ipAddressLength, DPI_OCI_ATTR_SUBSCR_IPADDR, "set IP address", error) < 0) return DPI_FAILURE; // set the port number used on the client to listen for events if (params->portNumber > 0 && dpiOci__attrSet(subscr->env->handle, DPI_OCI_HTYPE_ENV, (void*) ¶ms->portNumber, 0, DPI_OCI_ATTR_SUBSCR_PORTNO, "set port number", error) < 0) return DPI_FAILURE; // set the context for the callback if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) subscr, 0, DPI_OCI_ATTR_SUBSCR_CTX, "set callback context", error) < 0) return DPI_FAILURE; // set the callback, if applicable if (params->callback && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) dpiSubscr__callback, 0, DPI_OCI_ATTR_SUBSCR_CALLBACK, "set callback", error) < 0) return DPI_FAILURE; // set the subscription name, if applicable if (params->name && params->nameLength > 0 && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) params->name, params->nameLength, DPI_OCI_ATTR_SUBSCR_NAME, "set name", error) < 0) return DPI_FAILURE; // set QOS flags qosFlags = 0; if (params->qos & DPI_SUBSCR_QOS_RELIABLE) qosFlags |= DPI_OCI_SUBSCR_QOS_RELIABLE; if (params->qos & DPI_SUBSCR_QOS_DEREG_NFY) qosFlags |= DPI_OCI_SUBSCR_QOS_PURGE_ON_NTFN; if (qosFlags && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) &qosFlags, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_QOSFLAGS, "set QOS", error) < 0) return DPI_FAILURE; // set CQ specific QOS flags qosFlags = 0; if (params->qos & DPI_SUBSCR_QOS_QUERY) qosFlags |= DPI_OCI_SUBSCR_CQ_QOS_QUERY; if (params->qos & DPI_SUBSCR_QOS_BEST_EFFORT) qosFlags |= DPI_OCI_SUBSCR_CQ_QOS_BEST_EFFORT; if (qosFlags && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) &qosFlags, sizeof(uint32_t), DPI_OCI_ATTR_SUBSCR_CQ_QOSFLAGS, "set CQ QOS", error) < 0) return DPI_FAILURE; // set rowids flag, if applicable if (params->qos & DPI_SUBSCR_QOS_ROWIDS) { rowids = 1; if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) &rowids, 0, DPI_OCI_ATTR_CHNF_ROWIDS, "set rowids flag", error) < 0) return DPI_FAILURE; } // set which operations are desired, if applicable if (params->operations && dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->operations, 0, DPI_OCI_ATTR_CHNF_OPERATIONS, "set operations", error) < 0) return DPI_FAILURE; // set grouping information, if applicable if (params->groupingClass) { // set grouping class if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->groupingClass, 0, DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_CLASS, "set grouping class", error) < 0) return DPI_FAILURE; // set grouping value if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->groupingValue, 0, DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_VALUE, "set grouping value", error) < 0) return DPI_FAILURE; // set grouping type if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) ¶ms->groupingType, 0, DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_TYPE, "set grouping type", error) < 0) return DPI_FAILURE; // set grouping repeat count int32Val = DPI_SUBSCR_GROUPING_FOREVER; if (dpiOci__attrSet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, (void*) &int32Val, 0, DPI_OCI_ATTR_SUBSCR_NTFN_GROUPING_REPEAT_COUNT, "set grouping repeat count", error) < 0) return DPI_FAILURE; } // register the subscription; client initiated subscriptions are only valid // with 19.4 client and database mode = DPI_OCI_DEFAULT; if (params->clientInitiated) { if (dpiUtils__checkClientVersion(conn->env->versionInfo, 19, 4, error) < 0) return DPI_FAILURE; if (dpiUtils__checkDatabaseVersion(conn, 19, 4, error) < 0) return DPI_FAILURE; mode = DPI_OCI_SECURE_NOTIFICATION; } if (dpiOci__subscriptionRegister(conn, &subscr->handle, mode, error) < 0) return DPI_FAILURE; subscr->registered = 1; // acquire the registration id, if applicable; for AQ, the value is always // set to zero if (params->subscrNamespace == DPI_SUBSCR_NAMESPACE_AQ) { params->outRegId = 0; } else { if (dpiOci__attrGet(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION, ¶ms->outRegId, NULL, DPI_OCI_ATTR_SUBSCR_CQ_REGID, "get registration id", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__free() [INTERNAL] // Free the memory and any resources associated with the subscription. //----------------------------------------------------------------------------- void dpiSubscr__free(dpiSubscr *subscr, dpiError *error) { dpiMutex__acquire(subscr->mutex); if (subscr->handle) { if (subscr->registered) dpiOci__subscriptionUnRegister(subscr->conn, subscr, error); dpiOci__handleFree(subscr->handle, DPI_OCI_HTYPE_SUBSCRIPTION); subscr->handle = NULL; } if (subscr->conn) { dpiGen__setRefCount(subscr->conn, error, -1); subscr->conn = NULL; } dpiMutex__release(subscr->mutex); dpiMutex__destroy(subscr->mutex); dpiUtils__freeMemory(subscr); } //----------------------------------------------------------------------------- // dpiSubscr__freeMessage() [INTERNAL] // Free memory associated with the message. //----------------------------------------------------------------------------- static void dpiSubscr__freeMessage(dpiSubscrMessage *message) { dpiSubscrMessageQuery *query; uint32_t i, j; // free the tables for the message if (message->numTables > 0) { for (i = 0; i < message->numTables; i++) { if (message->tables[i].numRows > 0) dpiUtils__freeMemory(message->tables[i].rows); } dpiUtils__freeMemory(message->tables); } // free the queries for the message if (message->numQueries > 0) { for (i = 0; i < message->numQueries; i++) { query = &message->queries[i]; if (query->numTables > 0) { for (j = 0; j < query->numTables; j++) { if (query->tables[j].numRows > 0) dpiUtils__freeMemory(query->tables[j].rows); } dpiUtils__freeMemory(query->tables); } } dpiUtils__freeMemory(message->queries); } } //----------------------------------------------------------------------------- // dpiSubscr__populateAQMessage() [INTERNAL] // Populate message with details. //----------------------------------------------------------------------------- static int dpiSubscr__populateAQMessage(dpiSubscr *subscr, dpiSubscrMessage *message, void *descriptor, dpiError *error) { uint32_t flags = 0; void *rawValue; // determine if message is a deregistration message if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, &flags, NULL, DPI_OCI_ATTR_NFY_FLAGS, "get flags", error) < 0) return DPI_FAILURE; message->eventType = (flags == 1) ? DPI_EVENT_DEREG : DPI_EVENT_AQ; if (message->eventType == DPI_EVENT_DEREG) { subscr->registered = 0; return DPI_SUCCESS; } // determine the name of the queue which spawned the event if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, (void*) &message->queueName, &message->queueNameLength, DPI_OCI_ATTR_QUEUE_NAME, "get queue name", error) < 0) return DPI_FAILURE; // determine the consumer name for the queue that spawned the event if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, (void*) &message->consumerName, &message->consumerNameLength, DPI_OCI_ATTR_CONSUMER_NAME, "get consumer name", error) < 0) return DPI_FAILURE; // determine the msgid of the message of queue that spawned the event if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_AQNFY_DESCRIPTOR, &rawValue, NULL, DPI_OCI_ATTR_NFY_MSGID, "get message id", error) < 0) return DPI_FAILURE; dpiOci__rawPtr(subscr->env->handle, rawValue, (void**) &message->aqMsgId); dpiOci__rawSize(subscr->env->handle, rawValue, &message->aqMsgIdLength); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__populateObjectChangeMessage() [INTERNAL] // Populate object change message with details. //----------------------------------------------------------------------------- static int dpiSubscr__populateObjectChangeMessage(dpiSubscr *subscr, dpiSubscrMessage *message, void *descriptor, dpiError *error) { void **tableDescriptor, *indicator; int32_t numTables; void *tables; uint32_t i; int exists; // determine table collection if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &tables, 0, DPI_OCI_ATTR_CHDES_TABLE_CHANGES, "get tables", error) < 0) return DPI_FAILURE; if (!tables) return DPI_SUCCESS; // determine number of tables if (dpiOci__collSize(subscr->conn, tables, &numTables, error) < 0) return DPI_FAILURE; // allocate memory for table entries if (dpiUtils__allocateMemory((size_t) numTables, sizeof(dpiSubscrMessageTable), 1, "allocate msg tables", (void**) &message->tables, error) < 0) return DPI_FAILURE; message->numTables = (uint32_t) numTables; // populate message table entries for (i = 0; i < message->numTables; i++) { if (dpiOci__collGetElem(subscr->conn, tables, (int32_t) i, &exists, (void**) &tableDescriptor, &indicator, error) < 0) return DPI_FAILURE; if (dpiSubscr__populateMessageTable(subscr, &message->tables[i], *tableDescriptor, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__populateMessage() [INTERNAL] // Populate message with details. //----------------------------------------------------------------------------- static int dpiSubscr__populateMessage(dpiSubscr *subscr, dpiSubscrMessage *message, void *descriptor, dpiError *error) { void *rawValue; // if quality of service flag indicates that deregistration should take // place when the first notification is received, mark the subscription // as no longer registered if (subscr->qos & DPI_SUBSCR_QOS_DEREG_NFY) subscr->registered = 0; // handle AQ messages, if applicable if (subscr->subscrNamespace == DPI_SUBSCR_NAMESPACE_AQ) return dpiSubscr__populateAQMessage(subscr, message, descriptor, error); // determine the type of event that was spawned if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &message->eventType, NULL, DPI_OCI_ATTR_CHDES_NFYTYPE, "get event type", error) < 0) return DPI_FAILURE; // determine the name of the database which spawned the event if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, (void*) &message->dbName, &message->dbNameLength, DPI_OCI_ATTR_CHDES_DBNAME, "get DB name", error) < 0) return DPI_FAILURE; // determine the id of the transaction which spawned the event if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &rawValue, NULL, DPI_OCI_ATTR_CHDES_XID, "get transaction id", error) < 0) return DPI_FAILURE; dpiOci__rawPtr(subscr->env->handle, rawValue, (void**) &message->txId); dpiOci__rawSize(subscr->env->handle, rawValue, &message->txIdLength); // populate event specific attributes switch (message->eventType) { case DPI_EVENT_OBJCHANGE: return dpiSubscr__populateObjectChangeMessage(subscr, message, descriptor, error); case DPI_EVENT_QUERYCHANGE: return dpiSubscr__populateQueryChangeMessage(subscr, message, descriptor, error); case DPI_EVENT_DEREG: subscr->registered = 0; break; case DPI_EVENT_STARTUP: case DPI_EVENT_SHUTDOWN: case DPI_EVENT_SHUTDOWN_ANY: break; default: return dpiError__set(error, "event type", DPI_ERR_NOT_SUPPORTED); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__populateMessageQuery() [INTERNAL] // Populate a message query structure from the OCI descriptor. //----------------------------------------------------------------------------- static int dpiSubscr__populateMessageQuery(dpiSubscr *subscr, dpiSubscrMessageQuery *query, void *descriptor, dpiError *error) { void **tableDescriptor, *indicator, *tables; int32_t numTables; uint32_t i; int exists; // determine query id if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &query->id, 0, DPI_OCI_ATTR_CQDES_QUERYID, "get id", error) < 0) return DPI_FAILURE; // determine operation if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &query->operation, 0, DPI_OCI_ATTR_CQDES_OPERATION, "get operation", error) < 0) return DPI_FAILURE; // determine table collection if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CQDES, &tables, 0, DPI_OCI_ATTR_CQDES_TABLE_CHANGES, "get table descriptor", error) < 0) return DPI_FAILURE; if (!tables) return DPI_SUCCESS; // determine number of tables if (dpiOci__collSize(subscr->conn, tables, &numTables, error) < 0) return DPI_FAILURE; // allocate memory for table entries if (dpiUtils__allocateMemory((size_t) numTables, sizeof(dpiSubscrMessageTable), 1, "allocate query tables", (void**) &query->tables, error) < 0) return DPI_FAILURE; query->numTables = (uint32_t) numTables; // populate message table entries for (i = 0; i < query->numTables; i++) { if (dpiOci__collGetElem(subscr->conn, tables, (int32_t) i, &exists, (void**) &tableDescriptor, &indicator, error) < 0) return DPI_FAILURE; if (dpiSubscr__populateMessageTable(subscr, &query->tables[i], *tableDescriptor, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__populateMessageRow() [INTERNAL] // Populate a message row structure from the OCI descriptor. //----------------------------------------------------------------------------- static int dpiSubscr__populateMessageRow(dpiSubscrMessageRow *row, void *descriptor, dpiError *error) { // determine operation if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_ROW_CHDES, &row->operation, 0, DPI_OCI_ATTR_CHDES_ROW_OPFLAGS, "get operation", error) < 0) return DPI_FAILURE; // determine rowid if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_ROW_CHDES, (void*) &row->rowid, &row->rowidLength, DPI_OCI_ATTR_CHDES_ROW_ROWID, "get rowid", error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__populateMessageTable() [INTERNAL] // Populate a message table structure from the OCI descriptor. //----------------------------------------------------------------------------- static int dpiSubscr__populateMessageTable(dpiSubscr *subscr, dpiSubscrMessageTable *table, void *descriptor, dpiError *error) { void **rowDescriptor, *indicator, *rows; int32_t numRows; int exists; uint32_t i; // determine operation if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, &table->operation, 0, DPI_OCI_ATTR_CHDES_TABLE_OPFLAGS, "get operation", error) < 0) return DPI_FAILURE; // determine table name if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, (void*) &table->name, &table->nameLength, DPI_OCI_ATTR_CHDES_TABLE_NAME, "get table name", error) < 0) return DPI_FAILURE; // if change invalidated all rows, nothing to do if (table->operation & DPI_OPCODE_ALL_ROWS) return DPI_SUCCESS; // determine rows collection if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_TABLE_CHDES, &rows, 0, DPI_OCI_ATTR_CHDES_TABLE_ROW_CHANGES, "get rows descriptor", error) < 0) return DPI_FAILURE; // determine number of rows in collection if (dpiOci__collSize(subscr->conn, rows, &numRows, error) < 0) return DPI_FAILURE; // allocate memory for row entries if (dpiUtils__allocateMemory((size_t) numRows, sizeof(dpiSubscrMessageRow), 1, "allocate rows", (void**) &table->rows, error) < 0) return DPI_FAILURE; table->numRows = (uint32_t) numRows; // populate the rows attribute for (i = 0; i < table->numRows; i++) { if (dpiOci__collGetElem(subscr->conn, rows, (int32_t) i, &exists, (void**) &rowDescriptor, &indicator, error) < 0) return DPI_FAILURE; if (dpiSubscr__populateMessageRow(&table->rows[i], *rowDescriptor, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__populateQueryChangeMessage() [INTERNAL] // Populate query change message with details. //----------------------------------------------------------------------------- static int dpiSubscr__populateQueryChangeMessage(dpiSubscr *subscr, dpiSubscrMessage *message, void *descriptor, dpiError *error) { void **queryDescriptor, *indicator, *queries; int32_t numQueries; int exists; uint32_t i; // determine query collection if (dpiOci__attrGet(descriptor, DPI_OCI_DTYPE_CHDES, &queries, 0, DPI_OCI_ATTR_CHDES_QUERIES, "get queries", error) < 0) return DPI_FAILURE; if (!queries) return DPI_SUCCESS; // determine number of queries if (dpiOci__collSize(subscr->conn, queries, &numQueries, error) < 0) return DPI_FAILURE; // allocate memory for query entries if (dpiUtils__allocateMemory((size_t) numQueries, sizeof(dpiSubscrMessageQuery), 1, "allocate queries", (void**) &message->queries, error) < 0) return DPI_FAILURE; message->numQueries = (uint32_t) numQueries; // populate each entry with a message query instance for (i = 0; i < message->numQueries; i++) { if (dpiOci__collGetElem(subscr->conn, queries, (int32_t) i, &exists, (void**) &queryDescriptor, &indicator, error) < 0) return DPI_FAILURE; if (dpiSubscr__populateMessageQuery(subscr, &message->queries[i], *queryDescriptor, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiSubscr__prepareStmt() [INTERNAL] // Internal method for preparing statement against a subscription. This // allows for normal error processing without having to worry about freeing the // statement for every error that might take place. //----------------------------------------------------------------------------- static int dpiSubscr__prepareStmt(dpiSubscr *subscr, dpiStmt *stmt, const char *sql, uint32_t sqlLength, dpiError *error) { // prepare statement for execution; only SELECT statements are supported if (dpiStmt__prepare(stmt, sql, sqlLength, NULL, 0, error) < 0) return DPI_FAILURE; if (stmt->statementType != DPI_STMT_TYPE_SELECT) return dpiError__set(error, "subscr prepare statement", DPI_ERR_NOT_SUPPORTED); // fetch array size is set to 1 in order to avoid over allocation since // the query is not really going to be used for fetching rows, just for // registration stmt->fetchArraySize = 1; // set subscription handle return dpiOci__attrSet(stmt->handle, DPI_OCI_HTYPE_STMT, subscr->handle, 0, DPI_OCI_ATTR_CHNF_REGHANDLE, "set subscription handle", error); } //----------------------------------------------------------------------------- // dpiSubscr_addRef() [PUBLIC] // Add a reference to the subscription. //----------------------------------------------------------------------------- int dpiSubscr_addRef(dpiSubscr *subscr) { return dpiGen__addRef(subscr, DPI_HTYPE_SUBSCR, __func__); } //----------------------------------------------------------------------------- // dpiSubscr_prepareStmt() [PUBLIC] // Prepare statement for registration with subscription. //----------------------------------------------------------------------------- int dpiSubscr_prepareStmt(dpiSubscr *subscr, const char *sql, uint32_t sqlLength, dpiStmt **stmt) { dpiStmt *tempStmt; dpiError error; if (dpiSubscr__check(subscr, __func__, &error) < 0) return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(subscr, sql) DPI_CHECK_PTR_NOT_NULL(subscr, stmt) if (dpiStmt__allocate(subscr->conn, 0, &tempStmt, &error) < 0) return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); if (dpiSubscr__prepareStmt(subscr, tempStmt, sql, sqlLength, &error) < 0) { dpiStmt__free(tempStmt, &error); return dpiGen__endPublicFn(subscr, DPI_FAILURE, &error); } *stmt = tempStmt; return dpiGen__endPublicFn(subscr, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiSubscr_release() [PUBLIC] // Release a reference to the subscription. //----------------------------------------------------------------------------- int dpiSubscr_release(dpiSubscr *subscr) { return dpiGen__release(subscr, DPI_HTYPE_SUBSCR, __func__); } odpi-5.6.4/src/dpiUtils.c000066400000000000000000000625161510466437300152340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiUtils.c // Utility methods that aren't specific to a particular type. //----------------------------------------------------------------------------- #include "dpiImpl.h" //----------------------------------------------------------------------------- // dpiUtils__allocateMemory() [INTERNAL] // Method for allocating memory which permits tracing and populates the error // structure in the event of a memory allocation failure. //----------------------------------------------------------------------------- int dpiUtils__allocateMemory(size_t numMembers, size_t memberSize, int clearMemory, const char *action, void **ptr, dpiError *error) { if (clearMemory) *ptr = calloc(numMembers, memberSize); else *ptr = malloc(numMembers * memberSize); if (!*ptr) return dpiError__set(error, action, DPI_ERR_NO_MEMORY); if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) dpiDebug__print("allocated %u bytes at %p (%s)\n", numMembers * memberSize, *ptr, action); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__checkClientVersion() [INTERNAL] // Check the Oracle Client version and verify that it is at least at the // minimum version that is required. //----------------------------------------------------------------------------- int dpiUtils__checkClientVersion(dpiVersionInfo *versionInfo, int minVersionNum, int minReleaseNum, dpiError *error) { if (versionInfo->versionNum < minVersionNum || (versionInfo->versionNum == minVersionNum && versionInfo->releaseNum < minReleaseNum)) return dpiError__set(error, "check Oracle Client version", DPI_ERR_ORACLE_CLIENT_TOO_OLD, versionInfo->versionNum, versionInfo->releaseNum, minVersionNum, minReleaseNum); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__checkClientVersionMulti() [INTERNAL] // Check the Oracle Client version and verify that it is at least at the // minimum version that is required. //----------------------------------------------------------------------------- int dpiUtils__checkClientVersionMulti(dpiVersionInfo *versionInfo, int minVersionNum1, int minReleaseNum1, int minVersionNum2, int minReleaseNum2, dpiError *error) { if (versionInfo->versionNum < minVersionNum1 || (versionInfo->versionNum == minVersionNum1 && versionInfo->releaseNum < minReleaseNum1) || (versionInfo->versionNum > minVersionNum1 && versionInfo->versionNum < minVersionNum2) || (versionInfo->versionNum == minVersionNum2 && versionInfo->releaseNum < minReleaseNum2)) return dpiError__set(error, "check Oracle Client version", DPI_ERR_ORACLE_CLIENT_TOO_OLD_MULTI, versionInfo->versionNum, versionInfo->releaseNum, minVersionNum1, minReleaseNum1, minVersionNum2, minReleaseNum2); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__checkDatabaseVersion() [INTERNAL] // Check the Oracle Database version and verify that it is at least at the // minimum version that is required. //----------------------------------------------------------------------------- int dpiUtils__checkDatabaseVersion(dpiConn *conn, int minVersionNum, int minReleaseNum, dpiError *error) { if (dpiConn__getServerVersion(conn, 0, error) < 0) return DPI_FAILURE; if (conn->versionInfo.versionNum < minVersionNum || (conn->versionInfo.versionNum == minVersionNum && conn->versionInfo.releaseNum < minReleaseNum)) return dpiError__set(error, "check Oracle Database version", DPI_ERR_ORACLE_DB_TOO_OLD, conn->versionInfo.versionNum, conn->versionInfo.releaseNum, minVersionNum, minReleaseNum); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__clearMemory() [INTERNAL] // Method for clearing memory that will not be optimised away by the // compiler. Simple use of memset() can be optimised away. This routine makes // use of a volatile pointer which most compilers will avoid optimising away, // even if the pointer appears to be unused after the call. //----------------------------------------------------------------------------- void dpiUtils__clearMemory(void *ptr, size_t length) { volatile unsigned char *temp = (unsigned char *) ptr; while (length--) *temp++ = '\0'; } //----------------------------------------------------------------------------- // dpiUtils__ensureBuffer() [INTERNAL] // Ensure that a buffer of the specified size is available. If a buffer of // the requested size is not available, free any existing buffer and allocate a // new, larger buffer. //----------------------------------------------------------------------------- int dpiUtils__ensureBuffer(size_t desiredSize, const char *action, void **ptr, size_t *currentSize, dpiError *error) { if (desiredSize <= *currentSize) return DPI_SUCCESS; if (*ptr) { dpiUtils__freeMemory(*ptr); *ptr = NULL; *currentSize = 0; } if (dpiUtils__allocateMemory(1, desiredSize, 0, action, ptr, error) < 0) return DPI_FAILURE; *currentSize = desiredSize; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__freeMemory() [INTERNAL] // Method for allocating memory which permits tracing and populates the error // structure in the event of a memory allocation failure. //----------------------------------------------------------------------------- void dpiUtils__freeMemory(void *ptr) { if (dpiDebugLevel & DPI_DEBUG_LEVEL_MEM) dpiDebug__print("freed ptr at %p\n", ptr); free(ptr); } //----------------------------------------------------------------------------- // dpiUtils__getAttrStringWithDup() [INTERNAL] // Get the string attribute from the OCI and duplicate its contents. //----------------------------------------------------------------------------- int dpiUtils__getAttrStringWithDup(const char *action, const void *ociHandle, uint32_t ociHandleType, uint32_t ociAttribute, const char **value, uint32_t *valueLength, dpiError *error) { char *source, *temp; if (dpiOci__attrGet(ociHandle, ociHandleType, (void*) &source, valueLength, ociAttribute, action, error) < 0) return DPI_FAILURE; if (*valueLength == 0) { *value = NULL; } else { if (dpiUtils__allocateMemory(1, *valueLength, 0, action, (void**) &temp, error) < 0) return DPI_FAILURE; *value = (const char*) memcpy(temp, source, *valueLength); } return DPI_SUCCESS; } #ifdef _WIN32 //----------------------------------------------------------------------------- // dpiUtils__getWindowsError() [INTERNAL] // Get the error message from Windows and place into the supplied buffer. The // buffer and length are provided as pointers and memory is allocated as needed // in order to be able to store the entire error message. //----------------------------------------------------------------------------- int dpiUtils__getWindowsError(DWORD errorNum, char **buffer, size_t *bufferLength, dpiError *error) { char *fallbackErrorFormat = "failed to get message for Windows Error %d"; wchar_t *wLoadError = NULL; DWORD length = 0, status; // use English unless English error messages aren't available status = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, errorNum, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPWSTR) &wLoadError, 0, NULL); if (!status && GetLastError() == ERROR_MUI_FILE_NOT_FOUND) FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, errorNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &wLoadError, 0, NULL); // transform UTF-16 to UTF-8 if (wLoadError) { // strip trailing period and carriage return from message, if needed length = (DWORD) wcslen(wLoadError); while (length > 0) { if (wLoadError[length - 1] > 127 || (wLoadError[length - 1] != L'.' && !isspace(wLoadError[length - 1]))) break; length--; } wLoadError[length] = L'\0'; // convert to UTF-8 encoding if (length > 0) { length = WideCharToMultiByte(CP_UTF8, 0, wLoadError, -1, NULL, 0, NULL, NULL); if (length > 0) { if (dpiUtils__ensureBuffer(length, "allocate buffer for Windows error message", (void**) buffer, bufferLength, error) < 0) { LocalFree(wLoadError); return DPI_FAILURE; } length = WideCharToMultiByte(CP_UTF8, 0, wLoadError, -1, *buffer, (int) *bufferLength, NULL, NULL); } } LocalFree(wLoadError); } if (length == 0) { if (dpiUtils__ensureBuffer(strlen(fallbackErrorFormat) + 20, "allocate buffer for fallback error message", (void**) buffer, bufferLength, error) < 0) return DPI_FAILURE; (void) sprintf(*buffer, fallbackErrorFormat, errorNum); } return DPI_SUCCESS; } #endif //----------------------------------------------------------------------------- // dpiUtils__parseNumberString() [INTERNAL] // Parse the contents of a string that is supposed to contain a number. The // number is expected to be in the format (www.json.org): // - optional negative sign (-) // - any number of digits but at least one (0-9) // - an optional decimal point (.) // - any number of digits but at least one if decimal point specified (0-9) // - an optional exponent indicator (e or E) // - an optional exponent sign (+ or -) // - any number of digits, but at least one if exponent specified (0-9) // What is returned is an indication of whether the number is negative, what // the index of the decimal point in the string is and the list of digits // without the decimal point. Note that OCI doesn't support more than 40 digits // so if there are more than this amount an error is raised. OCI doesn't // support larger than 1e126 so check for this value and raise a numeric // overflow error if found. OCI also doesn't support smaller than 1E-130 so // check for this value as well and if smaller than that value simply return // zero. //----------------------------------------------------------------------------- int dpiUtils__parseNumberString(const char *value, uint32_t valueLength, uint16_t charsetId, int *isNegative, int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, dpiError *error) { char convertedValue[DPI_NUMBER_AS_TEXT_CHARS], exponentDigits[4]; uint8_t numExponentDigits, digit; uint32_t convertedValueLength; uint16_t *utf16chars, i; int exponentIsNegative; const char *endValue; int16_t exponent; // empty strings are not valid numbers if (valueLength == 0) return dpiError__set(error, "zero length", DPI_ERR_INVALID_NUMBER); // strings longer than the maximum length of a valid number are also // excluded if ((charsetId == DPI_CHARSET_ID_UTF16 && valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) || (charsetId != DPI_CHARSET_ID_UTF16 && valueLength > DPI_NUMBER_AS_TEXT_CHARS)) return dpiError__set(error, "check length", DPI_ERR_NUMBER_STRING_TOO_LONG); // if value is encoded in UTF-16, convert to single byte encoding first // check for values that cannot be encoded in a single byte and are // obviously not part of a valid numeric string // also verify maximum length of number if (charsetId == DPI_CHARSET_ID_UTF16) { utf16chars = (uint16_t*) value; convertedValue[0] = '\0'; convertedValueLength = valueLength / 2; for (i = 0; i < convertedValueLength; i++) { if (*utf16chars > 127) return dpiError__set(error, "convert from UTF-16", DPI_ERR_INVALID_NUMBER); convertedValue[i] = (char) *utf16chars++; } value = convertedValue; valueLength = convertedValueLength; } // see if first character is a minus sign (number is negative) endValue = value + valueLength; *isNegative = (*value == '-'); if (*isNegative) value++; // scan for digits until the decimal point or exponent indicator is found *numDigits = 0; while (value < endValue) { if (*value == '.' || *value == 'e' || *value == 'E') break; if (*value < '0' || *value > '9') return dpiError__set(error, "check digits before decimal point", DPI_ERR_INVALID_NUMBER); digit = (uint8_t) (*value++ - '0'); if (digit == 0 && *numDigits == 0) continue; *digits++ = digit; (*numDigits)++; } *decimalPointIndex = *numDigits; // scan for digits following the decimal point, if applicable if (value < endValue && *value == '.') { value++; while (value < endValue) { if (*value == 'e' || *value == 'E') break; if (*value < '0' || *value > '9') return dpiError__set(error, "check digits after decimal point", DPI_ERR_INVALID_NUMBER); digit = (uint8_t) (*value++ - '0'); if (digit == 0 && *numDigits == 0) { (*decimalPointIndex)--; continue; } *digits++ = digit; (*numDigits)++; } } // handle exponent, if applicable if (value < endValue && (*value == 'e' || *value == 'E')) { value++; exponentIsNegative = 0; numExponentDigits = 0; if (value < endValue && (*value == '+' || *value == '-')) { exponentIsNegative = (*value == '-'); value++; } while (value < endValue) { if (*value < '0' || *value > '9') return dpiError__set(error, "check digits in exponent", DPI_ERR_INVALID_NUMBER); if (numExponentDigits == 3) return dpiError__set(error, "check exponent digits > 3", DPI_ERR_NOT_SUPPORTED); exponentDigits[numExponentDigits] = *value++; numExponentDigits++; } if (numExponentDigits == 0) return dpiError__set(error, "no digits in exponent", DPI_ERR_INVALID_NUMBER); exponentDigits[numExponentDigits] = '\0'; exponent = (int16_t) strtol(exponentDigits, NULL, 10); if (exponentIsNegative) exponent = -exponent; *decimalPointIndex += exponent; } // if there is anything left in the string, that indicates an invalid // number as well if (value < endValue) return dpiError__set(error, "check string used", DPI_ERR_INVALID_NUMBER); // strip trailing zeroes digits--; while (*numDigits > 0 && *digits-- == 0) (*numDigits)--; // values must be less than 1e126 and greater than 1e-129; the number of // digits also cannot exceed the maximum precision of Oracle numbers if (*numDigits > DPI_NUMBER_MAX_DIGITS || *decimalPointIndex > 126 || *decimalPointIndex < -129) { return dpiError__set(error, "check value can be represented", DPI_ERR_NUMBER_NO_REPR); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__parseOracleNumber() [INTERNAL] // Parse the contents of an Oracle number and return its constituent parts // so that a string can be generated from it easily. //----------------------------------------------------------------------------- int dpiUtils__parseOracleNumber(void *oracleValue, int *isNegative, int16_t *decimalPointIndex, uint8_t *numDigits, uint8_t *digits, dpiError *error) { uint8_t *source, length, i, byte, digit; int8_t ociExponent; // the first byte of the structure is a length byte which includes the // exponent and the mantissa bytes source = (uint8_t*) oracleValue; length = *source++ - 1; // a mantissa length longer than 20 signals corruption of some kind if (length > 20) return dpiError__set(error, "check mantissa length", DPI_ERR_INVALID_OCI_NUMBER); // the second byte of the structure is the exponent // positive numbers have the highest order bit set whereas negative numbers // have the highest order bit cleared and the bits inverted ociExponent = (int8_t) *source++; *isNegative = (ociExponent & 0x80) ? 0 : 1; if (*isNegative) ociExponent = ~ociExponent; ociExponent -= 193; *decimalPointIndex = ociExponent * 2 + 2; // a mantissa length of 0 implies a value of 0 (if positive) // or -1e126 (if negative) if (length == 0) { if (*isNegative) { *digits = 1; *decimalPointIndex = 127; } else { *decimalPointIndex = 1; *digits = 0; } *numDigits = 1; return DPI_SUCCESS; } // check for the trailing 102 byte for negative numbers and if present, // reduce the number of mantissa digits if (*isNegative && source[length - 1] == 102) length--; // process the mantissa which are the remaining bytes // each mantissa byte is a base-100 digit *numDigits = length * 2; for (i = 0; i < length; i++) { byte = *source++; // positive numbers have 1 added to them; negative numbers are // subtracted from the value 101 if (*isNegative) byte = 101 - byte; else byte--; // process the first digit; leading zeroes are ignored digit = (uint8_t) (byte / 10); if (digit == 0 && i == 0) { (*numDigits)--; (*decimalPointIndex)--; } else if (digit == 10) { (*numDigits)++; (*decimalPointIndex)++; *digits++ = 1; *digits++ = 0; } else *digits++ = digit; // process the second digit; trailing zeroes are ignored digit = byte % 10; if (digit == 0 && i == length - 1) (*numDigits)--; else *digits++ = digit; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__setAttributesFromCommonCreateParams() [INTERNAL] // Set the attributes on the authorization info structure or session handle // using the specified parameters. //----------------------------------------------------------------------------- int dpiUtils__setAttributesFromCommonCreateParams(void *handle, uint32_t handleType, const dpiCommonCreateParams *params, dpiError *error) { if (params->driverName && params->driverNameLength > 0 && dpiOci__attrSet(handle, handleType, (void*) params->driverName, params->driverNameLength, DPI_OCI_ATTR_DRIVER_NAME, "set driver name", error) < 0) return DPI_FAILURE; if (params->edition && params->editionLength > 0 && dpiOci__attrSet(handle, handleType, (void*) params->edition, params->editionLength, DPI_OCI_ATTR_EDITION, "set edition", error) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__setAccessTokenAttributes() [INTERNAL] // Set the token and private key for token based authentication on the auth // handle. //----------------------------------------------------------------------------- int dpiUtils__setAccessTokenAttributes(void *handle, dpiAccessToken *accessToken, dpiVersionInfo *versionInfo, dpiError *error) { int isBearer = 1; // check validity of access token if (!accessToken->token || accessToken->tokenLength == 0 || (accessToken->privateKey && accessToken->privateKeyLength == 0)) return dpiError__set(error, "check token based authentication parameters", DPI_ERR_TOKEN_BASED_AUTH); // IAM feature only available in Oracle Client 19.14+ and 21.5+ libraries if (accessToken->privateKey) { if (dpiUtils__checkClientVersionMulti(versionInfo, 19, 14, 21, 5, error) < 0) return DPI_FAILURE; // OAuth feature only available in Oracle Client 19.15+ and 21.7+ libraries } else { if (dpiUtils__checkClientVersionMulti(versionInfo, 19, 15, 21, 7, error) < 0) return DPI_FAILURE; } // set token on auth handle if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_AUTHINFO, (void*) accessToken->token, accessToken->tokenLength, DPI_OCI_ATTR_TOKEN, "set access token", error) < 0) return DPI_FAILURE; // set IAM private key on auth handle if (accessToken->privateKey) { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_AUTHINFO, (void*) accessToken->privateKey, accessToken->privateKeyLength, DPI_OCI_ATTR_IAM_PRIVKEY, "set access token private key", error) < 0) return DPI_FAILURE; // set OAuth bearer flag on auth handle } else { if (dpiOci__attrSet(handle, DPI_OCI_HTYPE_AUTHINFO, (void*) &isBearer, 0, DPI_OCI_ATTR_TOKEN_ISBEARER, "set bearer flag", error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiUtils__getTransactionHandle() [INTERNAL] // Returns a transaction handle that may be manipulated, if possible. A new // transaction handle is allocated if needed but only if there is no // transaction handle already associated with the service context. Note that // the connection retains a transaction handle for its lifetime, once // allocated, but a separate transaction handle may be associated by OCI due to // certain server operations. If OCI has already associated a transaction // handle to the service context, NULL is returned and no attempt is made to // manipulate that transaction. //----------------------------------------------------------------------------- int dpiUtils__getTransactionHandle(dpiConn *conn, void **transactionHandle, dpiError *error) { void *currentTransactionHandle; // check if a transaction handle is already associated with the connection if (dpiOci__attrGet(conn->handle, DPI_OCI_HTYPE_SVCCTX, ¤tTransactionHandle, NULL, DPI_OCI_ATTR_TRANS, "get associated transaction handle", error) < 0) return DPI_FAILURE; // if no transaction handle is set on the service context, then it is // safe to proceed with setting our own if (!currentTransactionHandle) { // allocate a new transaction handle, if needed if (!conn->transactionHandle) { if (dpiOci__handleAlloc(conn->env->handle, &conn->transactionHandle, DPI_OCI_HTYPE_TRANS, "allocate a transaction handle", error) < 0) return DPI_FAILURE; } // associate the transaction with the connection if (dpiOci__attrSet(conn->handle, DPI_OCI_HTYPE_SVCCTX, conn->transactionHandle, 0, DPI_OCI_ATTR_TRANS, "associate transaction", error) < 0) return DPI_FAILURE; } // if no transaction handle was set or it matches our own transaction // handle, then it can be returned; otherwise, NULL is returned if (!currentTransactionHandle || currentTransactionHandle == conn->transactionHandle) { *transactionHandle = conn->transactionHandle; } else { *transactionHandle = NULL; } return DPI_SUCCESS; } odpi-5.6.4/src/dpiVar.c000066400000000000000000002400501510466437300146530ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2016, 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiVar.c // Implementation of variables. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer, dpiError *error); static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes, dpiDynamicBytes *dynBytes, dpiError *error); static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes, dpiLob *lob, dpiError *error); static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value, uint32_t valueLength, dpiError *error); static int dpiVar__setFromJson(dpiVar *var, uint32_t pos, dpiJson *json, dpiError *error); static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob, dpiError *error); static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj, dpiError *error); static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid, dpiError *error); static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt, dpiError *error); static int dpiVar__setFromVector(dpiVar *var, uint32_t pos, dpiVector *vector, dpiError *error); static int dpiVar__validateTypes(const dpiOracleType *oracleType, dpiNativeTypeNum nativeTypeNum, dpiError *error); //----------------------------------------------------------------------------- // dpiVar__allocate() [INTERNAL] // Create a new variable object and return it. In case of error NULL is // returned. //----------------------------------------------------------------------------- int dpiVar__allocate(dpiConn *conn, dpiOracleTypeNum oracleTypeNum, dpiNativeTypeNum nativeTypeNum, uint32_t maxArraySize, uint32_t size, int sizeIsBytes, int isArray, dpiObjectType *objType, dpiVar **var, dpiData **data, dpiError *error) { const dpiOracleType *type; uint32_t sizeInBytes; dpiVar *tempVar; // validate arguments *var = NULL; type = dpiOracleType__getFromNum(oracleTypeNum, error); if (!type) return DPI_FAILURE; if (maxArraySize == 0) return dpiError__set(error, "check max array size", DPI_ERR_ARRAY_SIZE_ZERO); if (isArray && !type->canBeInArray) return dpiError__set(error, "check can be in array", DPI_ERR_NOT_SUPPORTED); if (oracleTypeNum == DPI_ORACLE_TYPE_BOOLEAN && dpiUtils__checkClientVersion(conn->env->versionInfo, 12, 1, error) < 0) return DPI_FAILURE; if (nativeTypeNum != type->defaultNativeTypeNum) { if (dpiVar__validateTypes(type, nativeTypeNum, error) < 0) return DPI_FAILURE; } // calculate size in bytes if (size == 0) size = 1; if (type->sizeInBytes) sizeInBytes = type->sizeInBytes; else if (sizeIsBytes || !type->isCharacterData) sizeInBytes = size; else if (type->charsetForm == DPI_SQLCS_IMPLICIT) sizeInBytes = size * conn->env->maxBytesPerCharacter; else sizeInBytes = size * conn->env->nmaxBytesPerCharacter; // allocate memory for variable type if (dpiGen__allocate(DPI_HTYPE_VAR, conn->env, (void**) &tempVar, error) < 0) return DPI_FAILURE; // basic initialization tempVar->buffer.maxArraySize = maxArraySize; if (!isArray) tempVar->buffer.actualArraySize = maxArraySize; tempVar->sizeInBytes = sizeInBytes; if (sizeInBytes > DPI_MAX_BASIC_BUFFER_SIZE) { tempVar->sizeInBytes = 0; tempVar->isDynamic = 1; tempVar->requiresPreFetch = 1; } tempVar->type = type; tempVar->nativeTypeNum = nativeTypeNum; tempVar->isArray = isArray; dpiGen__setRefCount(conn, error, 1); tempVar->conn = conn; if (objType) { if (dpiGen__checkHandle(objType, DPI_HTYPE_OBJECT_TYPE, "check object type", error) < 0) { dpiVar__free(tempVar, error); return DPI_FAILURE; } dpiGen__setRefCount(objType, error, 1); tempVar->objectType = objType; } // allocate the data for the variable if (dpiVar__initBuffer(tempVar, &tempVar->buffer, error) < 0) { dpiVar__free(tempVar, error); return DPI_FAILURE; } *var = tempVar; *data = tempVar->buffer.externalData; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__allocateChunks() [INTERNAL] // Allocate more chunks for handling dynamic bytes. //----------------------------------------------------------------------------- static int dpiVar__allocateChunks(dpiDynamicBytes *dynBytes, dpiError *error) { dpiDynamicBytesChunk *chunks; uint32_t allocatedChunks; allocatedChunks = dynBytes->allocatedChunks + 8; if (dpiUtils__allocateMemory(allocatedChunks, sizeof(dpiDynamicBytesChunk), 1, "allocate chunks", (void**) &chunks, error) < 0) return DPI_FAILURE; if (dynBytes->chunks) { memcpy(chunks, dynBytes->chunks, dynBytes->numChunks * sizeof(dpiDynamicBytesChunk)); dpiUtils__freeMemory(dynBytes->chunks); } dynBytes->chunks = chunks; dynBytes->allocatedChunks = allocatedChunks; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__allocateDynamicBytes() [INTERNAL] // Allocate space in the dynamic bytes structure for the specified number of // bytes. When complete, there will be exactly one allocated chunk of the // specified size or greater in the dynamic bytes structure. //----------------------------------------------------------------------------- static int dpiVar__allocateDynamicBytes(dpiDynamicBytes *dynBytes, uint32_t size, dpiError *error) { // if an error occurs, none of the original space is valid dynBytes->numChunks = 0; // if there are no chunks at all, make sure some exist if (dynBytes->allocatedChunks == 0 && dpiVar__allocateChunks(dynBytes, error) < 0) return DPI_FAILURE; // at this point there should be 0 or 1 chunks as any retrieval that // resulted in multiple chunks would have been consolidated already // make sure that chunk has enough space in it if (size > dynBytes->chunks->allocatedLength) { if (dynBytes->chunks->ptr) dpiUtils__freeMemory(dynBytes->chunks->ptr); dynBytes->chunks->allocatedLength = (size + DPI_DYNAMIC_BYTES_CHUNK_SIZE - 1) & ~(DPI_DYNAMIC_BYTES_CHUNK_SIZE - 1); if (dpiUtils__allocateMemory(1, dynBytes->chunks->allocatedLength, 0, "allocate chunk", (void**) &dynBytes->chunks->ptr, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__assignCallbackBuffer() [INTERNAL] // Assign callback pointers during OCI statement execution. This is used with // the callack functions used for dynamic binding during DML returning // statement execution. //----------------------------------------------------------------------------- static void dpiVar__assignCallbackBuffer(dpiVar *var, dpiVarBuffer *buffer, uint32_t index, void **bufpp) { switch (var->type->oracleTypeNum) { case DPI_ORACLE_TYPE_TIMESTAMP: case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: *bufpp = buffer->data.asTimestamp[index]; break; case DPI_ORACLE_TYPE_INTERVAL_DS: case DPI_ORACLE_TYPE_INTERVAL_YM: *bufpp = buffer->data.asInterval[index]; break; case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BFILE: *bufpp = buffer->data.asLobLocator[index]; break; case DPI_ORACLE_TYPE_ROWID: *bufpp = buffer->data.asRowid[index]; break; case DPI_ORACLE_TYPE_JSON: *bufpp = buffer->data.asJsonDescriptor[index]; break; case DPI_ORACLE_TYPE_VECTOR: *bufpp = buffer->data.asVectorDescriptor[index]; break; case DPI_ORACLE_TYPE_STMT: *bufpp = buffer->data.asStmt[index]; break; default: *bufpp = buffer->data.asBytes + index * var->sizeInBytes; break; } } //----------------------------------------------------------------------------- // dpiVar__checkArraySize() [INTERNAL] // Verifies that the array size has not been exceeded. //----------------------------------------------------------------------------- static int dpiVar__checkArraySize(dpiVar *var, uint32_t pos, const char *fnName, dpiError *error) { if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, fnName, error) < 0) return DPI_FAILURE; if (pos >= var->buffer.maxArraySize) return dpiError__set(error, "check array size", DPI_ERR_INVALID_ARRAY_POSITION, pos, var->buffer.maxArraySize); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__convertToLob() [INTERNAL] // Convert the variable from using dynamic bytes for a long string to using a // LOB instead. This is needed for PL/SQL which cannot handle more than 32K // without the use of a LOB. //----------------------------------------------------------------------------- int dpiVar__convertToLob(dpiVar *var, dpiError *error) { dpiDynamicBytes *dynBytes; dpiLob *lob; uint32_t i; // change type based on the original Oracle type if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_RAW || var->type->oracleTypeNum == DPI_ORACLE_TYPE_LONG_RAW) var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_BLOB, error); else if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NCHAR) var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_NCLOB, error); else var->type = dpiOracleType__getFromNum(DPI_ORACLE_TYPE_CLOB, error); // adjust attributes and re-initialize buffers // the dynamic bytes structures will not be removed var->sizeInBytes = var->type->sizeInBytes; var->isDynamic = 0; if (dpiVar__initBuffer(var, &var->buffer, error) < 0) return DPI_FAILURE; // copy any values already set for (i = 0; i < var->buffer.maxArraySize; i++) { dynBytes = &var->buffer.dynamicBytes[i]; lob = var->buffer.references[i].asLOB; if (dynBytes->numChunks == 0) continue; if (dpiLob__setFromBytes(lob, dynBytes->chunks->ptr, dynBytes->chunks->length, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__copyData() [INTERNAL] // Copy the data from the source to the target variable at the given array // position. //----------------------------------------------------------------------------- int dpiVar__copyData(dpiVar *var, uint32_t pos, dpiData *sourceData, dpiError *error) { dpiData *targetData = &var->buffer.externalData[pos]; // handle null case targetData->isNull = sourceData->isNull; if (sourceData->isNull) return DPI_SUCCESS; // handle copying of value from source to target switch (var->nativeTypeNum) { case DPI_NATIVE_TYPE_BYTES: return dpiVar__setFromBytes(var, pos, sourceData->value.asBytes.ptr, sourceData->value.asBytes.length, error); case DPI_NATIVE_TYPE_JSON: return dpiVar__setFromJson(var, pos, sourceData->value.asJson, error); case DPI_NATIVE_TYPE_LOB: return dpiVar__setFromLob(var, pos, sourceData->value.asLOB, error); case DPI_NATIVE_TYPE_OBJECT: return dpiVar__setFromObject(var, pos, sourceData->value.asObject, error); case DPI_NATIVE_TYPE_STMT: return dpiVar__setFromStmt(var, pos, sourceData->value.asStmt, error); case DPI_NATIVE_TYPE_ROWID: return dpiVar__setFromRowid(var, pos, sourceData->value.asRowid, error); case DPI_NATIVE_TYPE_VECTOR: return dpiVar__setFromVector(var, pos, sourceData->value.asVector, error); default: memcpy(targetData, sourceData, sizeof(dpiData)); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__defineCallback() [INTERNAL] // Callback which runs during OCI statement execution and allocates the // buffers required as well as provides that information to the OCI. This is // intended for handling string and raw columns for which the size is unknown. // These include LONG, LONG RAW and retrieving CLOB and BLOB as bytes, rather // than use the LOB API. //----------------------------------------------------------------------------- int32_t dpiVar__defineCallback(dpiVar *var, UNUSED void *defnp, uint32_t iter, void **bufpp, uint32_t **alenpp, UNUSED uint8_t *piecep, void **indpp, uint16_t **rcodepp) { dpiDynamicBytesChunk *chunk; dpiDynamicBytes *bytes; // allocate more chunks, if necessary bytes = &var->buffer.dynamicBytes[iter]; if (bytes->numChunks == bytes->allocatedChunks && dpiVar__allocateChunks(bytes, var->error) < 0) return DPI_OCI_ERROR; // allocate memory for the chunk, if needed chunk = &bytes->chunks[bytes->numChunks]; if (!chunk->ptr) { chunk->allocatedLength = DPI_DYNAMIC_BYTES_CHUNK_SIZE; if (dpiUtils__allocateMemory(1, chunk->allocatedLength, 0, "allocate chunk", (void**) &chunk->ptr, var->error) < 0) return DPI_OCI_ERROR; } // return chunk to OCI bytes->numChunks++; chunk->length = chunk->allocatedLength; *bufpp = chunk->ptr; *alenpp = &chunk->length; *indpp = &(var->buffer.indicator[iter]); *rcodepp = NULL; return DPI_OCI_CONTINUE; } //----------------------------------------------------------------------------- // dpiVar__extendedPreFetch() [INTERNAL] // Perform any necessary actions prior to fetching data. //----------------------------------------------------------------------------- int dpiVar__extendedPreFetch(dpiVar *var, dpiVarBuffer *buffer, dpiError *error) { dpiVector *vector; dpiRowid *rowid; dpiData *data; dpiStmt *stmt; dpiJson *json; dpiLob *lob; uint32_t i; if (var->isDynamic) { for (i = 0; i < buffer->maxArraySize; i++) buffer->dynamicBytes[i].numChunks = 0; return DPI_SUCCESS; } switch (var->type->oracleTypeNum) { case DPI_ORACLE_TYPE_STMT: for (i = 0; i < buffer->maxArraySize; i++) { data = &buffer->externalData[i]; if (buffer->references[i].asStmt) { dpiGen__setRefCount(buffer->references[i].asStmt, error, -1); buffer->references[i].asStmt = NULL; } buffer->data.asStmt[i] = NULL; data->value.asStmt = NULL; if (dpiStmt__allocate(var->conn, 0, &stmt, error) < 0) return DPI_FAILURE; if (dpiOci__handleAlloc(var->env->handle, &stmt->handle, DPI_OCI_HTYPE_STMT, "allocate statement", error) < 0) { dpiStmt__free(stmt, error); return DPI_FAILURE; } if (dpiHandleList__addHandle(var->conn->openStmts, stmt, &stmt->openSlotNum, error) < 0) { dpiOci__handleFree(stmt->handle, DPI_OCI_HTYPE_STMT); stmt->handle = NULL; dpiStmt__free(stmt, error); return DPI_FAILURE; } buffer->references[i].asStmt = stmt; stmt->isOwned = 1; buffer->data.asStmt[i] = stmt->handle; data->value.asStmt = stmt; } break; case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BFILE: for (i = 0; i < buffer->maxArraySize; i++) { data = &buffer->externalData[i]; if (buffer->references[i].asLOB) { dpiGen__setRefCount(buffer->references[i].asLOB, error, -1); buffer->references[i].asLOB = NULL; } buffer->data.asLobLocator[i] = NULL; data->value.asLOB = NULL; if (dpiLob__allocate(var->conn, var->type, &lob, error) < 0) return DPI_FAILURE; buffer->references[i].asLOB = lob; buffer->data.asLobLocator[i] = lob->locator; data->value.asLOB = lob; if (buffer->dynamicBytes && dpiOci__lobCreateTemporary(lob, error) < 0) return DPI_FAILURE; } break; case DPI_ORACLE_TYPE_ROWID: for (i = 0; i < buffer->maxArraySize; i++) { data = &buffer->externalData[i]; if (buffer->references[i].asRowid) { dpiGen__setRefCount(buffer->references[i].asRowid, error, -1); buffer->references[i].asRowid = NULL; } buffer->data.asRowid[i] = NULL; data->value.asRowid = NULL; if (dpiRowid__allocate(var->conn, &rowid, error) < 0) return DPI_FAILURE; buffer->references[i].asRowid = rowid; buffer->data.asRowid[i] = rowid->handle; data->value.asRowid = rowid; } break; case DPI_ORACLE_TYPE_OBJECT: for (i = 0; i < buffer->maxArraySize; i++) { data = &buffer->externalData[i]; if (buffer->references[i].asObject) { dpiGen__setRefCount(buffer->references[i].asObject, error, -1); buffer->references[i].asObject = NULL; } buffer->data.asObject[i] = NULL; buffer->objectIndicator[i] = NULL; data->value.asObject = NULL; } break; case DPI_ORACLE_TYPE_JSON: for (i = 0; i < buffer->maxArraySize; i++) { data = &buffer->externalData[i]; if (buffer->references[i].asJson) { dpiGen__setRefCount(buffer->references[i].asJson, error, -1); buffer->references[i].asJson = NULL; } buffer->data.asJsonDescriptor[i] = NULL; data->value.asJson = NULL; if (dpiJson__allocate(var->conn, NULL, &json, error) < 0) return DPI_FAILURE; buffer->references[i].asJson = json; buffer->data.asJsonDescriptor[i] = json->handle; data->value.asJson = json; } break; case DPI_ORACLE_TYPE_VECTOR: for (i = 0; i < buffer->maxArraySize; i++) { data = &buffer->externalData[i]; if (buffer->references[i].asVector) { dpiGen__setRefCount(buffer->references[i].asVector, error, -1); buffer->references[i].asVector = NULL; } buffer->data.asVectorDescriptor[i] = NULL; data->value.asVector = NULL; if (dpiVector__allocate(var->conn, &vector, error) < 0) return DPI_FAILURE; buffer->references[i].asVector = vector; buffer->data.asVectorDescriptor[i] = vector->handle; data->value.asVector = vector; } break; default: break; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__finalizeBuffer() [INTERNAL] // Finalize buffer used for passing data to/from Oracle. //----------------------------------------------------------------------------- static void dpiVar__finalizeBuffer(dpiVar *var, dpiVarBuffer *buffer, dpiError *error) { dpiDynamicBytes *dynBytes; uint32_t i, j; // free any descriptors that were created switch (var->type->oracleTypeNum) { case DPI_ORACLE_TYPE_TIMESTAMP: dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP); break; case DPI_ORACLE_TYPE_TIMESTAMP_TZ: dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_TZ); break; case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: dpiOci__arrayDescriptorFree(&buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_LTZ); break; case DPI_ORACLE_TYPE_INTERVAL_DS: dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_DS); break; case DPI_ORACLE_TYPE_INTERVAL_YM: dpiOci__arrayDescriptorFree(&buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_YM); break; default: break; } // release any references that were created if (buffer->references) { for (i = 0; i < buffer->maxArraySize; i++) { if (buffer->references[i].asHandle) { dpiGen__setRefCount(buffer->references[i].asHandle, error, -1); buffer->references[i].asHandle = NULL; } } dpiUtils__freeMemory(buffer->references); buffer->references = NULL; } // free any dynamic buffers if (buffer->dynamicBytes) { for (i = 0; i < buffer->maxArraySize; i++) { dynBytes = &buffer->dynamicBytes[i]; if (dynBytes->allocatedChunks > 0) { for (j = 0; j < dynBytes->allocatedChunks; j++) { if (dynBytes->chunks[j].ptr) { dpiUtils__freeMemory(dynBytes->chunks[j].ptr); dynBytes->chunks[j].ptr = NULL; } } dpiUtils__freeMemory(dynBytes->chunks); dynBytes->allocatedChunks = 0; dynBytes->chunks = NULL; } } dpiUtils__freeMemory(buffer->dynamicBytes); buffer->dynamicBytes = NULL; } // free other memory allocated if (buffer->indicator) { dpiUtils__freeMemory(buffer->indicator); buffer->indicator = NULL; } if (buffer->returnCode) { dpiUtils__freeMemory(buffer->returnCode); buffer->returnCode = NULL; } if (buffer->actualLength16) { dpiUtils__freeMemory(buffer->actualLength16); buffer->actualLength16 = NULL; } if (buffer->actualLength32) { dpiUtils__freeMemory(buffer->actualLength32); buffer->actualLength32 = NULL; } if (buffer->externalData) { dpiUtils__freeMemory(buffer->externalData); buffer->externalData = NULL; } if (buffer->data.asRaw) { dpiUtils__freeMemory(buffer->data.asRaw); buffer->data.asRaw = NULL; } if (buffer->objectIndicator) { dpiUtils__freeMemory(buffer->objectIndicator); buffer->objectIndicator = NULL; } if (buffer->tempBuffer) { dpiUtils__freeMemory(buffer->tempBuffer); buffer->tempBuffer = NULL; } } //----------------------------------------------------------------------------- // dpiVar__free() [INTERNAL] // Free the memory associated with the variable. //----------------------------------------------------------------------------- void dpiVar__free(dpiVar *var, dpiError *error) { uint32_t i; dpiVar__finalizeBuffer(var, &var->buffer, error); if (var->dynBindBuffers) { for (i = 0; i < var->buffer.maxArraySize; i++) dpiVar__finalizeBuffer(var, &var->dynBindBuffers[i], error); dpiUtils__freeMemory(var->dynBindBuffers); var->dynBindBuffers = NULL; } if (var->objectType) { dpiGen__setRefCount(var->objectType, error, -1); var->objectType = NULL; } if (var->conn) { dpiGen__setRefCount(var->conn, error, -1); var->conn = NULL; } dpiUtils__freeMemory(var); } //----------------------------------------------------------------------------- // dpiVar__getValue() [PRIVATE] // Returns the contents of the variable in the type specified, if possible. //----------------------------------------------------------------------------- int dpiVar__getValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, int inFetch, dpiError *error) { dpiOracleTypeNum oracleTypeNum; dpiBytes *bytes; dpiData *data; uint32_t i; // check for dynamic binds first; if they exist, process them instead if (var->dynBindBuffers && buffer == &var->buffer) { buffer = &var->dynBindBuffers[pos]; for (i = 0; i < buffer->maxArraySize; i++) { if (dpiVar__getValue(var, buffer, i, inFetch, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } // check for a NULL value; for objects the indicator is elsewhere data = &buffer->externalData[pos]; if (!buffer->objectIndicator) data->isNull = (buffer->indicator[pos] == DPI_OCI_IND_NULL); else if (buffer->objectIndicator[pos]) data->isNull = (*((int16_t*) buffer->objectIndicator[pos]) == DPI_OCI_IND_NULL); else data->isNull = 1; if (data->isNull) { if (inFetch && var->objectType && var->objectType->isCollection) { if (dpiOci__objectFree(var->env->handle, buffer->data.asObject[pos], 1, error) < 0) return DPI_FAILURE; if (dpiOci__objectFree(var->env->handle, buffer->objectIndicator[pos], 1, error) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } // check return code for variable length data if (buffer->returnCode) { if (buffer->returnCode[pos] != 0) { dpiError__set(error, "check return code", DPI_ERR_COLUMN_FETCH, pos, buffer->returnCode[pos]); error->buffer->code = buffer->returnCode[pos]; return DPI_FAILURE; } } // for 11g, dynamic lengths are 32-bit whereas static lengths are 16-bit if (buffer->actualLength16 && buffer->actualLength32) buffer->actualLength16[pos] = (uint16_t) buffer->actualLength32[pos]; // transform the various types oracleTypeNum = var->type->oracleTypeNum; switch (var->nativeTypeNum) { case DPI_NATIVE_TYPE_INT64: case DPI_NATIVE_TYPE_UINT64: switch (oracleTypeNum) { case DPI_ORACLE_TYPE_NATIVE_INT: data->value.asInt64 = buffer->data.asInt64[pos]; return DPI_SUCCESS; case DPI_ORACLE_TYPE_NATIVE_UINT: data->value.asUint64 = buffer->data.asUint64[pos]; return DPI_SUCCESS; case DPI_ORACLE_TYPE_NUMBER: if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) return dpiDataBuffer__fromOracleNumberAsInteger( &data->value, error, &buffer->data.asNumber[pos]); return dpiDataBuffer__fromOracleNumberAsUnsignedInteger( &data->value, error, &buffer->data.asNumber[pos]); default: break; } break; case DPI_NATIVE_TYPE_DOUBLE: switch (oracleTypeNum) { case DPI_ORACLE_TYPE_NUMBER: return dpiDataBuffer__fromOracleNumberAsDouble( &data->value, error, &buffer->data.asNumber[pos]); case DPI_ORACLE_TYPE_NATIVE_DOUBLE: data->value.asDouble = buffer->data.asDouble[pos]; return DPI_SUCCESS; case DPI_ORACLE_TYPE_DATE: return dpiDataBuffer__fromOracleDateAsDouble(&data->value, var->env, error, &buffer->data.asDate[pos]); case DPI_ORACLE_TYPE_TIMESTAMP: case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: return dpiDataBuffer__fromOracleTimestampAsDouble( &data->value, oracleTypeNum, var->env, error, buffer->data.asTimestamp[pos]); default: break; } break; case DPI_NATIVE_TYPE_BYTES: bytes = &data->value.asBytes; switch (oracleTypeNum) { case DPI_ORACLE_TYPE_VARCHAR: case DPI_ORACLE_TYPE_NVARCHAR: case DPI_ORACLE_TYPE_CHAR: case DPI_ORACLE_TYPE_NCHAR: case DPI_ORACLE_TYPE_ROWID: case DPI_ORACLE_TYPE_RAW: case DPI_ORACLE_TYPE_LONG_VARCHAR: case DPI_ORACLE_TYPE_LONG_NVARCHAR: case DPI_ORACLE_TYPE_LONG_RAW: case DPI_ORACLE_TYPE_XMLTYPE: if (buffer->dynamicBytes) return dpiVar__setBytesFromDynamicBytes(bytes, &buffer->dynamicBytes[pos], error); if (buffer->actualLength16) bytes->length = buffer->actualLength16[pos]; else bytes->length = buffer->actualLength32[pos]; return DPI_SUCCESS; case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_BFILE: return dpiVar__setBytesFromLob(bytes, &buffer->dynamicBytes[pos], buffer->references[pos].asLOB, error); case DPI_ORACLE_TYPE_NUMBER: bytes->length = DPI_NUMBER_AS_TEXT_CHARS; if (var->env->charsetId == DPI_CHARSET_ID_UTF16) bytes->length *= 2; return dpiDataBuffer__fromOracleNumberAsText(&data->value, var->env, error, &buffer->data.asNumber[pos]); default: break; } break; case DPI_NATIVE_TYPE_FLOAT: data->value.asFloat = buffer->data.asFloat[pos]; break; case DPI_NATIVE_TYPE_TIMESTAMP: if (oracleTypeNum == DPI_ORACLE_TYPE_DATE) return dpiDataBuffer__fromOracleDate(&data->value, &buffer->data.asDate[pos]); return dpiDataBuffer__fromOracleTimestamp(&data->value, var->env, error, buffer->data.asTimestamp[pos], oracleTypeNum != DPI_ORACLE_TYPE_TIMESTAMP); break; case DPI_NATIVE_TYPE_INTERVAL_DS: return dpiDataBuffer__fromOracleIntervalDS(&data->value, var->env, error, buffer->data.asInterval[pos]); case DPI_NATIVE_TYPE_INTERVAL_YM: return dpiDataBuffer__fromOracleIntervalYM(&data->value, var->env, error, buffer->data.asInterval[pos]); case DPI_NATIVE_TYPE_OBJECT: data->value.asObject = NULL; if (!buffer->references[pos].asObject) { if (dpiObject__allocate(var->objectType, buffer->data.asObject[pos], buffer->objectIndicator[pos], NULL, &buffer->references[pos].asObject, error) < 0) return DPI_FAILURE; if (inFetch && var->objectType->isCollection) buffer->references[pos].asObject->freeIndicator = 1; } data->value.asObject = buffer->references[pos].asObject; break; case DPI_NATIVE_TYPE_STMT: data->value.asStmt = buffer->references[pos].asStmt; break; case DPI_NATIVE_TYPE_BOOLEAN: data->value.asBoolean = buffer->data.asBoolean[pos]; break; default: break; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__inBindCallback() [INTERNAL] // Callback which runs during OCI statement execution and provides buffers to // OCI for binding data IN. This is not used with DML returning so this method // does nothing useful except satisfy OCI requirements. //----------------------------------------------------------------------------- int32_t dpiVar__inBindCallback(dpiVar *var, UNUSED void *bindp, UNUSED uint32_t iter, UNUSED uint32_t index, void **bufpp, uint32_t *alenp, uint8_t *piecep, void **indpp) { dpiDynamicBytes *dynBytes; if (var->isDynamic) { dynBytes = &var->buffer.dynamicBytes[iter]; if (dynBytes->allocatedChunks == 0) { *bufpp = NULL; *alenp = 0; } else { *bufpp = dynBytes->chunks->ptr; *alenp = dynBytes->chunks->length; } } else { dpiVar__assignCallbackBuffer(var, &var->buffer, iter, bufpp); if (var->buffer.actualLength16) *alenp = var->buffer.actualLength16[iter]; else if (var->buffer.actualLength32) *alenp = var->buffer.actualLength32[iter]; else *alenp = var->type->sizeInBytes; } *piecep = DPI_OCI_ONE_PIECE; if (var->buffer.objectIndicator) *indpp = var->buffer.objectIndicator[iter]; else *indpp = &var->buffer.indicator[iter]; return DPI_OCI_CONTINUE; } //----------------------------------------------------------------------------- // dpiVar__initBuffer() [INTERNAL] // Initialize buffers necessary for passing data to/from Oracle. //----------------------------------------------------------------------------- static int dpiVar__initBuffer(dpiVar *var, dpiVarBuffer *buffer, dpiError *error) { uint32_t i, tempBufferSize = 0; unsigned long long dataLength; dpiBytes *bytes; // initialize dynamic buffers for dynamic variables if (var->isDynamic) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(dpiDynamicBytes), 1, "allocate dynamic bytes", (void**) &buffer->dynamicBytes, error) < 0) return DPI_FAILURE; // for all other variables, validate length and allocate buffers } else { dataLength = (unsigned long long) buffer->maxArraySize * (unsigned long long) var->sizeInBytes; if (dataLength > INT_MAX) return dpiError__set(error, "check max array size", DPI_ERR_ARRAY_SIZE_TOO_BIG, buffer->maxArraySize); if (dpiUtils__allocateMemory(1, (size_t) dataLength, 0, "allocate buffer", (void**) &buffer->data.asRaw, error) < 0) return DPI_FAILURE; } // allocate the indicator for the variable // ensure all values start out as null if (!buffer->indicator) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(int16_t), 0, "allocate indicator", (void**) &buffer->indicator, error) < 0) return DPI_FAILURE; for (i = 0; i < buffer->maxArraySize; i++) buffer->indicator[i] = DPI_OCI_IND_NULL; } // allocate the actual length buffers for all but dynamic bytes which are // handled differently; ensure actual length starts out as maximum value if (!var->isDynamic && !buffer->actualLength16 && !buffer->actualLength32) { if (var->env->versionInfo->versionNum < 12 && buffer == &var->buffer) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint16_t), 0, "allocate actual length", (void**) &buffer->actualLength16, error) < 0) return DPI_FAILURE; for (i = 0; i < buffer->maxArraySize; i++) buffer->actualLength16[i] = (uint16_t) var->sizeInBytes; } else { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint32_t), 0, "allocate actual length", (void**) &buffer->actualLength32, error) < 0) return DPI_FAILURE; for (i = 0; i < buffer->maxArraySize; i++) buffer->actualLength32[i] = var->sizeInBytes; } } // for variable length data, also allocate the return code array if (var->type->defaultNativeTypeNum == DPI_NATIVE_TYPE_BYTES && !var->isDynamic && !buffer->returnCode) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint16_t), 0, "allocate return code", (void**) &buffer->returnCode, error) < 0) return DPI_FAILURE; } // for numbers transferred to/from Oracle as bytes, allocate an additional // set of buffers if (var->type->oracleTypeNum == DPI_ORACLE_TYPE_NUMBER && var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { tempBufferSize = DPI_NUMBER_AS_TEXT_CHARS; if (var->env->charsetId == DPI_CHARSET_ID_UTF16) tempBufferSize *= 2; if (!buffer->tempBuffer) { if (dpiUtils__allocateMemory(buffer->maxArraySize, tempBufferSize, 0, "allocate temp buffer", (void**) &buffer->tempBuffer, error) < 0) return DPI_FAILURE; } } // allocate the external data array, if needed if (!buffer->externalData) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(dpiData), 1, "allocate external data", (void**) &buffer->externalData, error) < 0) return DPI_FAILURE; for (i = 0; i < buffer->maxArraySize; i++) buffer->externalData[i].isNull = 1; } // for bytes transfers, set encoding and pointers for small strings if (var->nativeTypeNum == DPI_NATIVE_TYPE_BYTES) { for (i = 0; i < buffer->maxArraySize; i++) { bytes = &buffer->externalData[i].value.asBytes; if (var->type->charsetForm == DPI_SQLCS_IMPLICIT) bytes->encoding = var->env->encoding; else bytes->encoding = var->env->nencoding; if (buffer->tempBuffer) bytes->ptr = buffer->tempBuffer + i * tempBufferSize; else if (!var->isDynamic && !buffer->dynamicBytes) bytes->ptr = buffer->data.asBytes + i * var->sizeInBytes; } } // create array of references, if applicable if (var->type->requiresPreFetch && !var->isDynamic) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(dpiReferenceBuffer), 1, "allocate references", (void**) &buffer->references, error) < 0) return DPI_FAILURE; } // perform variable specific initialization switch (var->type->oracleTypeNum) { case DPI_ORACLE_TYPE_TIMESTAMP: return dpiOci__arrayDescriptorAlloc(var->env->handle, &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP, buffer->maxArraySize, error); case DPI_ORACLE_TYPE_TIMESTAMP_TZ: return dpiOci__arrayDescriptorAlloc(var->env->handle, &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_TZ, buffer->maxArraySize, error); case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: return dpiOci__arrayDescriptorAlloc(var->env->handle, &buffer->data.asTimestamp[0], DPI_OCI_DTYPE_TIMESTAMP_LTZ, buffer->maxArraySize, error); case DPI_ORACLE_TYPE_INTERVAL_DS: return dpiOci__arrayDescriptorAlloc(var->env->handle, &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_DS, buffer->maxArraySize, error); case DPI_ORACLE_TYPE_INTERVAL_YM: return dpiOci__arrayDescriptorAlloc(var->env->handle, &buffer->data.asInterval[0], DPI_OCI_DTYPE_INTERVAL_YM, buffer->maxArraySize, error); case DPI_ORACLE_TYPE_CLOB: case DPI_ORACLE_TYPE_BLOB: case DPI_ORACLE_TYPE_NCLOB: case DPI_ORACLE_TYPE_BFILE: case DPI_ORACLE_TYPE_STMT: case DPI_ORACLE_TYPE_ROWID: case DPI_ORACLE_TYPE_JSON: case DPI_ORACLE_TYPE_VECTOR: return dpiVar__extendedPreFetch(var, buffer, error); case DPI_ORACLE_TYPE_OBJECT: if (!var->objectType) return dpiError__set(error, "check object type", DPI_ERR_NO_OBJECT_TYPE); if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(void*), 0, "allocate object indicator", (void**) &buffer->objectIndicator, error) < 0) return DPI_FAILURE; return dpiVar__extendedPreFetch(var, buffer, error); default: break; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__outBindCallback() [INTERNAL] // Callback which runs during OCI statement execution and allocates the // buffers required as well as provides that information to the OCI. This is // intended for use with DML returning only. //----------------------------------------------------------------------------- int32_t dpiVar__outBindCallback(dpiVar *var, void *bindp, UNUSED uint32_t iter, uint32_t index, void **bufpp, uint32_t **alenpp, uint8_t *piecep, void **indpp, uint16_t **rcodepp) { dpiDynamicBytesChunk *chunk; uint32_t numRowsReturned; dpiDynamicBytes *bytes; dpiVarBuffer *buffer; // determine which variable buffer to use if (!var->dynBindBuffers) { if (dpiUtils__allocateMemory(var->buffer.maxArraySize, sizeof(dpiVarBuffer), 1, "allocate DML returning buffers", (void**) &var->dynBindBuffers, var->error) < 0) return DPI_FAILURE; } buffer = &var->dynBindBuffers[iter]; // special processing during first value returned for each iteration if (index == 0) { // determine number of rows returned if (dpiOci__attrGet(bindp, DPI_OCI_HTYPE_BIND, &numRowsReturned, 0, DPI_OCI_ATTR_ROWS_RETURNED, "get rows returned", var->error) < 0) return DPI_OCI_ERROR; // reallocate buffers, if needed if (numRowsReturned > buffer->maxArraySize) { dpiVar__finalizeBuffer(var, buffer, var->error); buffer->maxArraySize = numRowsReturned; if (dpiVar__initBuffer(var, buffer, var->error) < 0) return DPI_OCI_ERROR; } // set actual array size to number of rows returned buffer->actualArraySize = numRowsReturned; } // handle dynamically allocated strings (multiple piece) // index is the current index into the chunks if (var->isDynamic) { // allocate more chunks, if necessary bytes = &buffer->dynamicBytes[index]; if (*piecep == DPI_OCI_ONE_PIECE) bytes->numChunks = 0; if (bytes->numChunks == bytes->allocatedChunks && dpiVar__allocateChunks(bytes, var->error) < 0) return DPI_OCI_ERROR; // allocate memory for the chunk, if needed chunk = &bytes->chunks[bytes->numChunks]; if (!chunk->ptr) { chunk->allocatedLength = DPI_DYNAMIC_BYTES_CHUNK_SIZE; if (dpiUtils__allocateMemory(1, chunk->allocatedLength, 0, "allocate chunk", (void**) &chunk->ptr, var->error) < 0) return DPI_OCI_ERROR; } // return chunk to OCI bytes->numChunks++; chunk->length = chunk->allocatedLength; *bufpp = chunk->ptr; *alenpp = &chunk->length; *indpp = &(buffer->indicator[index]); *rcodepp = NULL; // handle normally allocated variables (one piece) } else { *piecep = DPI_OCI_ONE_PIECE; if (dpiVar__setValue(var, buffer, index, &buffer->externalData[index], var->error) < 0) return DPI_OCI_ERROR; dpiVar__assignCallbackBuffer(var, buffer, index, bufpp); if (buffer->actualLength32 || buffer->actualLength16) { if (!buffer->actualLength32) { if (dpiUtils__allocateMemory(buffer->maxArraySize, sizeof(uint32_t), 1, "allocate 11g lengths", (void**) &buffer->actualLength32, var->error) < 0) return DPI_OCI_ERROR; } buffer->actualLength32[index] = var->sizeInBytes; *alenpp = &(buffer->actualLength32[index]); } else if (*alenpp && var->type->sizeInBytes) **alenpp = var->type->sizeInBytes; if (buffer->objectIndicator) *indpp = buffer->objectIndicator[index]; else *indpp = &(buffer->indicator[index]); if (buffer->returnCode) *rcodepp = &buffer->returnCode[index]; } return DPI_OCI_CONTINUE; } //----------------------------------------------------------------------------- // dpiVar__setBytesFromDynamicBytes() [PRIVATE] // Set the pointer and length in the dpiBytes structure to the values // retrieved from the database. At this point, if multiple chunks exist, they // are combined into one. //----------------------------------------------------------------------------- static int dpiVar__setBytesFromDynamicBytes(dpiBytes *bytes, dpiDynamicBytes *dynBytes, dpiError *error) { uint32_t i, totalAllocatedLength; // if only one chunk is available, make use of it if (dynBytes->numChunks == 1) { bytes->ptr = dynBytes->chunks->ptr; bytes->length = dynBytes->chunks->length; return DPI_SUCCESS; } // determine total allocated size of all chunks totalAllocatedLength = 0; for (i = 0; i < dynBytes->numChunks; i++) totalAllocatedLength += dynBytes->chunks[i].allocatedLength; // allocate new memory consolidating all of the chunks if (dpiUtils__allocateMemory(1, totalAllocatedLength, 0, "allocate consolidated chunk", (void**) &bytes->ptr, error) < 0) return DPI_FAILURE; // copy memory from chunks to consolidated chunk bytes->length = 0; for (i = 0; i < dynBytes->numChunks; i++) { memcpy(bytes->ptr + bytes->length, dynBytes->chunks[i].ptr, dynBytes->chunks[i].length); bytes->length += dynBytes->chunks[i].length; dpiUtils__freeMemory(dynBytes->chunks[i].ptr); dynBytes->chunks[i].ptr = NULL; dynBytes->chunks[i].length = 0; dynBytes->chunks[i].allocatedLength = 0; } // populate first chunk with consolidated information dynBytes->numChunks = 1; dynBytes->chunks->ptr = bytes->ptr; dynBytes->chunks->length = bytes->length; dynBytes->chunks->allocatedLength = totalAllocatedLength; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setBytesFromLob() [PRIVATE] // Populate the dynamic bytes structure with the data from the LOB and then // populate the bytes structure. //----------------------------------------------------------------------------- static int dpiVar__setBytesFromLob(dpiBytes *bytes, dpiDynamicBytes *dynBytes, dpiLob *lob, dpiError *error) { uint64_t length, lengthInBytes, lengthReadInBytes; // determine length of LOB in bytes if (dpiOci__lobGetLength2(lob, &length, error) < 0) return DPI_FAILURE; if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_CLOB) lengthInBytes = length * lob->env->maxBytesPerCharacter; else if (lob->type->oracleTypeNum == DPI_ORACLE_TYPE_NCLOB) lengthInBytes = length * lob->env->nmaxBytesPerCharacter; else lengthInBytes = length; // ensure there is enough space to store the entire LOB value if (lengthInBytes > UINT_MAX) return dpiError__set(error, "check max length", DPI_ERR_NOT_SUPPORTED); if (dpiVar__allocateDynamicBytes(dynBytes, (uint32_t) lengthInBytes, error) < 0) return DPI_FAILURE; // read data from the LOB lengthReadInBytes = lengthInBytes; if (length > 0 && dpiLob__readBytes(lob, 1, length, dynBytes->chunks->ptr, &lengthReadInBytes, error) < 0) return DPI_FAILURE; dynBytes->chunks->length = (uint32_t) lengthReadInBytes; bytes->ptr = dynBytes->chunks->ptr; bytes->length = dynBytes->chunks->length; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromBytes() [PRIVATE] // Set the value of the variable at the given array position from a byte // string. The byte string is not retained in any way. A copy will be made into // buffers allocated by ODPI-C. //----------------------------------------------------------------------------- static int dpiVar__setFromBytes(dpiVar *var, uint32_t pos, const char *value, uint32_t valueLength, dpiError *error) { dpiData *data = &var->buffer.externalData[pos]; dpiDynamicBytes *dynBytes; dpiBytes *bytes; // for internally used LOBs, write the data directly if (var->buffer.references) { data->isNull = 0; return dpiLob__setFromBytes(var->buffer.references[pos].asLOB, value, valueLength, error); } // validate the target can accept the input if ((var->buffer.tempBuffer && var->env->charsetId == DPI_CHARSET_ID_UTF16 && valueLength > DPI_NUMBER_AS_TEXT_CHARS * 2) || (var->buffer.tempBuffer && var->env->charsetId != DPI_CHARSET_ID_UTF16 && valueLength > DPI_NUMBER_AS_TEXT_CHARS) || (!var->buffer.dynamicBytes && !var->buffer.tempBuffer && valueLength > var->sizeInBytes)) return dpiError__set(error, "check source length", DPI_ERR_BUFFER_SIZE_TOO_SMALL, var->sizeInBytes); // for dynamic bytes, allocate space as needed bytes = &data->value.asBytes; if (var->buffer.dynamicBytes) { dynBytes = &var->buffer.dynamicBytes[pos]; if (dpiVar__allocateDynamicBytes(dynBytes, valueLength, error) < 0) return DPI_FAILURE; if (valueLength > 0) memcpy(dynBytes->chunks->ptr, value, valueLength); dynBytes->numChunks = 1; dynBytes->chunks->length = valueLength; bytes->ptr = dynBytes->chunks->ptr; bytes->length = valueLength; // for everything else, space has already been allocated } else { bytes->length = valueLength; if (valueLength > 0) memcpy(bytes->ptr, value, valueLength); if (var->type->sizeInBytes == 0) { if (var->buffer.actualLength32) var->buffer.actualLength32[pos] = valueLength; else if (var->buffer.actualLength16) var->buffer.actualLength16[pos] = (uint16_t) valueLength; } if (var->buffer.returnCode) var->buffer.returnCode[pos] = 0; } data->isNull = 0; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromJson() [PRIVATE] // Set the value of the variable at the given array position from a JSON // value. A reference to the JSON value is retained by the variable. //----------------------------------------------------------------------------- static int dpiVar__setFromJson(dpiVar *var, uint32_t pos, dpiJson *json, dpiError *error) { dpiData *data; // validate the JSON value if (dpiGen__checkHandle(json, DPI_HTYPE_JSON, "check JSON", error) < 0) return DPI_FAILURE; // mark the value as not null data = &var->buffer.externalData[pos]; data->isNull = 0; // if values are the same, nothing to do if (var->buffer.references[pos].asJson == json) return DPI_SUCCESS; // clear original value, if needed if (var->buffer.references[pos].asJson) { dpiGen__setRefCount(var->buffer.references[pos].asJson, error, -1); var->buffer.references[pos].asJson = NULL; } // add reference to passed object dpiGen__setRefCount(json, error, 1); var->buffer.references[pos].asJson = json; var->buffer.data.asJsonDescriptor[pos] = json->handle; data->value.asJson = json; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromLob() [PRIVATE] // Set the value of the variable at the given array position from a LOB. // A reference to the LOB is retained by the variable. //----------------------------------------------------------------------------- static int dpiVar__setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob, dpiError *error) { dpiData *data; // validate the LOB object if (dpiGen__checkHandle(lob, DPI_HTYPE_LOB, "check LOB", error) < 0) return DPI_FAILURE; // mark the value as not null data = &var->buffer.externalData[pos]; data->isNull = 0; // if values are the same, nothing to do if (var->buffer.references[pos].asLOB == lob) return DPI_SUCCESS; // clear original value, if needed if (var->buffer.references[pos].asLOB) { dpiGen__setRefCount(var->buffer.references[pos].asLOB, error, -1); var->buffer.references[pos].asLOB = NULL; } // add reference to passed object dpiGen__setRefCount(lob, error, 1); var->buffer.references[pos].asLOB = lob; var->buffer.data.asLobLocator[pos] = lob->locator; data->value.asLOB = lob; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromObject() [PRIVATE] // Set the value of the variable at the given array position from an object. // The variable and position are assumed to be valid at this point. A reference // to the object is retained by the variable. //----------------------------------------------------------------------------- static int dpiVar__setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj, dpiError *error) { dpiData *data; // validate the object if (dpiGen__checkHandle(obj, DPI_HTYPE_OBJECT, "check obj", error) < 0) return DPI_FAILURE; if (obj->type->tdo != var->objectType->tdo) return dpiError__set(error, "check type", DPI_ERR_WRONG_TYPE, obj->type->schemaLength, obj->type->schema, obj->type->nameLength, obj->type->name, var->objectType->schemaLength, var->objectType->schema, var->objectType->nameLength, var->objectType->name); // mark the value as not null data = &var->buffer.externalData[pos]; data->isNull = 0; // if values are the same, nothing to do if (var->buffer.references[pos].asObject == obj) return DPI_SUCCESS; // clear original value, if needed if (var->buffer.references[pos].asObject) { dpiGen__setRefCount(var->buffer.references[pos].asObject, error, -1); var->buffer.references[pos].asObject = NULL; } // add reference to passed object dpiGen__setRefCount(obj, error, 1); var->buffer.references[pos].asObject = obj; var->buffer.data.asObject[pos] = obj->instance; var->buffer.objectIndicator[pos] = obj->indicator; data->value.asObject = obj; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromRowid() [PRIVATE] // Set the value of the variable at the given array position from a rowid. // A reference to the rowid is retained by the variable. //----------------------------------------------------------------------------- static int dpiVar__setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid, dpiError *error) { dpiData *data; // validate the rowid if (dpiGen__checkHandle(rowid, DPI_HTYPE_ROWID, "check rowid", error) < 0) return DPI_FAILURE; // mark the value as not null data = &var->buffer.externalData[pos]; data->isNull = 0; // if values are the same, nothing to do if (var->buffer.references[pos].asRowid == rowid) return DPI_SUCCESS; // clear original value, if needed if (var->buffer.references[pos].asRowid) { dpiGen__setRefCount(var->buffer.references[pos].asRowid, error, -1); var->buffer.references[pos].asRowid = NULL; } // add reference to passed object dpiGen__setRefCount(rowid, error, 1); var->buffer.references[pos].asRowid = rowid; var->buffer.data.asRowid[pos] = rowid->handle; data->value.asRowid = rowid; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromStmt() [PRIVATE] // Set the value of the variable at the given array position from a // statement. A reference to the statement is retained by the variable. //----------------------------------------------------------------------------- static int dpiVar__setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt, dpiError *error) { dpiData *data; uint32_t i; // validate the statement if (dpiGen__checkHandle(stmt, DPI_HTYPE_STMT, "check stmt", error) < 0) return DPI_FAILURE; // prevent attempts to bind a statement to itself for (i = 0; i < stmt->numBindVars; i++) { if (stmt->bindVars[i].var == var) return dpiError__set(error, "bind to self", DPI_ERR_NOT_SUPPORTED); } // mark the value as not null data = &var->buffer.externalData[pos]; data->isNull = 0; // if values are the same, nothing to do if (var->buffer.references[pos].asStmt == stmt) return DPI_SUCCESS; // clear original value, if needed if (var->buffer.references[pos].asStmt) { dpiGen__setRefCount(var->buffer.references[pos].asStmt, error, -1); var->buffer.references[pos].asStmt = NULL; } // add reference to passed object dpiGen__setRefCount(stmt, error, 1); var->buffer.references[pos].asStmt = stmt; var->buffer.data.asStmt[pos] = stmt->handle; data->value.asStmt = stmt; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setFromVector() [PRIVATE] // Set the value of the variable at the given array position from a vector // value. A reference to the vector value is retained by the variable. //----------------------------------------------------------------------------- static int dpiVar__setFromVector(dpiVar *var, uint32_t pos, dpiVector *vector, dpiError *error) { dpiData *data; // validate the vector value if (dpiGen__checkHandle(vector, DPI_HTYPE_VECTOR, "check vector", error) < 0) return DPI_FAILURE; // mark the value as not null data = &var->buffer.externalData[pos]; data->isNull = 0; // if values are the same, nothing to do if (var->buffer.references[pos].asVector == vector) return DPI_SUCCESS; // clear original value, if needed if (var->buffer.references[pos].asVector) { dpiGen__setRefCount(var->buffer.references[pos].asVector, error, -1); var->buffer.references[pos].asVector = NULL; } // add reference to passed object dpiGen__setRefCount(vector, error, 1); var->buffer.references[pos].asVector = vector; var->buffer.data.asVectorDescriptor[pos] = vector->handle; data->value.asVector = vector; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__setValue() [PRIVATE] // Sets the contents of the variable using the type specified, if possible. //----------------------------------------------------------------------------- int dpiVar__setValue(dpiVar *var, dpiVarBuffer *buffer, uint32_t pos, dpiData *data, dpiError *error) { dpiOracleTypeNum oracleTypeNum; dpiObject *obj; // if value is null, no need to proceed further // however, when binding objects a value MUST be present or OCI will // segfault! if (data->isNull) { buffer->indicator[pos] = DPI_OCI_IND_NULL; if (buffer->objectIndicator && !buffer->data.asObject[pos]) { if (dpiObject__allocate(var->objectType, NULL, NULL, NULL, &obj, error) < 0) return DPI_FAILURE; buffer->references[pos].asObject = obj; data->value.asObject = obj; buffer->data.asObject[pos] = obj->instance; buffer->objectIndicator[pos] = obj->indicator; if (buffer->objectIndicator[pos]) *((int16_t*) buffer->objectIndicator[pos]) = DPI_OCI_IND_NULL; } return DPI_SUCCESS; } // transform the various types buffer->indicator[pos] = DPI_OCI_IND_NOTNULL; oracleTypeNum = var->type->oracleTypeNum; switch (var->nativeTypeNum) { case DPI_NATIVE_TYPE_INT64: case DPI_NATIVE_TYPE_UINT64: switch (oracleTypeNum) { case DPI_ORACLE_TYPE_NATIVE_INT: buffer->data.asInt64[pos] = data->value.asInt64; return DPI_SUCCESS; case DPI_ORACLE_TYPE_NATIVE_UINT: buffer->data.asUint64[pos] = data->value.asUint64; return DPI_SUCCESS; case DPI_ORACLE_TYPE_NUMBER: if (var->nativeTypeNum == DPI_NATIVE_TYPE_INT64) return dpiDataBuffer__toOracleNumberFromInteger( &data->value, error, &buffer->data.asNumber[pos]); return dpiDataBuffer__toOracleNumberFromUnsignedInteger( &data->value, error, &buffer->data.asNumber[pos]); default: break; } break; case DPI_NATIVE_TYPE_FLOAT: buffer->data.asFloat[pos] = data->value.asFloat; return DPI_SUCCESS; case DPI_NATIVE_TYPE_DOUBLE: switch (oracleTypeNum) { case DPI_ORACLE_TYPE_NATIVE_DOUBLE: buffer->data.asDouble[pos] = data->value.asDouble; return DPI_SUCCESS; case DPI_ORACLE_TYPE_NUMBER: return dpiDataBuffer__toOracleNumberFromDouble( &data->value, error, &buffer->data.asNumber[pos]); case DPI_ORACLE_TYPE_DATE: return dpiDataBuffer__toOracleDateFromDouble( &data->value, var->env, error, &buffer->data.asDate[pos]); case DPI_ORACLE_TYPE_TIMESTAMP: case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: return dpiDataBuffer__toOracleTimestampFromDouble( &data->value, oracleTypeNum, var->env, error, buffer->data.asTimestamp[pos]); default: break; } break; case DPI_NATIVE_TYPE_BYTES: if (oracleTypeNum == DPI_ORACLE_TYPE_NUMBER) return dpiDataBuffer__toOracleNumberFromText(&data->value, var->env, error, &buffer->data.asNumber[pos]); if (buffer->actualLength32) buffer->actualLength32[pos] = data->value.asBytes.length; else if (buffer->actualLength16) buffer->actualLength16[pos] = (uint16_t) data->value.asBytes.length; if (buffer->returnCode) buffer->returnCode[pos] = 0; break; case DPI_NATIVE_TYPE_TIMESTAMP: if (oracleTypeNum == DPI_ORACLE_TYPE_DATE) return dpiDataBuffer__toOracleDate(&data->value, &buffer->data.asDate[pos]); else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP) return dpiDataBuffer__toOracleTimestamp(&data->value, var->env, error, buffer->data.asTimestamp[pos], 0); else if (oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_TZ || oracleTypeNum == DPI_ORACLE_TYPE_TIMESTAMP_LTZ) return dpiDataBuffer__toOracleTimestamp(&data->value, var->env, error, buffer->data.asTimestamp[pos], 1); break; case DPI_NATIVE_TYPE_INTERVAL_DS: return dpiDataBuffer__toOracleIntervalDS(&data->value, var->env, error, buffer->data.asInterval[pos]); case DPI_NATIVE_TYPE_INTERVAL_YM: return dpiDataBuffer__toOracleIntervalYM(&data->value, var->env, error, buffer->data.asInterval[pos]); case DPI_NATIVE_TYPE_BOOLEAN: buffer->data.asBoolean[pos] = data->value.asBoolean; return DPI_SUCCESS; case DPI_NATIVE_TYPE_STMT: return dpiOci__attrSet(data->value.asStmt->handle, DPI_OCI_HTYPE_STMT, &data->value.asStmt->prefetchRows, sizeof(data->value.asStmt->prefetchRows), DPI_OCI_ATTR_PREFETCH_ROWS, "set prefetch rows for REF cursor", error); default: break; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVar__validateTypes() [PRIVATE] // Validate that the Oracle type and the native type are compatible with // each other when the native type is not already the default native type. //----------------------------------------------------------------------------- static int dpiVar__validateTypes(const dpiOracleType *oracleType, dpiNativeTypeNum nativeTypeNum, dpiError *error) { switch (oracleType->oracleTypeNum) { case DPI_ORACLE_TYPE_DATE: case DPI_ORACLE_TYPE_TIMESTAMP: case DPI_ORACLE_TYPE_TIMESTAMP_TZ: case DPI_ORACLE_TYPE_TIMESTAMP_LTZ: if (nativeTypeNum == DPI_NATIVE_TYPE_DOUBLE) return DPI_SUCCESS; break; case DPI_ORACLE_TYPE_NUMBER: if (nativeTypeNum == DPI_NATIVE_TYPE_INT64 || nativeTypeNum == DPI_NATIVE_TYPE_UINT64 || nativeTypeNum == DPI_NATIVE_TYPE_BYTES) return DPI_SUCCESS; break; default: break; } return dpiError__set(error, "validate types", DPI_ERR_UNHANDLED_CONVERSION, oracleType->oracleTypeNum, nativeTypeNum); } //----------------------------------------------------------------------------- // dpiVar_addRef() [PUBLIC] // Add a reference to the variable. //----------------------------------------------------------------------------- int dpiVar_addRef(dpiVar *var) { return dpiGen__addRef(var, DPI_HTYPE_VAR, __func__); } //----------------------------------------------------------------------------- // dpiVar_copyData() [PUBLIC] // Copy the data from the source variable to the target variable at the given // array position. The variables must use the same native type. If the // variables contain variable length data, the source length must not exceed // the target allocated memory. //----------------------------------------------------------------------------- int dpiVar_copyData(dpiVar *var, uint32_t pos, dpiVar *sourceVar, uint32_t sourcePos) { dpiData *sourceData; dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (dpiGen__checkHandle(sourceVar, DPI_HTYPE_VAR, "check source var", &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (sourcePos >= sourceVar->buffer.maxArraySize) { dpiError__set(&error, "check source size", DPI_ERR_INVALID_ARRAY_POSITION, sourcePos, sourceVar->buffer.maxArraySize); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } if (var->nativeTypeNum != sourceVar->nativeTypeNum) { dpiError__set(&error, "check types match", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } sourceData = &sourceVar->buffer.externalData[sourcePos]; status = dpiVar__copyData(var, pos, sourceData, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_getNumElementsInArray() [PUBLIC] // Return the actual number of elements in the array. This value is only // relevant if the variable is bound as an array. //----------------------------------------------------------------------------- int dpiVar_getNumElementsInArray(dpiVar *var, uint32_t *numElements) { dpiError error; if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(var, numElements) if (var->dynBindBuffers) *numElements = var->dynBindBuffers->actualArraySize; else *numElements = var->buffer.actualArraySize; return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiVar_getReturnedData() [PUBLIC] // Return a pointer to the array of dpiData structures allocated for the // given row that have been returned by a DML returning statement. The number // of returned rows is also provided. If the bind variable had no data // returned, the number of rows returned will be 0 and the pointer to the array // of dpiData structures will be NULL. This will also be the case if the // variable was only bound IN or was not bound to a DML returning statement. // There is no way to differentiate between the two. //----------------------------------------------------------------------------- int dpiVar_getReturnedData(dpiVar *var, uint32_t pos, uint32_t *numElements, dpiData **data) { dpiError error; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(var, numElements) DPI_CHECK_PTR_NOT_NULL(var, data) if (var->dynBindBuffers) { *numElements = var->dynBindBuffers[pos].actualArraySize; *data = var->dynBindBuffers[pos].externalData; } else { *numElements = 0; *data = NULL; } return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiVar_getSizeInBytes() [PUBLIC] // Returns the size in bytes of the buffer allocated for the variable. //----------------------------------------------------------------------------- int dpiVar_getSizeInBytes(dpiVar *var, uint32_t *sizeInBytes) { dpiError error; if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); DPI_CHECK_PTR_NOT_NULL(var, sizeInBytes) *sizeInBytes = var->sizeInBytes; return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); } //----------------------------------------------------------------------------- // dpiVar_release() [PUBLIC] // Release a reference to the variable. //----------------------------------------------------------------------------- int dpiVar_release(dpiVar *var) { return dpiGen__release(var, DPI_HTYPE_VAR, __func__); } //----------------------------------------------------------------------------- // dpiVar_setFromBytes() [PUBLIC] // Set the value of the variable at the given array position from a byte // string. Checks on the array position, the size of the string and the type of // variable will be made. The byte string is not retained in any way. A copy // will be made into buffers allocated by ODPI-C. //----------------------------------------------------------------------------- int dpiVar_setFromBytes(dpiVar *var, uint32_t pos, const char *value, uint32_t valueLength) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); DPI_CHECK_PTR_AND_LENGTH(var, value) if (var->nativeTypeNum != DPI_NATIVE_TYPE_BYTES && var->nativeTypeNum != DPI_NATIVE_TYPE_LOB) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } if (valueLength > DPI_MAX_VAR_BUFFER_SIZE) { dpiError__set(&error, "check buffer", DPI_ERR_BUFFER_SIZE_TOO_LARGE, valueLength, DPI_MAX_VAR_BUFFER_SIZE); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromBytes(var, pos, value, valueLength, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setFromJson() [PUBLIC] // Set the value of the variable at the given position from a JSON value. // Checks on the array position and the validity of the passed value. // A reference to the JSON value is retained by the variable. //----------------------------------------------------------------------------- int dpiVar_setFromJson( dpiVar *var, uint32_t pos, dpiJson *json) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (var->nativeTypeNum != DPI_NATIVE_TYPE_JSON) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromJson(var, pos, json, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setFromLob() [PUBLIC] // Set the value of the variable at the given array position from a LOB. // Checks on the array position and the validity of the passed handle. A // reference to the LOB is retained by the variable. //----------------------------------------------------------------------------- int dpiVar_setFromLob(dpiVar *var, uint32_t pos, dpiLob *lob) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (var->nativeTypeNum != DPI_NATIVE_TYPE_LOB) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromLob(var, pos, lob, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setFromObject() [PUBLIC] // Set the value of the variable at the given array position from an object. // Checks on the array position and the validity of the passed handle. A // reference to the object is retained by the variable. //----------------------------------------------------------------------------- int dpiVar_setFromObject(dpiVar *var, uint32_t pos, dpiObject *obj) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (var->nativeTypeNum != DPI_NATIVE_TYPE_OBJECT) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromObject(var, pos, obj, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setFromRowid() [PUBLIC] // Set the value of the variable at the given array position from a rowid. // Checks on the array position and the validity of the passed handle. A // reference to the rowid is retained by the variable. //----------------------------------------------------------------------------- int dpiVar_setFromRowid(dpiVar *var, uint32_t pos, dpiRowid *rowid) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (var->nativeTypeNum != DPI_NATIVE_TYPE_ROWID) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromRowid(var, pos, rowid, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setFromStmt() [PUBLIC] // Set the value of the variable at the given array position from a // statement. Checks on the array position and the validity of the passed // handle. A reference to the statement is retained by the variable. //----------------------------------------------------------------------------- int dpiVar_setFromStmt(dpiVar *var, uint32_t pos, dpiStmt *stmt) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (var->nativeTypeNum != DPI_NATIVE_TYPE_STMT) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromStmt(var, pos, stmt, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setFromVector() [PUBLIC] // Set the value of the variable at the given position from a vector value. // Checks on the array position and the validity of the passed value. // A reference to the vector value is retained by the variable. //----------------------------------------------------------------------------- int dpiVar_setFromVector(dpiVar *var, uint32_t pos, dpiVector *vector) { dpiError error; int status; if (dpiVar__checkArraySize(var, pos, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (var->nativeTypeNum != DPI_NATIVE_TYPE_VECTOR) { dpiError__set(&error, "native type", DPI_ERR_NOT_SUPPORTED); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } status = dpiVar__setFromVector(var, pos, vector, &error); return dpiGen__endPublicFn(var, status, &error); } //----------------------------------------------------------------------------- // dpiVar_setNumElementsInArray() [PUBLIC] // Set the number of elements in the array (different from the number of // allocated elements). //----------------------------------------------------------------------------- int dpiVar_setNumElementsInArray(dpiVar *var, uint32_t numElements) { dpiError error; if (dpiGen__startPublicFn(var, DPI_HTYPE_VAR, __func__, &error) < 0) return dpiGen__endPublicFn(var, DPI_FAILURE, &error); if (numElements > var->buffer.maxArraySize) { dpiError__set(&error, "check num elements", DPI_ERR_ARRAY_SIZE_TOO_SMALL, var->buffer.maxArraySize); return dpiGen__endPublicFn(var, DPI_FAILURE, &error); } var->buffer.actualArraySize = numElements; return dpiGen__endPublicFn(var, DPI_SUCCESS, &error); } odpi-5.6.4/src/dpiVector.c000066400000000000000000000224121510466437300153650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2024, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // dpiVector.c // Implementation of vector manipulation routines. //----------------------------------------------------------------------------- #include "dpiImpl.h" // forward declarations of internal functions only used in this file static void dpiVector__clearDimensions(dpiVector *vector); //----------------------------------------------------------------------------- // dpiVector__allocate() [INTERNAL] // Allocate and initialize a vector object. //----------------------------------------------------------------------------- int dpiVector__allocate(dpiConn *conn, dpiVector **vector, dpiError *error) { dpiVector *tempVector; if (dpiUtils__checkClientVersion(conn->env->versionInfo, 23, 4, error) < 0) return DPI_FAILURE; if (dpiGen__allocate(DPI_HTYPE_VECTOR, conn->env, (void**) &tempVector, error) < 0) return DPI_FAILURE; dpiGen__setRefCount(conn, error, 1); tempVector->conn = conn; if (dpiOci__descriptorAlloc(conn->env->handle, &tempVector->handle, DPI_OCI_DTYPE_VECTOR, "allocate vector descriptor", error) < 0) { dpiVector__free(tempVector, error); return DPI_FAILURE; } *vector = tempVector; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVector__clearDimensions() [INTERNAL] // Clear the dimensions cached in the vector. //----------------------------------------------------------------------------- static void dpiVector__clearDimensions(dpiVector *vector) { if (vector->dimensions) { dpiUtils__freeMemory(vector->dimensions); vector->dimensions = NULL; } } //----------------------------------------------------------------------------- // dpiVector__free() [INTERNAL] // Free the vector object contents. //----------------------------------------------------------------------------- void dpiVector__free(dpiVector *vector, dpiError *error) { if (vector->handle) { dpiOci__descriptorFree(vector->handle, DPI_OCI_DTYPE_VECTOR); vector->handle = NULL; } if (vector->conn) { dpiGen__setRefCount(vector->conn, error, -1); vector->conn = NULL; } dpiVector__clearDimensions(vector); dpiUtils__freeMemory(vector); } //----------------------------------------------------------------------------- // dpiVector__getValue() [INTERNAL] // Gets information about the vector. //----------------------------------------------------------------------------- int dpiVector__getValue(dpiVector *vector, dpiVectorInfo *info, dpiError *error) { uint32_t numElements, flags; // only need to acquire information if it was not already cached if (!vector->dimensions) { // determine the format of the vector if (dpiOci__attrGet(vector->handle, DPI_OCI_DTYPE_VECTOR, &vector->format, 0, DPI_OCI_ATTR_VECTOR_DATA_FORMAT, "get vector format", error) < 0) return DPI_FAILURE; // determine the number of dimensions in the vector if (dpiOci__attrGet(vector->handle, DPI_OCI_DTYPE_VECTOR, &vector->numDimensions, 0, DPI_OCI_ATTR_VECTOR_DIMENSION, "get number of vector dimensions", error) < 0) return DPI_FAILURE; // determine the size of each dimension numElements = vector->numDimensions; switch (vector->format) { case DPI_VECTOR_FORMAT_BINARY: vector->dimensionSize = sizeof(uint8_t); numElements = (uint32_t) (vector->numDimensions / 8); break; case DPI_VECTOR_FORMAT_FLOAT32: vector->dimensionSize = sizeof(float); break; case DPI_VECTOR_FORMAT_FLOAT64: vector->dimensionSize = sizeof(double); break; case DPI_VECTOR_FORMAT_INT8: vector->dimensionSize = sizeof(int8_t); break; default: return dpiError__set(error, "check vector format", DPI_ERR_UNSUPPORTED_VECTOR_FORMAT, vector->format); } // determine if the vector is SPARSE or DENSE if (dpiOci__attrGet(vector->handle, DPI_OCI_DTYPE_VECTOR, &flags, 0, DPI_OCI_ATTR_VECTOR_PROPERTY, "get vector flags", error) < 0) return DPI_FAILURE; // if vector is sparse, determine the number of sparse dimensions if (flags & DPI_OCI_ATTR_VECTOR_COL_PROPERTY_IS_SPARSE) { if (dpiOci__attrGet(vector->handle, DPI_OCI_DTYPE_VECTOR, &vector->numSparseValues, 0, DPI_OCI_ATTR_VECTOR_SPARSE_DIMENSION, "get number of sparse vector dimensions", error) < 0) return DPI_FAILURE; numElements = vector->numSparseValues; if (dpiUtils__allocateMemory(numElements, sizeof(uint32_t), 0, "allocate sparse vector indices", (void**) &vector->sparseIndices, error) < 0) return DPI_FAILURE; // otherwise, clear the sparse vector members } else { vector->numSparseValues = 0; vector->sparseIndices = NULL; } // allocate a buffer for the dimensions if (dpiUtils__allocateMemory(numElements, vector->dimensionSize, 0, "allocate vector dimensions", &vector->dimensions, error) < 0) return DPI_FAILURE; // populate buffer with array data if (vector->numSparseValues > 0) { if (dpiOci__vectorToSparseArray(vector, error) < 0) return DPI_FAILURE; } else { if (dpiOci__vectorToArray(vector, error) < 0) return DPI_FAILURE; } } // transfer cached information to the output structure info->format = vector->format; info->numDimensions = vector->numDimensions; info->dimensionSize = vector->dimensionSize; info->dimensions.asPtr = vector->dimensions; info->numSparseValues = vector->numSparseValues; info->sparseIndices = vector->sparseIndices; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiVector_addRef() [PUBLIC] // Add a reference to the vector object. //----------------------------------------------------------------------------- int dpiVector_addRef(dpiVector *vector) { return dpiGen__addRef(vector, DPI_HTYPE_VECTOR, __func__); } //----------------------------------------------------------------------------- // dpiVector_getValue() [PUBLIC] // Returns information about the vector to the caller. //----------------------------------------------------------------------------- int dpiVector_getValue(dpiVector *vector, dpiVectorInfo *info) { dpiError error; int status; if (dpiGen__startPublicFn(vector, DPI_HTYPE_VECTOR, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(vector, info) status = dpiVector__getValue(vector, info, &error); return dpiGen__endPublicFn(vector, status, &error); } //----------------------------------------------------------------------------- // dpiVector_release() [PUBLIC] // Release a reference to the vector object. //----------------------------------------------------------------------------- int dpiVector_release(dpiVector *vector) { return dpiGen__release(vector, DPI_HTYPE_VECTOR, __func__); } //----------------------------------------------------------------------------- // dpiVector_setValue() [PUBLIC] // Sets the vector value from the supplied information. //----------------------------------------------------------------------------- int dpiVector_setValue(dpiVector *vector, dpiVectorInfo *info) { dpiError error; int status; if (dpiGen__startPublicFn(vector, DPI_HTYPE_VECTOR, __func__, &error) < 0) return DPI_FAILURE; DPI_CHECK_PTR_NOT_NULL(vector, info) if (info->numSparseValues > 0) { status = dpiOci__vectorFromSparseArray(vector, info, &error); } else { status = dpiOci__vectorFromArray(vector, info, &error); } return dpiGen__endPublicFn(vector, status, &error); } odpi-5.6.4/test/000077500000000000000000000000001510466437300134515ustar00rootroot00000000000000odpi-5.6.4/test/Makefile000066400000000000000000000054721510466437300151210ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2016, 2025, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #------------------------------------------------------------------------------ # # Sample Makefile if you wish to build the ODPI-C test executables. # # Look at README.md for information on how to build and run the tests. #------------------------------------------------------------------------------ BUILD_DIR = build INCLUDE_DIR = ../include LIB_DIR = ../lib CC = gcc LD = gcc CFLAGS = -I$(INCLUDE_DIR) -O2 -g -Wall LIBS = -L$(LIB_DIR) -lodpic COMMON_OBJS = $(BUILD_DIR)/TestLib.o SOURCES = TestSuiteRunner.c \ test_1000_context.c \ test_1100_numbers.c \ test_1200_conn.c \ test_1300_conn_properties.c \ test_1400_pool.c \ test_1500_pool_properties.c \ test_1600_queries.c \ test_1700_transactions.c \ test_1800_misc.c \ test_1900_variables.c \ test_2000_statements.c \ test_2100_data_types.c \ test_2200_object_types.c \ test_2300_objects.c \ test_2400_enq_options.c \ test_2500_deq_options.c \ test_2600_msg_props.c \ test_2700_aq.c \ test_2800_lobs.c \ test_2900_implicit_results.c \ test_3000_scroll_cursors.c \ test_3100_subscriptions.c \ test_3200_batch_errors.c \ test_3300_dml_returning.c \ test_3400_soda_db.c \ test_3500_soda_coll.c \ test_3600_soda_coll_cursor.c \ test_3700_soda_doc.c \ test_3800_soda_doc_cursor.c \ test_3900_sess_tags.c \ test_4000_queue.c \ test_4100_binds.c \ test_4200_rowids.c \ test_4300_json.c \ test_4400_vector.c \ test_4500_sessionless_txn.c BINARIES = $(SOURCES:%.c=$(BUILD_DIR)/%) all: $(BUILD_DIR) $(BINARIES) clean: rm -rf $(BUILD_DIR) $(BUILD_DIR): mkdir -p $@ $(BUILD_DIR)/%.o: %.c TestLib.h $(CC) -c $(CFLAGS) -o $@ $< $(BUILD_DIR)/%: $(BUILD_DIR)/%.o $(COMMON_OBJS) $(LD) $(LDFLAGS) $< -o $@ $(COMMON_OBJS) $(LIBS) odpi-5.6.4/test/Makefile.win32000066400000000000000000000067331510466437300160630ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2017, 2025, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #------------------------------------------------------------------------------ # # Sample nmake Makefile if you wish to build the ODPI-C test executables. # # Look at README.md for information on how to build and run the tests. #------------------------------------------------------------------------------ BUILD_DIR = build INCLUDE_DIR = ..\include LIB_DIR = ..\lib LIBS = $(LIB_DIR)\odpic.lib COMMON_OBJS = $(BUILD_DIR)\TestLib.obj EXES = $(BUILD_DIR)\test_1000_context.exe \ $(BUILD_DIR)\test_1100_numbers.exe \ $(BUILD_DIR)\test_1200_conn.exe \ $(BUILD_DIR)\test_1300_conn_properties.exe \ $(BUILD_DIR)\test_1400_pool.exe \ $(BUILD_DIR)\test_1500_pool_properties.exe \ $(BUILD_DIR)\test_1600_queries.exe \ $(BUILD_DIR)\test_1700_transactions.exe \ $(BUILD_DIR)\test_1800_misc.exe \ $(BUILD_DIR)\test_1900_variables.exe \ $(BUILD_DIR)\test_2000_statements.exe \ $(BUILD_DIR)\test_2100_data_types.exe \ $(BUILD_DIR)\test_2200_object_types.exe \ $(BUILD_DIR)\test_2300_objects.exe \ $(BUILD_DIR)\test_2400_enq_options.exe \ $(BUILD_DIR)\test_2500_deq_options.exe \ $(BUILD_DIR)\test_2600_msg_props.exe \ $(BUILD_DIR)\test_2700_aq.exe \ $(BUILD_DIR)\test_2800_lobs.exe \ $(BUILD_DIR)\test_2900_implicit_results.exe \ $(BUILD_DIR)\test_3000_scroll_cursors.exe \ $(BUILD_DIR)\test_3100_subscriptions.exe \ $(BUILD_DIR)\test_3200_batch_errors.exe \ $(BUILD_DIR)\test_3300_dml_returning.exe \ $(BUILD_DIR)\test_3400_soda_db.exe \ $(BUILD_DIR)\test_3500_soda_coll.exe \ $(BUILD_DIR)\test_3600_soda_coll_cursor.exe \ $(BUILD_DIR)\test_3700_soda_doc.exe \ $(BUILD_DIR)\test_3800_soda_doc_cursor.exe \ $(BUILD_DIR)\test_3900_sess_tags.exe \ $(BUILD_DIR)\test_4000_queue.exe \ $(BUILD_DIR)\test_4100_binds.exe \ $(BUILD_DIR)\test_4200_rowids.exe \ $(BUILD_DIR)\test_4300_json.exe \ $(BUILD_DIR)\test_4400_vector.exe \ $(BUILD_DIR)\test_4500_sessionless_txn.exe \ $(BUILD_DIR)\TestSuiteRunner.exe all: $(EXES) $(BUILD_DIR) $(EXES): $(BUILD_DIR) $(COMMON_OBJS) $*.obj clean: @if exist $(BUILD_DIR) rmdir /S /Q $(BUILD_DIR) $(BUILD_DIR): @if not exist $(BUILD_DIR) mkdir $(BUILD_DIR) {.}.c{$(BUILD_DIR)}.obj :: cl /nologo /c /Fo$(BUILD_DIR)\ /I$(INCLUDE_DIR) $< {$(BUILD_DIR)}.obj{$(BUILD_DIR)}.exe: link /nologo /out:$@ $< $(COMMON_OBJS) $(LIBS) odpi-5.6.4/test/README.md000066400000000000000000000042101510466437300147250ustar00rootroot00000000000000This directory contains tests for ODPI-C. All of the test executables are built using the supplied Makefile (Makefile.win32 for use with nmake on Windows). The test executables will be placed in the subdirectory "build". See the top level [README](../README.md) for the platforms and compilers that have been tested and are known to work. To run the tests: - Ensure that installation of the ODPI-C library has been completed as explained [here](https://oracle.github.io/odpi/doc/installation.html). - Optionally edit the file sql/TestEnv.sql and edit the parameters defined there. If you don't change any of the parameters, make the sure the schemas odpic and odpic_proxy can be dropped. If you do edit the parameters defined there, also set the corresponding environment variables indicated on the right of the defined variable. - Optionally set the environment variable ODPIC_TEST_CONNECT_STRING to point to the database in which you plan to run the tests. If this environment variable is not set, the connect string will be assumed to be the EZ connect string "localhost/orclpdb". - Run 'make clean' and 'make' to build the tests - Run SQL\*Plus as SYSDBA and create the test suite SQL objects with sql/SetupTest.sql. The syntax is: sqlplus sys/syspassword@hostname/servicename as sysdba @SetupTest - Change to the 'build' directory and run the TestSuiteRunner executable found there. It will run all of the tests in the other executables and report on success or failure when it finishes running all of the tests. On Linux you will need to set LD_LIBRARY_PATH to point to the location of the library, as in: LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../lib ./TestSuiteRunner - After running the tests, drop the SQL objects by running the script sql/DropTest.sql. The syntax is: sqlplus sys/syspassword@hostname/servicename as sysdba @DropTest NOTES: - if you are using the BEQ connection method (setting the environment variable ORACLE_SID and using an empty connection string) then you will need to add the configuration bequeath_detach=yes to your sqlnet.ora file odpi-5.6.4/test/TestLib.c000066400000000000000000001116041510466437300151660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // TestLib.c // Common code used by all test cases. //----------------------------------------------------------------------------- #include "TestLib.h" // global test suite static dpiTestSuite gTestSuite; // global DPI context used for most test cases static dpiContext *gContext = NULL; // global common creation parameters used for creating connections and pools static dpiCommonCreateParams gCommonCreateParams; // global Oracle version information static dpiVersionInfo gClientVersionInfo; static dpiVersionInfo gDatabaseVersionInfo; static int gDatabaseVersionAcquired = 0; //----------------------------------------------------------------------------- // dpiTestCase__cleanUp() [PUBLIC] // Frees the memory used by connections and pools established by the test // case. //----------------------------------------------------------------------------- static void dpiTestCase__cleanUp(dpiTestCase *testCase) { if (testCase->conn) { dpiConn_release(testCase->conn); testCase->conn = NULL; } if (testCase->adminConn) { dpiConn_release(testCase->adminConn); testCase->adminConn = NULL; } } //----------------------------------------------------------------------------- // dpiTestSuite__fatalError() [INTERNAL] // Called when a fatal error is encountered from which recovery is not // possible. This simply prints a message to stderr and exits the program with // a non-zero exit code to indicate an error. //----------------------------------------------------------------------------- static void dpiTestSuite__fatalError(const char *message) { fprintf(stderr, "FATAL: %s\n", message); exit(1); } //----------------------------------------------------------------------------- // dpiTestSuite__fatalDPIError() [INTERNAL] // Called when a fatal DPI error is encountered from which recovery is not // possible. This simply prints the ODPI-C error information to stderr and // exits the program with a non-zero exit code to indicate an error. //----------------------------------------------------------------------------- static void dpiTestSuite__fatalDPIError(dpiErrorInfo *errorInfo, const char *message) { fprintf(stderr, "FN: %s\n", errorInfo->fnName); fprintf(stderr, "ACTION: %s\n", errorInfo->action); fprintf(stderr, "MSG: %.*s\n", errorInfo->messageLength, errorInfo->message); dpiTestSuite__fatalError(message); } //----------------------------------------------------------------------------- // dpiTestSuite__getEnvValue() [PUBLIC] // Get value from environment or use supplied default value if the value is // not set in the environment. Memory is allocated to accommodate the value and // optionally converted to upper case. //----------------------------------------------------------------------------- static void dpiTestSuite__getEnvValue(const char *envName, const char *defaultValue, const char **value, uint32_t *valueLength, int convertToUpper) { const char *source; uint32_t i; char *ptr; source = getenv(envName); if (!source) source = defaultValue; *value = NULL; *valueLength = strlen(source); if (*valueLength > 0) { *value = malloc(*valueLength); if (!*value) dpiTestSuite__fatalError("Out of memory!"); memcpy((void*) *value, source, *valueLength); if (convertToUpper) { ptr = (char*) *value; for (i = 0; i < *valueLength; i++) ptr[i] = toupper(ptr[i]); } } } //----------------------------------------------------------------------------- // dpiTestCase_cleanupSodaColl() // Drops the collection (and verifies that it was actually dropped), then // releases the collection. //----------------------------------------------------------------------------- int dpiTestCase_cleanupSodaColl(dpiTestCase *testCase, dpiSodaColl *coll) { int isDropped; if (dpiSodaColl_drop(coll, DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isDropped, 1) < 0) return DPI_FAILURE; if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_dropAllSodaColls() // Drops all collections in the database. //----------------------------------------------------------------------------- int dpiTestCase_dropAllSodaColls(dpiTestCase *testCase, dpiSodaDb *db) { dpiSodaCollCursor *cursor; dpiSodaColl *coll; int isDropped; // create cursor if (dpiSodaDb_getCollections(db, NULL, 0, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiTestCase_setFailedFromError(testCase); // iterate over all collections and drop them while (1) { if (dpiSodaCollCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (!coll) break; if (dpiSodaColl_drop(coll, DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiSodaCollCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_expectAnyError() [PUBLIC] // Check to see that any of the error message prefixes provided matches the // actual error returned. //----------------------------------------------------------------------------- int dpiTestCase_expectAnyError(dpiTestCase *testCase, const char **expectedErrors) { dpiErrorInfo errorInfo; dpiTestSuite_getErrorInfo(&errorInfo); return dpiTestCase_expectAnyErrorInfo(testCase, &errorInfo, expectedErrors); } //----------------------------------------------------------------------------- // dpiTestCase_expectAnyErrorInfo() [PUBLIC] // Check to see that any of the error message prefixes provided matches the // actual error returned. //----------------------------------------------------------------------------- int dpiTestCase_expectAnyErrorInfo(dpiTestCase *testCase, const dpiErrorInfo *errorInfo, const char **expectedErrors) { uint32_t expectedErrorLength, i; size_t messageLength; char message[512]; if (errorInfo->messageLength == 0) { messageLength = sizeof(message); messageLength -= snprintf(message, messageLength, "Expected error starting with: '%s'", expectedErrors[0]); for (i = 1; ; i++) { if (expectedErrors[i] == NULL) break; messageLength -= snprintf(message + strlen(message), messageLength, " or '%s'", expectedErrors[i]); } return dpiTestCase_setFailed(testCase, message); } for (i = 0; ; i++) { if (expectedErrors[i] == NULL) break; expectedErrorLength = strlen(expectedErrors[i]); if (strncmp(errorInfo->message, expectedErrors[i], expectedErrorLength) == 0) return DPI_SUCCESS; } messageLength = sizeof(message); messageLength -= snprintf(message, messageLength, "Expected error starting with '%s'", expectedErrors[0]); for (i = 1; ; i++) { if (expectedErrors[i] == NULL) break; messageLength -= snprintf(message + strlen(message), messageLength, " or '%s'", expectedErrors[i]); } snprintf(message + strlen(message), messageLength, " but got '%.*s'.\n", errorInfo->messageLength, errorInfo->message); return dpiTestCase_setFailed(testCase, message); } //----------------------------------------------------------------------------- // dpiTestCase_expectDoubleEqual() [PUBLIC] // Check to see that the double values are equal and if not, report a failure // and set the test case as failed. //----------------------------------------------------------------------------- int dpiTestCase_expectDoubleEqual(dpiTestCase *testCase, double actualValue, double expectedValue) { char message[512]; if (actualValue == expectedValue) return DPI_SUCCESS; snprintf(message, sizeof(message), "Value %g does not match expected value %g.\n", actualValue, expectedValue); return dpiTestCase_setFailed(testCase, message); } //----------------------------------------------------------------------------- // dpiTestCase_expectIntEqual() [PUBLIC] // Check to see that the signed integers are equal and if not, report a // failure and set the test case as failed. //----------------------------------------------------------------------------- int dpiTestCase_expectIntEqual(dpiTestCase *testCase, int64_t actualValue, int64_t expectedValue) { char message[512]; if (actualValue == expectedValue) return DPI_SUCCESS; snprintf(message, sizeof(message), "Value %" PRId64 " does not match expected value %" PRId64 ".\n", actualValue, expectedValue); return dpiTestCase_setFailed(testCase, message); } //----------------------------------------------------------------------------- // dpiTestCase_expectRoundTripsEqual() // Check that the number of round trips matches the expected value. //----------------------------------------------------------------------------- int dpiTestCase_expectRoundTripsEqual(dpiTestCase *testCase, uint64_t expected) { uint64_t currentRoundTrips; currentRoundTrips = testCase->roundTrips; if (dpiTestCase_updateRoundTrips(testCase) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, testCase->roundTrips - currentRoundTrips, expected); } //----------------------------------------------------------------------------- // dpiTestCase_expectStringEqual() [PUBLIC] // Check to see that the strings are equal and if not, report a failure and // set the test case as failed. //----------------------------------------------------------------------------- int dpiTestCase_expectStringEqual(dpiTestCase *testCase, const char *actual, uint32_t actualLength, const char *expected, uint32_t expectedLength) { char message[512]; if (actualLength == expectedLength && (actualLength == 0 || (actual && strncmp(actual, expected, expectedLength) == 0))) return DPI_SUCCESS; snprintf(message, sizeof(message), "String '%.*s' (%u) does not match expected string '%.*s' (%u).\n", actualLength, actual, actualLength, expectedLength, expected, expectedLength); return dpiTestCase_setFailed(testCase, message); } //----------------------------------------------------------------------------- // dpiTestCase_expectTimestampEqual() [INTERNAL] // Check to see that the timestamps are equal and if not, report a failure // and set the test case as failed. //----------------------------------------------------------------------------- int dpiTestCase_expectTimestampEqual(dpiTestCase *testCase, const dpiTimestamp *timestamp, const dpiTimestamp *expectedTimestamp) { char message[512]; if (timestamp->year == expectedTimestamp->year && timestamp->month == expectedTimestamp->month && timestamp->day == expectedTimestamp->day && timestamp->hour == expectedTimestamp->hour && timestamp->minute == expectedTimestamp->minute && timestamp->second == expectedTimestamp->second && timestamp->fsecond == expectedTimestamp->fsecond) return DPI_SUCCESS; snprintf(message, sizeof(message), "Timestamp %.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.6d does not match " "expected timestamp %.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.6d\n", timestamp->year, timestamp->month, timestamp->day, timestamp->hour, timestamp->minute, timestamp->second, timestamp->fsecond, expectedTimestamp->year, expectedTimestamp->month, expectedTimestamp->day, expectedTimestamp->hour, expectedTimestamp->minute, expectedTimestamp->second, expectedTimestamp->fsecond); return dpiTestCase_setFailed(testCase, message); } //----------------------------------------------------------------------------- // dpiTestCase_expectUintEqual() [PUBLIC] // Check to see that the unsigned integers are equal and if not, report a // failure and set the test case as failed. //----------------------------------------------------------------------------- int dpiTestCase_expectUintEqual(dpiTestCase *testCase, uint64_t actualValue, uint64_t expectedValue) { char message[512]; if (actualValue == expectedValue) return DPI_SUCCESS; snprintf(message, sizeof(message), "Value %" PRIu64 " does not match expected value %" PRIu64 ".\n", actualValue, expectedValue); return dpiTestCase_setFailed(testCase, message); } //----------------------------------------------------------------------------- // dpiTestCase_expectError() [PUBLIC] // Check to see that the error message prefix matches. //----------------------------------------------------------------------------- int dpiTestCase_expectError(dpiTestCase *testCase, const char *expectedError) { const char *expectedErrors[2]; expectedErrors[0] = expectedError; expectedErrors[1] = NULL; return dpiTestCase_expectAnyError(testCase, expectedErrors); } //----------------------------------------------------------------------------- // dpiTestCase_expectErrorInfo() [PUBLIC] // Check to see that the error message prefix matches. //----------------------------------------------------------------------------- int dpiTestCase_expectErrorInfo(dpiTestCase *testCase, const dpiErrorInfo *errorInfo, const char *expectedError) { const char *expectedErrors[2]; expectedErrors[0] = expectedError; expectedErrors[1] = NULL; return dpiTestCase_expectAnyErrorInfo(testCase, errorInfo, expectedErrors); } //----------------------------------------------------------------------------- // dpiTestCase_getConnection() [PUBLIC] // Create a new standalone connection and return it. If this cannot be done // the test case is marked as failed. //----------------------------------------------------------------------------- int dpiTestCase_getConnection(dpiTestCase *testCase, dpiConn **conn) { if (dpiConn_create(gContext, gTestSuite.params.mainUserName, gTestSuite.params.mainUserNameLength, gTestSuite.params.mainPassword, gTestSuite.params.mainPasswordLength, gTestSuite.params.connectString, gTestSuite.params.connectStringLength, &gCommonCreateParams, NULL, conn) < 0) return dpiTestCase_setFailedFromError(testCase); testCase->conn = *conn; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_getPool() [PUBLIC] // Create a new pool and return it. If this cannot be done the test case is // marked as failed. //----------------------------------------------------------------------------- int dpiTestCase_getPool(dpiTestCase *testCase, dpiPool **pool) { dpiPoolCreateParams createParams; if (dpiContext_initPoolCreateParams(gContext, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.minSessions = DPI_TEST_POOL_MIN_SESSIONS; createParams.maxSessions = DPI_TEST_POOL_MAX_SESSIONS; createParams.sessionIncrement = DPI_TEST_POOL_SESSION_INCREMENT; if (dpiPool_create(gContext, gTestSuite.params.mainUserName, gTestSuite.params.mainUserNameLength, gTestSuite.params.mainPassword, gTestSuite.params.mainPasswordLength, gTestSuite.params.connectString, gTestSuite.params.connectStringLength, &gCommonCreateParams, &createParams, pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_getSodaDb() [PUBLIC] // Create a new standalone connection and then get the SODA database object // associated with it. If this cannot be done the test case is marked as // failed. //----------------------------------------------------------------------------- int dpiTestCase_getSodaDb(dpiTestCase *testCase, dpiSodaDb **db) { dpiConn *conn; // verify client is a minimum of 18.3 and the server a minimum of 18.0 if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 1, 18, 3) < 0) return DPI_FAILURE; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 18, 0) < 0) return DPI_FAILURE; // get connection and SODA database object if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getSodaDb(conn, db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_getDatabaseVersionInfo() [PUBLIC] // Return database version information. //----------------------------------------------------------------------------- int dpiTestCase_getDatabaseVersionInfo(dpiTestCase *testCase, dpiVersionInfo **versionInfo) { uint32_t releaseStringLength; const char *releaseString; dpiConn *conn; if (!gDatabaseVersionAcquired) { if (dpiConn_create(gContext, gTestSuite.params.mainUserName, gTestSuite.params.mainUserNameLength, gTestSuite.params.mainPassword, gTestSuite.params.mainPasswordLength, gTestSuite.params.connectString, gTestSuite.params.connectStringLength, &gCommonCreateParams, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getServerVersion(conn, &releaseString, &releaseStringLength, &gDatabaseVersionInfo) < 0) return dpiTestCase_setFailedFromError(testCase); gDatabaseVersionAcquired = 1; dpiConn_release(conn); } *versionInfo = &gDatabaseVersionInfo; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_setFailed() [PUBLIC] // Set the test case as failed. Print the message to the log file and return // DPI_FAILURE as a convenience to the caller. //----------------------------------------------------------------------------- int dpiTestCase_setFailed(dpiTestCase *testCase, const char *message) { fprintf(gTestSuite.logFile, " [FAILED]\n"); fprintf(gTestSuite.logFile, " %s\n", message); fflush(gTestSuite.logFile); return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiTestCase_setFailedFromError() [PUBLIC] // Set the test case as failed from a DPI error. The error is first fetched // from the global DPI context. //----------------------------------------------------------------------------- int dpiTestCase_setFailedFromError(dpiTestCase *testCase) { dpiErrorInfo errorInfo; dpiContext_getError(gContext, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } //----------------------------------------------------------------------------- // dpiTestCase_setFailedFromErrorInfo() [PUBLIC] // Set the test case as failed from a DPI error info structure. //----------------------------------------------------------------------------- int dpiTestCase_setFailedFromErrorInfo(dpiTestCase *testCase, dpiErrorInfo *info) { fprintf(gTestSuite.logFile, " [FAILED]\n"); fprintf(gTestSuite.logFile, " FN: %s\n", info->fnName); fprintf(gTestSuite.logFile, " ACTION: %s\n", info->action); fprintf(gTestSuite.logFile, " MSG: %.*s\n", info->messageLength, info->message); fflush(gTestSuite.logFile); return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiTestCase_setSkipped() [PUBLIC] // Set the test case as skipped. Print the message to the log file and return // DPI_FAILURE as a convenience to the caller. //----------------------------------------------------------------------------- int dpiTestCase_setSkipped(dpiTestCase *testCase, const char *message) { testCase->skipped = 1; fprintf(gTestSuite.logFile, " [SKIPPED]\n"); fprintf(gTestSuite.logFile, " %s\n", message); fflush(gTestSuite.logFile); return DPI_FAILURE; } //----------------------------------------------------------------------------- // dpiTestCase_setSkippedIfVersionTooOld() [PUBLIC] // Set the test case as skipped if the client and/or database versions are // too old. //----------------------------------------------------------------------------- int dpiTestCase_setSkippedIfVersionTooOld(dpiTestCase *testCase, int clientOnly, unsigned minVersionNum, unsigned minReleaseNum) { dpiVersionInfo *versionInfo; char message[128]; // check OCI client version dpiTestSuite_getClientVersionInfo(&versionInfo); if (versionInfo->versionNum < minVersionNum || (versionInfo->versionNum == minVersionNum && versionInfo->releaseNum < minReleaseNum)) { sprintf(message, "OCI client version must be %u.%u or higher", minVersionNum, minReleaseNum); return dpiTestCase_setSkipped(testCase, message); } if (clientOnly) return DPI_SUCCESS; // check database version if (dpiTestCase_getDatabaseVersionInfo(testCase, &versionInfo) < 0) return DPI_FAILURE; if (versionInfo->versionNum < minVersionNum || (versionInfo->versionNum == minVersionNum && versionInfo->releaseNum < minReleaseNum)) { sprintf(message, "Database version must be %u.%u or higher", minVersionNum, minReleaseNum); return dpiTestCase_setSkipped(testCase, message); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestCase_setupRoundTripChecker() [PUBLIC] // If an administrative user and password have been specified, establish a // connection to this user and determine the number of round trips that have // been made with the connection associated with the test case. If no // administrative user and password have been specified, the test is marked as // skipped. //----------------------------------------------------------------------------- int dpiTestCase_setupRoundTripChecker(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context('userenv', 'sid') from dual"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiContext *context; dpiData *data; dpiStmt *stmt; int found; // first, check to see if an administrative user and password have been // specified and mark the test as skipped if these are not present if (!params->adminUserName || !params->adminPassword) return dpiTestCase_setSkipped(testCase, "administrative credentials not provided"); // determine SID for connection if (dpiConn_prepareStmt(testCase->conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 0, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); testCase->sid = data->value.asInt64; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // establish connection with administrative user dpiTestSuite_getContext(&context); if (dpiConn_create(context, params->adminUserName, params->adminUserNameLength, params->adminPassword, params->adminPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &testCase->adminConn) < 0) return dpiTestCase_setFailedFromError(testCase); // get the current round trips return dpiTestCase_updateRoundTrips(testCase); } //----------------------------------------------------------------------------- // dpiTestCase_updateRoundTrips() [PUBLIC] // Update the number of round trips associated with the connection used by // the test case. This assumes that a call to the function // dpiTestCase_setupRoundTripChecker() was performed earlier. //----------------------------------------------------------------------------- int dpiTestCase_updateRoundTrips(dpiTestCase *testCase) { const char *sql = "select ss.value from v$sesstat ss, v$statname sn " "where ss.sid = :sid and ss.statistic# = sn.statistic# " " and sn.name like '%roundtrip%client%'"; dpiNativeTypeNum nativeTypeNum; dpiData inData, *outData; uint32_t bufferRowIndex; dpiStmt *stmt; int found; inData.isNull = 0; inData.value.asInt64 = testCase->sid; if (dpiConn_prepareStmt(testCase->adminConn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &inData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 0, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outData) < 0) return dpiTestCase_setFailedFromError(testCase); testCase->roundTrips = outData->value.asInt64; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTestSuite_addCase() [PUBLIC] // Adds a test case to the test suite. Memory for the test cases is allocated // in groups in order to avoid constant memory allocation. Failure to allocate // memory is a fatal error which will terminate the test program. //----------------------------------------------------------------------------- void dpiTestSuite_addCase(dpiTestCaseFunction func, const char *description) { dpiTestCase *testCases, *testCase; // allocate space for more test cases if needed if (gTestSuite.numTestCases == gTestSuite.allocatedTestCases) { gTestSuite.allocatedTestCases += 16; testCases = malloc(gTestSuite.allocatedTestCases * sizeof(dpiTestCase)); if (!testCases) dpiTestSuite__fatalError("Out of memory!"); if (gTestSuite.testCases) { memcpy(testCases, gTestSuite.testCases, gTestSuite.numTestCases * sizeof(dpiTestCase)); free(gTestSuite.testCases); } gTestSuite.testCases = testCases; } // add new case testCase = &gTestSuite.testCases[gTestSuite.numTestCases++]; testCase->description = description; testCase->func = func; testCase->conn = NULL; testCase->adminConn = NULL; testCase->sid = 0; testCase->roundTrips = 0; testCase->skipped = 0; } //----------------------------------------------------------------------------- // dpiTestSuite_getClientVersionInfo() [PUBLIC] // Return Oracle Client version information. //----------------------------------------------------------------------------- void dpiTestSuite_getClientVersionInfo(dpiVersionInfo **versionInfo) { *versionInfo = &gClientVersionInfo; } //----------------------------------------------------------------------------- // dpiTestSuite_getContext() [PUBLIC] // Return global context used for most test cases. //----------------------------------------------------------------------------- void dpiTestSuite_getContext(dpiContext **context) { *context = gContext; } //----------------------------------------------------------------------------- // dpiTestSuite_getErrorInfo() [PUBLIC] // Return error information from the global context. //----------------------------------------------------------------------------- void dpiTestSuite_getErrorInfo(dpiErrorInfo *errorInfo) { dpiContext_getError(gContext, errorInfo); } //----------------------------------------------------------------------------- // dpiTestSuite_initialize() [PUBLIC] // Initializes the global test suite and test parameters structure. //----------------------------------------------------------------------------- void dpiTestSuite_initialize(uint32_t minTestCaseId) { uint32_t releaseStringLength; const char *releaseString; dpiErrorInfo errorInfo; dpiTestParams *params; dpiConn *conn; gTestSuite.numTestCases = 0; gTestSuite.allocatedTestCases = 0; gTestSuite.testCases = NULL; gTestSuite.logFile = stderr; gTestSuite.minTestCaseId = minTestCaseId; params = &gTestSuite.params; // acquire test suite parameters from the environment dpiTestSuite__getEnvValue("ODPIC_TEST_MAIN_USER", "odpic", ¶ms->mainUserName, ¶ms->mainUserNameLength, 1); dpiTestSuite__getEnvValue("ODPIC_TEST_MAIN_PASSWORD", "welcome", ¶ms->mainPassword, ¶ms->mainPasswordLength, 0); dpiTestSuite__getEnvValue("ODPIC_TEST_PROXY_USER", "odpic_proxy", ¶ms->proxyUserName, ¶ms->proxyUserNameLength, 1); dpiTestSuite__getEnvValue("ODPIC_TEST_PROXY_PASSWORD", "welcome", ¶ms->proxyPassword, ¶ms->proxyPasswordLength, 0); dpiTestSuite__getEnvValue("ODPIC_TEST_EDITION_USER", "odpic_edition", ¶ms->editionUserName, ¶ms->editionUserNameLength, 1); dpiTestSuite__getEnvValue("ODPIC_TEST_EDITION_PASSWORD", "welcome", ¶ms->editionPassword, ¶ms->editionPasswordLength, 0); dpiTestSuite__getEnvValue("ODPIC_TEST_CONNECT_STRING", "localhost/orclpdb", ¶ms->connectString, ¶ms->connectStringLength, 0); dpiTestSuite__getEnvValue("ODPIC_TEST_DIR_NAME", "odpic_dir", ¶ms->dirName, ¶ms->dirNameLength, 1); dpiTestSuite__getEnvValue("ODPIC_TEST_EDITION_NAME", "odpic_e1", ¶ms->editionName, ¶ms->editionNameLength, 1); dpiTestSuite__getEnvValue("ODPIC_TEST_ADMIN_USER", "", ¶ms->adminUserName, ¶ms->adminUserNameLength, 1); dpiTestSuite__getEnvValue("ODPIC_TEST_ADMIN_PASSWORD", "", ¶ms->adminPassword, ¶ms->adminPasswordLength, 0); // set up ODPI-C context and common creation parameters to use the UTF-8 // encoding if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, &gContext, &errorInfo) < 0) dpiTestSuite__fatalDPIError(&errorInfo, "Unable to create initial DPI context."); if (dpiContext_getClientVersion(gContext, &gClientVersionInfo) < 0) { dpiContext_getError(gContext, &errorInfo); dpiTestSuite__fatalDPIError(&errorInfo, "Unable to create initial DPI context."); } if (dpiContext_initCommonCreateParams(gContext, &gCommonCreateParams) < 0) { dpiContext_getError(gContext, &errorInfo); dpiTestSuite__fatalDPIError(&errorInfo, "Unable to initialize common create parameters."); } gCommonCreateParams.encoding = "UTF-8"; gCommonCreateParams.nencoding = "UTF-8"; // if minTestCaseId is 0 a simple connection test is performed // and version information is displayed if (minTestCaseId == 0) { fprintf(stderr, "ODPI-C version: %s\n", DPI_VERSION_STRING); fprintf(stderr, "OCI Client version: %d.%d.%d.%d.%d\n", gClientVersionInfo.versionNum, gClientVersionInfo.releaseNum, gClientVersionInfo.updateNum, gClientVersionInfo.portReleaseNum, gClientVersionInfo.portUpdateNum); if (dpiConn_create(gContext, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &gCommonCreateParams, NULL, &conn) < 0) { dpiContext_getError(gContext, &errorInfo); fprintf(stderr, "FN: %s\n", errorInfo.fnName); fprintf(stderr, "ACTION: %s\n", errorInfo.action); fprintf(stderr, "MSG: %.*s\n", errorInfo.messageLength, errorInfo.message); fprintf(stderr, "CREDENTIALS: %.*s/%.*s@%.*s\n", params->mainUserNameLength, params->mainUserName, params->mainPasswordLength, params->mainPassword, params->connectStringLength, params->connectString); dpiTestSuite__fatalError("Cannot connect to database."); } if (dpiConn_getServerVersion(conn, &releaseString, &releaseStringLength, &gDatabaseVersionInfo) < 0) { dpiContext_getError(gContext, &errorInfo); fprintf(stderr, "FN: %s\n", errorInfo.fnName); fprintf(stderr, "ACTION: %s\n", errorInfo.action); fprintf(stderr, "MSG: %.*s\n", errorInfo.messageLength, errorInfo.message); dpiTestSuite__fatalError("Cannot get database version."); } gDatabaseVersionAcquired = 1; fprintf(stderr, "OCI Database version: %d.%d.%d.%d.%d\n\n", gDatabaseVersionInfo.versionNum, gDatabaseVersionInfo.releaseNum, gDatabaseVersionInfo.updateNum, gDatabaseVersionInfo.portReleaseNum, gDatabaseVersionInfo.portUpdateNum); fflush(stderr); } } //----------------------------------------------------------------------------- // dpiTestSuite_run() [PUBLIC] // Runs the test cases in the test suite and reports to stderr the success // and failure of each of those test cases. When all test cases have completed // a summary is written to stderr. //----------------------------------------------------------------------------- int dpiTestSuite_run() { uint32_t i, numPassed, numSkipped; dpiTestCase *testCase; int result; numPassed = numSkipped = 0; for (i = 0; i < gTestSuite.numTestCases; i++) { testCase = &gTestSuite.testCases[i]; fprintf(gTestSuite.logFile, "%d. %s", gTestSuite.minTestCaseId + i, testCase->description); fflush(gTestSuite.logFile); fflush(gTestSuite.logFile); result = (*testCase->func)(testCase, &gTestSuite.params); if (testCase->skipped) numSkipped++; else if (result == 0) { numPassed++; fprintf(gTestSuite.logFile, " [OK]\n"); fflush(gTestSuite.logFile); } dpiTestCase__cleanUp(testCase); } dpiContext_destroy(gContext); if (numSkipped > 0) fprintf(gTestSuite.logFile, "%d / %d tests passed (%d skipped)\n", numPassed, gTestSuite.numTestCases - numSkipped, numSkipped); else fprintf(gTestSuite.logFile, "%d / %d tests passed\n", numPassed, gTestSuite.numTestCases); return gTestSuite.numTestCases - numPassed - numSkipped; } odpi-5.6.4/test/TestLib.h000066400000000000000000000160271510466437300151760ustar00rootroot00000000000000//---------------------------------------------------------------------------- // Copyright (c) 2017, 2022, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // TestLib.h // Header used for all test cases. //---------------------------------------------------------------------------- #include #include #include #include #include #ifdef _WIN32 #include #else #include #endif #ifdef _MSC_VER #if _MSC_VER < 1900 #define PRId64 "I64d" #define PRIu64 "I64u" #endif #endif #ifndef PRIu64 #include #endif // constants #define DPI_TEST_POOL_MIN_SESSIONS 3 #define DPI_TEST_POOL_MAX_SESSIONS 9 #define DPI_TEST_POOL_SESSION_INCREMENT 2 // forward declarations typedef struct dpiTestCase dpiTestCase; typedef struct dpiTestParams dpiTestParams; typedef struct dpiTestSuite dpiTestSuite; // define function prototype for test cases typedef int (*dpiTestCaseFunction)(dpiTestCase *testCase, dpiTestParams *params); // define test parameters struct dpiTestParams { const char *mainUserName; uint32_t mainUserNameLength; const char *mainPassword; uint32_t mainPasswordLength; const char *proxyUserName; uint32_t proxyUserNameLength; const char *proxyPassword; uint32_t proxyPasswordLength; const char *editionUserName; uint32_t editionUserNameLength; const char *editionPassword; uint32_t editionPasswordLength; const char *editionName; uint32_t editionNameLength; const char *connectString; uint32_t connectStringLength; const char *dirName; uint32_t dirNameLength; const char *adminUserName; uint32_t adminUserNameLength; const char *adminPassword; uint32_t adminPasswordLength; }; // define test case structure struct dpiTestCase { const char *description; dpiTestCaseFunction func; dpiConn *conn; dpiConn *adminConn; uint64_t sid; uint64_t roundTrips; int skipped; }; // define test suite struct dpiTestSuite { uint32_t numTestCases; uint32_t allocatedTestCases; uint32_t minTestCaseId; dpiTestCase *testCases; dpiTestParams params; FILE *logFile; }; // drop SODA collection and release connection to it int dpiTestCase_cleanupSodaColl(dpiTestCase *testCase, dpiSodaColl *coll); // drop all SODA collections in the database int dpiTestCase_dropAllSodaColls(dpiTestCase *testCase, dpiSodaDb *db); // expect an error with any of the specified message prefixes int dpiTestCase_expectAnyError(dpiTestCase *testCase, const char **expectedErrors); // expect an error with any of the specified message prefixes (in the given // error info) int dpiTestCase_expectAnyErrorInfo(dpiTestCase *testCase, const dpiErrorInfo *errorInfo, const char **expectedErrors); // expect double to be equal and sets test case as failed if not int dpiTestCase_expectDoubleEqual(dpiTestCase *testCase, double actualValue, double expectedValue); // expect an error with the specified message prefix int dpiTestCase_expectError(dpiTestCase *testCase, const char *expectedError); // expect an error with the specified message prefix in the given error info int dpiTestCase_expectErrorInfo(dpiTestCase *testCase, const dpiErrorInfo *erorInfo, const char *expectedError); // expect signed integers to be equal and sets test case as failed if not int dpiTestCase_expectIntEqual(dpiTestCase *testCase, int64_t actualValue, int64_t expectedValue); // expect that the number of round trips matches the expected value int dpiTestCase_expectRoundTripsEqual(dpiTestCase *testCase, uint64_t expected); // expect string to be equal and sets test case as failed if not int dpiTestCase_expectStringEqual(dpiTestCase *testCase, const char *actual, uint32_t actualLength, const char *expected, uint32_t expectedLength); // expect timestamp to be equal and sets test caswe as failed if not int dpiTestCase_expectTimestampEqual(dpiTestCase *testCase, const dpiTimestamp *timestamp, const dpiTimestamp *expectedTimestamp); // expect unsigned integers to be equal and sets test case as failed if not int dpiTestCase_expectUintEqual(dpiTestCase *testCase, uint64_t actualValue, uint64_t expectedValue); // get standalone connection int dpiTestCase_getConnection(dpiTestCase *testCase, dpiConn **conn); // get database version info int dpiTestCase_getDatabaseVersionInfo(dpiTestCase *testCase, dpiVersionInfo **versionInfo); // get pool int dpiTestCase_getPool(dpiTestCase *testCase, dpiPool **pool); // get SODA database int dpiTestCase_getSodaDb(dpiTestCase *testCase, dpiSodaDb **db); // set test case as failed int dpiTestCase_setFailed(dpiTestCase *testCase, const char *message); // set test case as failed from DPI error (fetched from context) int dpiTestCase_setFailedFromError(dpiTestCase *testCase); // set test case as failed from DPI error info int dpiTestCase_setFailedFromErrorInfo(dpiTestCase *testCase, dpiErrorInfo *info); // set test case as skipped int dpiTestCase_setSkipped(dpiTestCase *testCase, const char *message); // set test case as skipped if OCI client and/or database version is too old int dpiTestCase_setSkippedIfVersionTooOld(dpiTestCase *testCase, int clientOnly, unsigned minVersionNum, unsigned minReleaseNum); // setup round trip checker int dpiTestCase_setupRoundTripChecker(dpiTestCase *testCase, dpiTestParams *params); // update the number of round trips int dpiTestCase_updateRoundTrips(dpiTestCase *testCase); // add test case to test suite void dpiTestSuite_addCase(dpiTestCaseFunction func, const char *description); // get client version info void dpiTestSuite_getClientVersionInfo(dpiVersionInfo **versionInfo); // get global context void dpiTestSuite_getContext(dpiContext **context); // get error information from global context void dpiTestSuite_getErrorInfo(dpiErrorInfo *errorInfo); // initialize test suite void dpiTestSuite_initialize(uint32_t minTestCaseId); // run test suite int dpiTestSuite_run(); odpi-5.6.4/test/TestSuiteRunner.c000066400000000000000000000131371510466437300167450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // TestSuiteRunner.c // Runs each of the test executables. //----------------------------------------------------------------------------- #include "TestLib.h" #ifdef _WIN32 #include #else #include #include #include extern char **environ; #endif #define NUM_EXECUTABLES 36 static const char *dpiTestNames[NUM_EXECUTABLES] = { "test_1000_context", "test_1100_numbers", "test_1200_conn", "test_1300_conn_properties", "test_1400_pool", "test_1500_pool_properties", "test_1600_queries", "test_1700_transactions", "test_1800_misc", "test_1900_variables", "test_2000_statements", "test_2100_data_types", "test_2200_object_types", "test_2300_objects", "test_2400_enq_options", "test_2500_deq_options", "test_2600_msg_props", "test_2700_aq", "test_2800_lobs", "test_2900_implicit_results", "test_3000_scroll_cursors", "test_3100_subscriptions", "test_3200_batch_errors", "test_3300_dml_returning", "test_3400_soda_db", "test_3500_soda_coll", "test_3600_soda_coll_cursor", "test_3700_soda_doc", "test_3800_soda_doc_cursor", "test_3900_sess_tags", "test_4000_queue", "test_4100_binds", "test_4200_rowids", "test_4300_json", "test_4400_vector", "test_4500_sessionless_txn" }; //----------------------------------------------------------------------------- // dpiTest_runExecutable() // Run executable with the specified name. If all tests pass, return 0; // otherwise, return a negative value to indicate failure. //----------------------------------------------------------------------------- int dpiTest_runExecutable(const char *runnerName, const char *name) { #ifdef _WIN32 PROCESS_INFORMATION processInfo; STARTUPINFO startupInfo; DWORD result; // initialization ZeroMemory(&startupInfo, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); ZeroMemory(&processInfo, sizeof(processInfo)); // create process if (!CreateProcess(NULL, (char*) name, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { fprintf(stderr, "Unable to create process\n"); return -1; } // wait for process to complete and return success only if all tests pass WaitForSingleObject(processInfo.hProcess, INFINITE); GetExitCodeProcess(processInfo.hProcess, &result); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); if (result != 0) return -1; #else char executableName[PATH_MAX + 1], *temp; char * const argv[2] = { executableName, NULL }; int status; pid_t pid; // calculate name of executable to run strcpy(executableName, runnerName); temp = strrchr(executableName, '/'); if (temp) strcpy(temp + 1, name); else strcpy(executableName, name); // run executable and return success only if all tests pass status = posix_spawn(&pid, executableName, NULL, NULL, argv, environ); if (status != 0) { perror("Failed to spawn executable"); return -1; } if (waitpid(pid, &status, 0) < 0) { perror("Failed to wait for child process"); return -1; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return -1; #endif return 0; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { int testResults[NUM_EXECUTABLES], i, someTestsFailed; // verify that connection parameters are correct dpiTestSuite_initialize(0); // run all tests someTestsFailed = 0; for (i = 0; i < NUM_EXECUTABLES; i++) { fprintf(stderr, "Running cases in %s\n", dpiTestNames[i]); fflush(stderr); testResults[i] = dpiTest_runExecutable(argv[0], dpiTestNames[i]); fprintf(stderr, "\n"); fflush(stderr); if (testResults[i] < 0) someTestsFailed = 1; } // if some tests failed, report on which ones if (someTestsFailed) { fprintf(stderr, "Cases in the following tests failed:\n"); for (i = 0; i < NUM_EXECUTABLES; i++) { if (testResults[i] < 0) fprintf(stderr, " %s\n", dpiTestNames[i]); } return 1; } fprintf(stderr, "All tests passed!\n"); fflush(stderr); return 0; } odpi-5.6.4/test/sql/000077500000000000000000000000001510466437300142505ustar00rootroot00000000000000odpi-5.6.4/test/sql/DropTest.sql000066400000000000000000000047041510466437300165420ustar00rootroot00000000000000/*----------------------------------------------------------------------------- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License * 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose * either license.* * * If you elect to accept the software under the Apache License, Version 2.0, * the following applies: * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * DropTest.sql * Drops database objects used for testing * * Run this like: * sqlplus / as sysdba @DropTest * * Note that the script TestEnv.sql should be modified if you would like to use * something other than the default configuration. *---------------------------------------------------------------------------*/ whenever sqlerror exit failure -- setup environment @@TestEnv.sql -- drop schemas begin for r in ( select username from dba_users where username in (upper('&main_user'), upper('&proxy_user'), upper('&edition_user')) ) loop execute immediate 'drop user ' || r.username || ' cascade'; end loop; end; / -- drop directory begin for r in ( select directory_name from dba_directories where directory_name = upper('&dir_name') ) loop execute immediate 'drop directory ' || r.directory_name; end loop; end; / -- drop edition begin for r in ( select edition_name from dba_editions where edition_name in (upper('&edition_name')) ) loop execute immediate 'drop edition ' || r.edition_name || ' cascade'; end loop; end; / odpi-5.6.4/test/sql/SetupTest.sql000066400000000000000000001402061510466437300167340ustar00rootroot00000000000000/*----------------------------------------------------------------------------- * Copyright (c) 2016, 2025, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License * 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose * either license.* * * If you elect to accept the software under the Apache License, Version 2.0, * the following applies: * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * SetupTest.sql * Creates a test user and populates its schema with the tables and packages * necessary for performing the test suite. * * Run this like: * sqlplus / as sysdba @SetupTest * * Note that the script TestEnv.sql should be modified if you would like to use * something other than the default configuration. *---------------------------------------------------------------------------*/ whenever sqlerror exit failure -- drop existing users, if present @@DropTest.sql -- create directory CREATE DIRECTORY &dir_name AS '&dir_path'; alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'; alter session set nls_numeric_characters='.,'; alter session set nls_length_semantics = byte; create user &main_user identified by &main_password quota unlimited on users default tablespace users; create user &proxy_user identified by &proxy_password; alter user &proxy_user grant connect through &main_user; create user &edition_user identified by &edition_password quota unlimited on users default tablespace users; alter user &edition_user enable editions; create edition &edition_name; grant use on edition &edition_name to &edition_user; grant create session to &proxy_user; grant create session to &edition_user; grant create session, create table, create procedure, create sequence, create type, change notification to &main_user; grant read on directory &dir_name to &main_user; grant select on v_$session to &main_user; grant select on v_$sql_monitor to &main_user; begin for r in ( select role from dba_roles where role in ('SODA_APP') ) loop execute immediate 'grant ' || r.role || ' to &main_user'; end loop; end; / -- create types create type &main_user..udt_SubObject as object ( SubNumberValue number, SubStringValue varchar2(60) ); / create or replace type &main_user..udt_NestTab as table of &main_user..udt_SubObject; / create or replace type &main_user..udt_NestTabOfNestTab as table of &main_user..udt_NestTab; / create type &main_user..udt_ObjectArray as varray(10) of &main_user..udt_SubObject; / create type &main_user..udt_Object as object ( NumberValue number, StringValue varchar2(60), FixedCharValue char(10), DateValue date, TimestampValue timestamp, SubObjectValue &main_user..udt_SubObject, SubObjectArray &main_user..udt_ObjectArray ); / create type &main_user..udt_Array as varray(10) of number; / create type &main_user..udt_ObjectDataTypes as object ( StringCol varchar2(60), UnicodeCol nvarchar2(60), FixedCharCol char(30), FixedUnicodeCol nchar(30), RawCol raw(30), IntCol number, NumberCol number(9,2), DateCol date, TimestampCol timestamp, TimestampTZCol timestamp with time zone, TimestampLTZCol timestamp with local time zone, BinaryFltCol binary_float, BinaryDoubleCol binary_double, SignedIntCol integer ); / create type &main_user..udt_Dates as object ( IntCol number, DateCol date, TimestampCol timestamp, TimestampTZCol timestamp with time zone, TimestampLTZCol timestamp with local time zone ); / create type &main_user..udt_DatesArray as varray(10) of &main_user..udt_Dates; / create type &main_user..udt_ObjectDataTypesArray as varray(10) of &main_user..udt_ObjectDataTypes; / create type &main_user..udt_NestedArray is table of &main_user..udt_SubObject; / -- create tables create table &main_user..TestNumbers ( IntCol number(9) not null, NumberCol number(9, 2) not null, FloatCol float not null, UnconstrainedCol number not null, NullableCol number(38) ); create table &main_user..TestStrings ( IntCol number(9) not null, StringCol varchar2(20) not null, RawCol raw(30) not null, FixedCharCol char(40) not null, NullableCol varchar2(50) ); create table &main_user..TestUnicodes ( IntCol number(9) not null, UnicodeCol nvarchar2(20) not null, FixedUnicodeCol nchar(40) not null, NullableCol nvarchar2(50) ); create table &main_user..TestDates ( IntCol number(9) not null, DateCol date not null, NullableCol date ); create table &main_user..TestCLOBs ( IntCol number(9) not null, CLOBCol clob not null ) lob (CLOBCol) store as (chunk 16K); create table &main_user..TestNCLOBs ( IntCol number(9) not null, NCLOBCol nclob not null ); create table &main_user..TestBLOBs ( IntCol number(9) not null, BLOBCol blob not null ); create table &main_user..TestBFILEs ( IntCol number(9) not null, BFILECol bfile not null ); create table &main_user..TestXML ( IntCol number(9) not null, XMLCol xmltype not null ); create table &main_user..TestLongs ( IntCol number(9) not null, LongCol long not null ); create table &main_user..TestLongsAlter ( IntCol number(9), LongCol long ); create table &main_user..TestLongRaws ( IntCol number(9) not null, LongRawCol long raw not null ); create table &main_user..TestTempTable ( IntCol number(9) not null, StringCol varchar2(100), constraint TestTempTable_pk primary key (IntCol) ); create table &main_user..TestArrayDML ( IntCol number(9) not null, StringCol varchar2(100), IntCol2 number(3), constraint TestArrayDML_pk primary key (IntCol) ); create table &main_user..TestObjects ( IntCol number(9) not null, ObjectCol &main_user..udt_Object, ArrayCol &main_user..udt_Array ); create table &main_user..TestTimestamps ( IntCol number(9) not null, TimestampCol timestamp not null, TimestampTZCol timestamp with time zone not null, TimestampLTZCol timestamp with local time zone not null, NullableCol timestamp ); create table &main_user..TestIntervals ( IntCol number(9) not null, IntervalCol interval day to second not null, NullableCol interval day to second ); create table &main_user..TestObjectDataTypes ( ObjectCol &main_user..udt_ObjectDataTypes ); create table &main_user..TestObjectDataTypesVarray ( ObjectCol &main_user..udt_ObjectDataTypesArray ); create table &main_user..TestDatesVarray ( ObjectCol &main_user..udt_DatesArray ); create table &main_user..TestDataTypes ( StringCol varchar2(100) not null, UnicodeCol nvarchar2(100) not null, FixedCharCol char(100) not null, FixedUnicodeCol nchar(100) not null, RawCol raw(30) not null, FloatCol float not null, DoublePrecCol double precision not null, IntCol number(9) not null, NumberCol number(9,2) not null, DateCol date not null, TimestampCol timestamp not null, TimestampTZCol timestamp with time zone not null, TimestampLTZCol timestamp with local time zone not null, IntervalDSCol interval day to second not null, IntervalYMCol interval year to month not null, BinaryFltCol binary_float not null, BinaryDoubleCol binary_double not null, CLOBCol clob, NCLOBCol nclob, BLOBCol blob, BFILECol bfile, LongCol long not null, UnconstrainedCol number not null, SignedIntCol integer, SubObjectCol &main_user..udt_SubObject, constraint TestDataTypes_pk primary key (IntCol) ); create table &main_user..TestOrgIndex ( IntCol number(9) not null, StringCol varchar2(30) not null, constraint pk_index primary key (IntCol) ) organization index; create table &main_user..PlsqlSessionCallbacks ( RequestedTag varchar2(250), ActualTag varchar2(250), FixupTimestamp timestamp ); create table &main_user..TestNestedCollections ( IntCol number, StringCol varchar(60), NestedCol &main_user..udt_NestTabOfNestTab ) nested table NestedCol store as NestedColStore (nested table column_value store as SubNestedColStore) / -- populate tables begin for i in 1..30 loop insert into &main_user..TestOrgIndex values (i, 'String value ' || i); end loop; end; / begin for i in 1..10 loop insert into &main_user..TestNumbers values (i, i + i * 0.25, i + i * .75, i * i * i + i *.5, decode(mod(i, 2), 0, null, power(143, i))); end loop; end; / declare t_RawValue raw(30); function ConvertHexDigit(a_Value number) return varchar2 is begin if a_Value between 0 and 9 then return to_char(a_Value); end if; return chr(ascii('A') + a_Value - 10); end; function ConvertToHex(a_Value varchar2) return varchar2 is t_HexValue varchar2(60); t_Digit number; begin for i in 1..length(a_Value) loop t_Digit := ascii(substr(a_Value, i, 1)); t_HexValue := t_HexValue || ConvertHexDigit(trunc(t_Digit / 16)) || ConvertHexDigit(mod(t_Digit, 16)); end loop; return t_HexValue; end; begin for i in 1..10 loop t_RawValue := hextoraw(ConvertToHex('Raw ' || to_char(i))); insert into &main_user..TestStrings values (i, 'String ' || to_char(i), t_RawValue, 'Fixed Char ' || to_char(i), decode(mod(i, 2), 0, null, 'Nullable ' || to_char(i))); end loop; end; / begin for i in 1..10 loop insert into &main_user..TestUnicodes values (i, 'Unicode ' || unistr('\3042') || ' ' || to_char(i), 'Fixed Unicode ' || to_char(i), decode(mod(i, 2), 0, null, unistr('Nullable ') || to_char(i))); end loop; end; / begin for i in 1..10 loop insert into &main_user..TestDates values (i, to_date(20021209, 'YYYYMMDD') + i + i * .1, decode(mod(i, 2), 0, null, to_date(20021209, 'YYYYMMDD') + i + i + i * .15)); end loop; end; / begin for i in 1..10 loop insert into &main_user..TestTimestamps values (i, to_timestamp('20021209', 'YYYYMMDD') + to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 2) || '.' || to_char(i * 50)), to_timestamp_tz('20021210 00:00:00 ' || decode(mod(i, 2), 0, '-', '+') || ltrim(to_char(abs(i - 6), '00')) || ':' || decode(mod(i, 2), 0, '30', '00'), 'YYYYMMDD HH24:MI:SS TZH:TZM') + to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 3) || '.' || to_char(i * 75)), to_timestamp_tz('20021211 00:00:00 ' || to_char(i - 8, 'S00') || ':00', 'YYYYMMDD HH24:MI:SS TZH:TZM') + to_dsinterval(to_char(i) || ' 00:00:' || to_char(i * 4) || '.' || to_char(i * 100)), decode(mod(i, 2), 0, to_timestamp(null, 'YYYYMMDD'), to_timestamp('20021209', 'YYYYMMDD') + to_dsinterval(to_char(i + 1) || ' 00:00:' || to_char(i * 3) || '.' || to_char(i * 125)))); end loop; end; / begin for i in 1..10 loop insert into &main_user..TestIntervals values (i, to_dsinterval(to_char(i) || ' ' || to_char(i) || ':' || to_char(i * 2) || ':' || to_char(i * 3)), decode(mod(i, 2), 0, to_dsinterval(null), to_dsinterval(to_char(i + 5) || ' ' || to_char(i + 2) || ':' || to_char(i * 2 + 5) || ':' || to_char(i * 3 + 5)))); end loop; end; / insert into &main_user..TestObjects values (1, &main_user..udt_Object(1, 'First row', 'First', to_date(20070306, 'YYYYMMDD'), to_timestamp('20080912 16:40:00', 'YYYYMMDD HH24:MI:SS'), &main_user..udt_SubObject(11, 'Sub object 1'), &main_user..udt_ObjectArray( &main_user..udt_SubObject(5, 'first element'), &main_user..udt_SubObject(6, 'second element'))), &main_user..udt_Array(5, 10, null, 20)); insert into &main_user..TestObjects values (2, null, &main_user..udt_Array(3, null, 9, 12, 15)); insert into &main_user..TestObjects values (3, &main_user..udt_Object(3, 'Third row', 'Third', to_date(20070621, 'YYYYMMDD'), to_timestamp('20071213 07:30:45', 'YYYYMMDD HH24:MI:SS'), &main_user..udt_SubObject(13, 'Sub object 3'), &main_user..udt_ObjectArray( &main_user..udt_SubObject(10, 'element #1'), &main_user..udt_SubObject(20, 'element #2'), &main_user..udt_SubObject(30, 'element #3'), &main_user..udt_SubObject(40, 'element #4'))), null); commit; -- create procedures for testing callproc() create procedure &main_user..proc_Test ( a_InValue varchar2, a_InOutValue in out number, a_OutValue out number ) as begin a_InOutValue := a_InOutValue * length(a_InValue); a_OutValue := length(a_InValue); end; / create procedure &main_user..proc_TestNoArgs as begin null; end; / -- create functions for testing callfunc() create function &main_user..func_Test ( a_String varchar2, a_ExtraAmount number ) return number as begin return length(a_String) + a_ExtraAmount; end; / create function &main_user..func_TestNoArgs return number as begin return 712; end; / -- create packages create or replace package &main_user..pkg_TestStringArrays as type udt_StringList is table of varchar2(100) index by binary_integer; function TestInArrays ( a_StartingLength number, a_Array udt_StringList ) return number; procedure TestInOutArrays ( a_NumElems number, a_Array in out nocopy udt_StringList ); procedure TestOutArrays ( a_NumElems number, a_Array out nocopy udt_StringList ); procedure TestIndexBy ( a_Array out nocopy udt_StringList ); end; / create or replace package body &main_user..pkg_TestStringArrays as function TestInArrays ( a_StartingLength number, a_Array udt_StringList ) return number is t_Length number; begin t_Length := a_StartingLength; for i in 1..a_Array.count loop t_Length := t_Length + length(a_Array(i)); end loop; return t_Length; end; procedure TestInOutArrays ( a_NumElems number, a_Array in out udt_StringList ) is begin for i in 1..a_NumElems loop a_Array(i) := 'Converted element # ' || to_char(i) || ' originally had length ' || to_char(length(a_Array(i))); end loop; end; procedure TestOutArrays ( a_NumElems number, a_Array out udt_StringList ) is begin for i in 1..a_NumElems loop a_Array(i) := 'Test out element # ' || to_char(i); end loop; end; procedure TestIndexBy ( a_Array out nocopy udt_StringList ) is begin a_Array(-1048576) := 'First element'; a_Array(-576) := 'Second element'; a_Array(284) := 'Third element'; a_Array(8388608) := 'Fourth element'; end; end; / create or replace package &main_user..pkg_TestUnicodeArrays as type udt_UnicodeList is table of nvarchar2(100) index by binary_integer; function TestInArrays ( a_StartingLength number, a_Array udt_UnicodeList ) return number; procedure TestInOutArrays ( a_NumElems number, a_Array in out nocopy udt_UnicodeList ); procedure TestOutArrays ( a_NumElems number, a_Array out nocopy udt_UnicodeList ); end; / create or replace package body &main_user..pkg_TestUnicodeArrays as function TestInArrays ( a_StartingLength number, a_Array udt_UnicodeList ) return number is t_Length number; begin t_Length := a_StartingLength; for i in 1..a_Array.count loop t_Length := t_Length + length(a_Array(i)); end loop; return t_Length; end; procedure TestInOutArrays ( a_NumElems number, a_Array in out udt_UnicodeList ) is begin for i in 1..a_NumElems loop a_Array(i) := unistr('Converted element ' || unistr('\3042') || ' # ') || to_char(i) || ' originally had length ' || to_char(length(a_Array(i))); end loop; end; procedure TestOutArrays ( a_NumElems number, a_Array out udt_UnicodeList ) is begin for i in 1..a_NumElems loop a_Array(i) := unistr('Test out element ') || unistr('\3042') || ' # ' || to_char(i); end loop; end; end; / create or replace package &main_user..pkg_TestNumberArrays as type udt_NumberList is table of number index by binary_integer; function TestInArrays ( a_StartingValue number, a_Array udt_NumberList ) return number; procedure TestInOutArrays ( a_NumElems number, a_Array in out nocopy udt_NumberList ); procedure TestOutArrays ( a_NumElems number, a_Array out nocopy udt_NumberList ); end; / create or replace package body &main_user..pkg_TestNumberArrays as function TestInArrays ( a_StartingValue number, a_Array udt_NumberList ) return number is t_Value number; begin t_Value := a_StartingValue; for i in 1..a_Array.count loop t_Value := t_Value + a_Array(i); end loop; return t_Value; end; procedure TestInOutArrays ( a_NumElems number, a_Array in out udt_NumberList ) is begin for i in 1..a_NumElems loop a_Array(i) := a_Array(i) * 10; end loop; end; procedure TestOutArrays ( a_NumElems number, a_Array out udt_NumberList ) is begin for i in 1..a_NumElems loop a_Array(i) := i * 100; end loop; end; end; / create or replace package &main_user..pkg_TestDateArrays as type udt_DateList is table of date index by binary_integer; function TestInArrays ( a_StartingValue number, a_BaseDate date, a_Array udt_DateList ) return number; procedure TestInOutArrays ( a_NumElems number, a_Array in out nocopy udt_DateList ); procedure TestOutArrays ( a_NumElems number, a_Array out nocopy udt_DateList ); end; / create or replace package body &main_user..pkg_TestDateArrays as function TestInArrays ( a_StartingValue number, a_BaseDate date, a_Array udt_DateList ) return number is t_Value number; begin t_Value := a_StartingValue; for i in 1..a_Array.count loop t_Value := t_Value + a_Array(i) - a_BaseDate; end loop; return t_Value; end; procedure TestInOutArrays ( a_NumElems number, a_Array in out udt_DateList ) is begin for i in 1..a_NumElems loop a_Array(i) := a_Array(i) + 7; end loop; end; procedure TestOutArrays ( a_NumElems number, a_Array out udt_DateList ) is begin for i in 1..a_NumElems loop a_Array(i) := to_date(20021212, 'YYYYMMDD') + i; end loop; end; end; / create or replace package &main_user..pkg_TestNumberVArrays as function TestInArrays ( a_StartingValue number, a_Array udt_Array ) return number; procedure TestInOutArrays ( a_NumElems number, a_Array in out nocopy udt_Array ); procedure TestOutArrays ( a_NumElems number, a_Array out nocopy udt_Array ); end; / create or replace package body &main_user..pkg_TestNumberVArrays as function TestInArrays ( a_StartingValue number, a_Array udt_Array ) return number is t_Value number; begin t_Value := a_StartingValue; for i in 1..a_Array.count loop t_Value := t_Value + a_Array(i); end loop; return t_Value; end; procedure TestInOutArrays ( a_NumElems number, a_Array in out udt_Array ) is begin for i in 1..a_NumElems loop a_Array(i) := a_Array(i) * 20; end loop; end; procedure TestOutArrays ( a_NumElems number, a_Array out udt_Array ) is begin a_Array := udt_Array(); for i in 1..a_NumElems loop a_Array.extend(); a_Array(i) := i * 200; end loop; end; end; / create or replace package &main_user..pkg_TestObjectArrays as function TestInObjArray ( a_NumElems number, a_InObject udt_ObjectArray ) return number; procedure TestInOutObjArray ( a_NumElems number, a_InOutObject in out nocopy udt_ObjectArray ); procedure TestOutObjArray ( a_NumElems number, a_OutObject out nocopy udt_ObjectArray ); end; / create or replace package body &main_user..pkg_TestObjectArrays as function TestInObjArray ( a_NumElems number, a_InObject udt_ObjectArray ) return number is t_Value number; begin t_Value := a_NumElems; for i in 1..a_InObject.count loop t_Value := t_Value + a_InObject(i).SubNumberValue + length(a_InObject(i).SubStringValue); end loop; return t_Value; end; procedure TestInOutObjArray ( a_NumElems number, a_InOutObject in out udt_ObjectArray ) is begin for i in 1..a_NumElems loop a_InOutObject(i) := udt_SubObject(i, 'Test in/out element number ' || to_char(i)); end loop; end; procedure TestOutObjArray ( a_NumElems number, a_OutObject out udt_ObjectArray ) is begin a_OutObject := udt_ObjectArray(); for i in 1..a_NumElems loop a_OutObject.extend(); a_OutObject(i) := udt_SubObject(i, 'Test out element number ' || to_char(i)); end loop; end; end; / create or replace package &main_user..pkg_TestOutCursors as type udt_RefCursor is ref cursor; procedure TestOutCursor ( a_MaxIntValue number, a_Cursor out udt_RefCursor ); end; / create or replace package body &main_user..pkg_TestOutCursors as procedure TestOutCursor ( a_MaxIntValue number, a_Cursor out udt_RefCursor ) is begin open a_Cursor for select IntCol, StringCol from TestStrings where IntCol <= a_MaxIntValue order by IntCol; end; end; / create or replace package &main_user..pkg_TestBooleans as type udt_BooleanList is table of boolean index by binary_integer; function GetStringRep ( a_Value boolean ) return varchar2; function IsLessThan10 ( a_Value number ) return boolean; function TestInArrays ( a_Value udt_BooleanList ) return number; procedure TestOutArrays ( a_NumElements number, a_Value out nocopy udt_BooleanList ); end; / create or replace package body &main_user..pkg_TestBooleans as function GetStringRep ( a_Value boolean ) return varchar2 is begin if a_Value is null then return 'NULL'; elsif a_Value then return 'TRUE'; end if; return 'FALSE'; end; function IsLessThan10 ( a_Value number ) return boolean is begin return a_Value < 10; end; function TestInArrays ( a_Value udt_BooleanList ) return number is t_Result pls_integer; begin t_Result := 0; for i in 1..a_Value.count loop if a_Value(i) then t_Result := t_Result + 1; end if; end loop; return t_Result; end; procedure TestOutArrays ( a_NumElements number, a_Value out nocopy udt_BooleanList ) is begin for i in 1..a_NumElements loop a_Value(i) := (mod(i, 2) = 1); end loop; end; end; / create or replace package &main_user..pkg_TestBindObject as function GetStringRep ( a_Object udt_Object ) return varchar2; end; / create or replace package body &main_user..pkg_TestBindObject as function GetStringRep ( a_Object udt_SubObject ) return varchar2 is begin if a_Object is null then return 'null'; end if; return 'udt_SubObject(' || nvl(to_char(a_Object.SubNumberValue), 'null') || ', ' || case when a_Object.SubStringValue is null then 'null' else '''' || a_Object.SubStringValue || '''' end || ')'; end; function GetStringRep ( a_Array udt_ObjectArray ) return varchar2 is t_StringRep varchar2(4000); begin if a_Array is null then return 'null'; end if; t_StringRep := 'udt_ObjectArray('; for i in 1..a_Array.count loop if i > 1 then t_StringRep := t_StringRep || ', '; end if; t_StringRep := t_StringRep || GetStringRep(a_Array(i)); end loop; return t_StringRep || ')'; end; function GetStringRep ( a_Object udt_Object ) return varchar2 is begin if a_Object is null then return 'null'; end if; return 'udt_Object(' || nvl(to_char(a_Object.NumberValue), 'null') || ', ' || case when a_Object.StringValue is null then 'null' else '''' || a_Object.StringValue || '''' end || ', ' || case when a_Object.FixedCharValue is null then 'null' else '''' || a_Object.FixedCharValue || '''' end || ', ' || case when a_Object.DateValue is null then 'null' else 'to_date(''' || to_char(a_Object.DateValue, 'YYYY-MM-DD') || ''', ''YYYY-MM-DD'')' end || ', ' || case when a_Object.TimestampValue is null then 'null' else 'to_timestamp(''' || to_char(a_Object.TimestampValue, 'YYYY-MM-DD HH24:MI:SS') || ''', ''YYYY-MM-DD HH24:MI:SS'')' end || ', ' || GetStringRep(a_Object.SubObjectValue) || ', ' || GetStringRep(a_Object.SubObjectArray) || ')'; end; end; / create or replace package &main_user..pkg_TestRecords as type udt_Record is record ( NumberValue number, StringValue varchar2(30), DateValue date, TimestampValue timestamp, BooleanValue boolean, PlsIntegerValue pls_integer, BinaryIntegerValue binary_integer ); type udt_RecordArray is table of udt_Record index by binary_integer; function GetStringRep ( a_Value udt_Record ) return varchar2; procedure TestInOut ( a_Value in out nocopy udt_Record ); procedure TestOut ( a_Value out nocopy udt_Record ); function TestInArrays ( a_Value udt_RecordArray ) return number; procedure TestInOutArrays ( a_Value in out nocopy udt_RecordArray ); procedure TestOutArrays ( a_NumElems number, a_Value out nocopy udt_RecordArray ); end; / create or replace package body &main_user..pkg_TestRecords as function GetStringRep ( a_Value udt_Record ) return varchar2 is begin return 'udt_Record(' || nvl(to_char(a_Value.NumberValue), 'null') || ', ' || case when a_Value.StringValue is null then 'null' else '''' || a_Value.StringValue || '''' end || ', ' || case when a_Value.DateValue is null then 'null' else 'to_date(''' || to_char(a_Value.DateValue, 'YYYY-MM-DD') || ''', ''YYYY-MM-DD'')' end || ', ' || case when a_Value.TimestampValue is null then 'null' else 'to_timestamp(''' || to_char(a_Value.TimestampValue, 'YYYY-MM-DD HH24:MI:SS') || ''', ''YYYY-MM-DD HH24:MI:SS'')' end || ', ' || case when a_Value.BooleanValue is null then 'null' when a_Value.BooleanValue then 'true' else 'false' end || ', ' || nvl(to_char(a_Value.PlsIntegerValue), 'null') || ', ' || nvl(to_char(a_Value.BinaryIntegerValue), 'null') || ')'; end; procedure TestInOut ( a_Value in out nocopy udt_Record ) is begin a_Value.NumberValue := a_Value.NumberValue * 10; a_Value.StringValue := 'String in/out record'; a_Value.DateValue := a_Value.DateValue + 4; a_Value.TimestampValue := a_Value.TimestampValue - 1; a_Value.BooleanValue := false; a_Value.PlsIntegerValue := a_Value.PlsIntegerValue * 10; a_Value.BinaryIntegerValue := a_Value.BinaryIntegerValue * 10; end; procedure TestOut ( a_Value out nocopy udt_Record ) is begin a_Value.NumberValue := 25; a_Value.StringValue := 'String in record'; a_Value.DateValue := to_date(20160216, 'YYYYMMDD'); a_Value.TimestampValue := to_timestamp('20160216 18:23:55', 'YYYYMMDD HH24:MI:SS'); a_Value.BooleanValue := true; a_Value.PlsIntegerValue := -214748; a_Value.BinaryIntegerValue := 214748; end; function TestInArrays ( a_Value udt_RecordArray ) return number is t_Result number; begin t_Result := 0; for i in 0..a_Value.count - 1 loop t_Result := t_Result + a_Value(i).NumberValue; end loop; return t_Result; end; procedure TestInOutArrays ( a_Value in out nocopy udt_RecordArray ) is begin for i in 0..a_Value.count - 1 loop a_Value(i).NumberValue := a_Value(i).NumberValue * 10; a_Value(i).StringValue := 'Converted in/out record # ' || to_char(i); a_Value(i).DateValue := a_Value(i).DateValue + i; a_Value(i).TimestampValue := a_Value(i).TimestampValue + i; a_Value(i).BooleanValue := (mod(i, 2) = 1); a_Value(i).PlsIntegerValue := a_Value(i).PlsIntegerValue * 10; a_Value(i).BinaryIntegerValue := a_Value(i).BinaryIntegerValue *10; end loop; end; procedure TestOutArrays ( a_NumElems number, a_Value out nocopy udt_RecordArray ) is begin for i in 0..a_NumElems - 1 loop a_Value(i).NumberValue := i * 10; a_Value(i).StringValue := 'Test OUT record # ' || to_char(i); a_Value(i).DateValue := to_date(20160216, 'YYYYMMDD') + i; a_Value(i).TimestampValue := to_timestamp('20160216 18:23:55', 'YYYYMMDD HH24:MI:SS') + i; a_Value(i).BooleanValue := (mod(i, 2) = 1); a_Value(i).PlsIntegerValue := i * 7; a_Value(i).BinaryIntegerValue := i * 5; end loop; end; end; / create or replace package &main_user..pkg_TestLOBs as procedure TestInOutTempClob ( a_IntValue number, a_CLOB in out clob ); function TestInClob ( a_CLOB in clob ) return number; procedure TestInOutClob ( a_CLOB in out clob ); procedure TestOutClob ( a_CLOB out clob ); function TestInNClob ( a_NCLOB in nclob ) return number; procedure TestInOutNClob ( a_NCLOB in out nclob ); procedure TestOutNClob ( a_NCLOB out nclob ); function TestInBlob ( a_BLOB in blob ) return number; procedure TestInOutBlob ( a_BLOB in out blob ); procedure TestOutBlob ( a_BLOB out blob ); end; / create or replace package body &main_user..pkg_TestLOBs as procedure TestInOutTempClob ( a_IntValue number, a_CLOB in out clob ) is begin delete from TestClobs where IntCol = a_IntValue; insert into TestClobs ( IntCol, ClobCol ) values ( a_IntValue, a_CLOB ); select ClobCol into a_CLOB from TestClobs where IntCol = a_IntValue; end; function TestInClob ( a_CLOB in clob ) return number is begin return dbms_lob.getlength(a_CLOB); end; procedure TestInOutClob ( a_CLOB in out clob ) is t_AppendValue varchar2(100) := ' (Modified)'; begin dbms_lob.writeappend(a_CLOB, length(t_AppendValue), t_AppendValue); end; procedure TestOutClob ( a_CLOB out clob ) is begin a_CLOB := to_clob('OUT CLOB'); end; function TestInNClob ( a_NCLOB in nclob ) return number is begin return dbms_lob.getlength(a_NCLOB); end; procedure TestInOutNClob ( a_NCLOB in out nclob ) is t_AppendValue nvarchar2(100) := ' (Modified)'; begin dbms_lob.writeappend(a_NCLOB, length(t_AppendValue), t_AppendValue); end; procedure TestOutNClob ( a_NCLOB out nclob ) is begin a_NCLOB := to_nclob('OUT NCLOB'); end; function TestInBlob ( a_BLOB in blob ) return number is begin return dbms_lob.getlength(a_BLOB); end; procedure TestInOutBlob ( a_BLOB in out blob ) is t_AppendValue varchar2(100) := ' (Modified)'; begin dbms_lob.writeappend(a_BLOB, length(t_AppendValue), utl_raw.cast_to_raw(t_AppendValue)); end; procedure TestOutBlob ( a_BLOB out blob ) is begin a_BLOB := to_blob(utl_raw.cast_to_raw('OUT BLOB')); end; end; / create or replace procedure &main_user..proc_TestInOutBool ( a_BooleanCol in out boolean ) as begin a_BooleanCol := a_BooleanCol; end; / create or replace procedure &main_user..proc_TestInOut ( a_StringCol in out varchar2, a_UnicodeCol in out nvarchar2, a_FloatCol in out float, a_DoublePrecCol in out double precision, a_NumberCol in out number, a_DateCol in out date, a_TimestampCol in out timestamp, a_TimestampTZCol in out timestamp with time zone, a_IntervalDSCol in out interval day to second, a_IntervalYMCol in out interval year to month, a_BinaryFltCol in out binary_float, a_BinaryDoubleCol in out binary_double, a_SignedIntCol in out integer, a_Object in out udt_SubObject ) as begin a_StringCol := a_StringCol || ' (Modified)'; a_UnicodeCol := a_UnicodeCol || ' (Modified)'; a_FloatCol := a_FloatCol + a_FloatCol; a_DoublePrecCol := a_DoublePrecCol + a_DoublePrecCol; a_NumberCol := a_NumberCol + a_NumberCol; a_DateCol := a_DateCol + interval '1' year; a_TimestampCol := a_TimestampCol + interval '30' minute; a_TimestampTZCol := a_TimestampTZCol + interval '30' minute; a_IntervalDSCol := a_IntervalDSCol + a_IntervalDSCol; a_IntervalYMCol := a_IntervalYMCol + a_IntervalYMCol; a_BinaryFltCol := a_BinaryFltCol + a_BinaryFltCol; a_BinaryDoubleCol := a_BinaryDoubleCol + a_BinaryDoubleCol; a_SignedIntCol := a_SignedIntCol + a_SignedIntCol; a_Object.SubNumberValue := a_Object.SubNumberValue * 3; a_Object.SubStringValue := a_Object.SubStringValue || ' (Modified)'; end; / -- create type and table for testing advanced queuing create or replace type &main_user..udt_Book as object ( Title varchar2(100), Authors varchar2(100), Price number(5,2) ); / begin dbms_aqadm.create_queue_table('&main_user..BOOK_QUEUE_TAB', '&main_user..UDT_BOOK'); dbms_aqadm.create_queue('&main_user..BOOK_QUEUE', '&main_user..BOOK_QUEUE_TAB'); dbms_aqadm.start_queue('&main_user..BOOK_QUEUE'); dbms_aqadm.create_queue_table('&main_user..RAW_QUEUE_TAB', 'RAW'); dbms_aqadm.create_queue('&main_user..RAW_QUEUE', '&main_user..RAW_QUEUE_TAB'); dbms_aqadm.start_queue('&main_user..RAW_QUEUE'); end; / -- -- Create package for demoing PL/SQL session callback -- create or replace package &main_user..pkg_SessionCallback as procedure TheCallback ( a_RequestedTag varchar2, a_ActualTag varchar2 ); end; / create or replace package body &main_user..pkg_SessionCallback as type udt_Properties is table of varchar2(64) index by varchar2(64); procedure LogCall ( a_RequestedTag varchar2, a_ActualTag varchar2 ) is pragma autonomous_transaction; begin insert into PlsqlSessionCallbacks values (a_RequestedTag, a_ActualTag, systimestamp); commit; end; procedure ParseProperty ( a_Property varchar2, a_Name out nocopy varchar2, a_Value out nocopy varchar2 ) is t_Pos number; begin t_Pos := instr(a_Property, '='); if t_Pos = 0 then raise_application_error(-20000, 'Tag must contain key=value pairs'); end if; a_Name := substr(a_Property, 1, t_Pos - 1); a_Value := substr(a_Property, t_Pos + 1); end; procedure SetProperty ( a_Name varchar2, a_Value varchar2 ) is t_ValidValues udt_Properties; begin if a_Name = 'TIME_ZONE' then t_ValidValues('UTC') := 'UTC'; t_ValidValues('MST') := '-07:00'; elsif a_Name = 'NLS_DATE_FORMAT' then t_ValidValues('SIMPLE') := 'YYYY-MM-DD HH24:MI'; t_ValidValues('FULL') := 'YYYY-MM-DD HH24:MI:SS'; else raise_application_error(-20000, 'Unsupported session setting'); end if; if not t_ValidValues.exists(a_Value) then raise_application_error(-20000, 'Unsupported session setting'); end if; execute immediate 'ALTER SESSION SET ' || a_Name || '=''' || t_ValidValues(a_Value) || ''''; end; procedure ParseTag ( a_Tag varchar2, a_Properties out nocopy udt_Properties ) is t_PropertyName varchar2(64); t_PropertyValue varchar2(64); t_StartPos number; t_EndPos number; begin t_StartPos := 1; while t_StartPos < length(a_Tag) loop t_EndPos := instr(a_Tag, ';', t_StartPos); if t_EndPos = 0 then t_EndPos := length(a_Tag) + 1; end if; ParseProperty(substr(a_Tag, t_StartPos, t_EndPos - t_StartPos), t_PropertyName, t_PropertyValue); a_Properties(t_PropertyName) := t_PropertyValue; t_StartPos := t_EndPos + 1; end loop; end; procedure TheCallback ( a_RequestedTag varchar2, a_ActualTag varchar2 ) is t_RequestedProps udt_Properties; t_ActualProps udt_Properties; t_PropertyName varchar2(64); begin LogCall(a_RequestedTag, a_ActualTag); ParseTag(a_RequestedTag, t_RequestedProps); ParseTag(a_ActualTag, t_ActualProps); t_PropertyName := t_RequestedProps.first; while t_PropertyName is not null loop if not t_ActualProps.exists(t_PropertyName) or t_ActualProps(t_PropertyName) != t_RequestedProps(t_PropertyName) then SetProperty(t_PropertyName, t_RequestedProps(t_PropertyName)); end if; t_PropertyName := t_RequestedProps.next(t_PropertyName); end loop; end; end; / declare t_Version number; begin select to_number(substr(version, 1, instr(version, '.') - 1)) into t_Version from product_component_version where product like 'Oracle Database%'; if t_Version >= 21 then execute immediate 'create table &main_user..TestJson (' || ' JsonCol json' || ')'; end if; if t_Version >= 23 then execute immediate 'create table &main_user..TestVectors (' || ' IntCol number(9) not null,' || ' VectorFlexAllCol vector,' || ' VectorFlexTypeCol vector(2),' || ' VectorFlex8Col vector(*, int8),' || ' VectorFlex32Col vector(*, float32),' || ' VectorFlex64Col vector(*, float64),' || ' Vector32Col vector(10, float32),' || ' Vector64Col vector(10, float64),' || ' Vector8Col vector(10, int8)' || ')'; end if; end; / odpi-5.6.4/test/sql/TestEnv.sql000066400000000000000000000053261510466437300163670ustar00rootroot00000000000000/*----------------------------------------------------------------------------- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. * * This software is dual-licensed to you under the Universal Permissive License * (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License * 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose * either license.* * * If you elect to accept the software under the Apache License, Version 2.0, * the following applies: * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * TestEnv.sql * Sets up configuration for the SetupTest.sql and DropTest.sql scripts. * Change the values below if you would like to use something other than the * default values. Note that the environment variables noted below will also * need to be set, if non-default values are used. * The directory path must be one that both the server and the client can * read simultaneously. *---------------------------------------------------------------------------*/ set echo off termout on feedback off verify off define main_user = "odpic" -- $ODPIC_TEST_MAIN_USER define main_password = "welcome" -- $ODPIC_TEST_MAIN_PASSWORD define proxy_user = "odpic_proxy" -- $ODPIC_TEST_PROXY_USER define proxy_password = "welcome" -- $ODPIC_TEST_PROXY_PASSWORD define edition_user = "odpic_edition" -- $ODPIC_TEST_EDITION_USER define edition_password = "welcome" -- $ODPIC_TEST_EDITION_PASSWORD define edition_name = "odpic_e1" -- $ODPIC_TEST_EDITION_NAME define dir_name = "odpic_dir" -- $ODPIC_TEST_DIR_NAME define dir_path = "/tmp" prompt ************************************************************************ prompt CONFIGURATION prompt ************************************************************************ prompt Main Schema: &main_user prompt Proxy Schema: &proxy_user prompt Edition Schema: &edition_user prompt Edition Name: &edition_name prompt Directory Name: &dir_name prompt Directory Path: &dir_path prompt set echo on verify on feedback on odpi-5.6.4/test/test_1000_context.c000066400000000000000000000217431510466437300170070ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1000_context.c // Test suite for testing dpiContext functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_1000() // Verify that dpiContext_createWithParams() succeeds when valid major and // minor version numbers are passed. //----------------------------------------------------------------------------- int dpiTest_1000(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo; dpiContext *context; if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, &context, &errorInfo) < 0) return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); if (dpiContext_destroy(context) < 0) { dpiContext_getError(context, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1001() // Verify that dpiContext_createWithParams() returns error DPI-1020 when // called with a major version that doesn't match the one with which DPI was // compiled. //----------------------------------------------------------------------------- int dpiTest_1001(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo; dpiContext *context; dpiContext_createWithParams(DPI_MAJOR_VERSION + 1, DPI_MINOR_VERSION, NULL, &context, &errorInfo); return dpiTestCase_expectError(testCase, "DPI-1020:"); } //----------------------------------------------------------------------------- // dpiTest_1002() // Verify that dpiContext_createWithParams() returns error DPI-1020 when // called with a minor version that doesn't match the one with which DPI was // compiled. //----------------------------------------------------------------------------- int dpiTest_1002(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo; dpiContext *context; dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION + 1, NULL, &context, &errorInfo); return dpiTestCase_expectError(testCase, "DPI-1020:"); } //----------------------------------------------------------------------------- // dpiTest_1003() // Verify that dpiContext_createWithParams() when passed a NULL pointer // returns error DPI-1046. //----------------------------------------------------------------------------- int dpiTest_1003(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo; dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, NULL, &errorInfo); return dpiTestCase_expectError(testCase, "DPI-1046:"); } //----------------------------------------------------------------------------- // dpiTest_1004() // Verify that dpiContext_destroy() when passed a NULL pointer returns error // DPI-1002. //----------------------------------------------------------------------------- int dpiTest_1004(dpiTestCase *testCase, dpiTestParams *params) { dpiContext_destroy(NULL); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1005() // Verify that dpiContext_destroy() called twice returns error DPI-1002. //----------------------------------------------------------------------------- int dpiTest_1005(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo; dpiContext *context; if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, &context, &errorInfo) < 0) return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); if (dpiContext_destroy(context) < 0) return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); dpiContext_destroy(context); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1006() // Verify that dpiContext_createWithParams() succeeds when valid // dpiContextCreateParams is passed. //----------------------------------------------------------------------------- int dpiTest_1006(dpiTestCase *testCase, dpiTestParams *params) { dpiContextCreateParams ctxParams = {0}; dpiErrorInfo errorInfo; dpiContext *context; ctxParams.defaultEncoding = "ASCII"; ctxParams.defaultDriverName = "dummy : 0.0.1"; if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, &ctxParams, &context, &errorInfo) < 0) return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); if (dpiContext_destroy(context) < 0) { dpiContext_getError(context, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1007() // Verify that dpiContext_createWithParams() can be called twice and the same // version information is provided in both cases. //----------------------------------------------------------------------------- int dpiTest_1007(dpiTestCase *testCase, dpiTestParams *params) { dpiVersionInfo versionInfo1, versionInfo2; dpiContext *context1, *context2; dpiErrorInfo errorInfo; // create first context if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, &context1, &errorInfo) < 0) return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); if (dpiContext_getClientVersion(context1, &versionInfo1) < 0) { dpiContext_getError(context1, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } // create second context if (dpiContext_createWithParams(DPI_MAJOR_VERSION, DPI_MINOR_VERSION, NULL, &context2, &errorInfo) < 0) return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); if (dpiContext_getClientVersion(context2, &versionInfo2) < 0) { dpiContext_getError(context2, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } // verify version information is the same if (dpiTestCase_expectUintEqual(testCase, versionInfo1.versionNum, versionInfo2.versionNum) < 0) return DPI_FAILURE; // cleanup if (dpiContext_destroy(context1) < 0) { dpiContext_getError(context1, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } if (dpiContext_destroy(context2) < 0) { dpiContext_getError(context2, &errorInfo); return dpiTestCase_setFailedFromErrorInfo(testCase, &errorInfo); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1000); dpiTestSuite_addCase(dpiTest_1000, "dpiContext_createWithParams() with valid major/minor versions"); dpiTestSuite_addCase(dpiTest_1001, "dpiContext_createWithParams() with invalid major version"); dpiTestSuite_addCase(dpiTest_1002, "dpiContext_createWithParams() with invalid minor version"); dpiTestSuite_addCase(dpiTest_1003, "dpiContext_createWithParams() with NULL pointer"); dpiTestSuite_addCase(dpiTest_1004, "dpiContext_destroy() with NULL pointer"); dpiTestSuite_addCase(dpiTest_1005, "dpiContext_destroy() called twice on same pointer"); dpiTestSuite_addCase(dpiTest_1006, "dpiContext_createWithParams() with creation parameters"); dpiTestSuite_addCase(dpiTest_1007, "dpiContext_createWithParams() twice"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1100_numbers.c000066400000000000000000000376431510466437300170050ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1100_numbers.c // Test suite for testing the handling of numbers. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_1100() // Verify that a large unsigned integer (larger than can be represented by // a signed integer) is transferred to Oracle and returned from Oracle // successfully as an Oracle number. //----------------------------------------------------------------------------- int dpiTest_1100(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numQueryColumns, bufferRowIndex; const char *sql = "select :1 from dual"; dpiData *varData; dpiConn *conn; dpiStmt *stmt; dpiVar *var; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); varData->isNull = 0; varData->value.asUint64 = 18446744073709551615UL; if (dpiStmt_bindByPos(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, varData->value.asBytes.ptr, varData->value.asBytes.length, "18446744073709551615", 20) < 0) return DPI_FAILURE; if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1101() // Verify that a large unsigned integer (larger than can be represented by // a signed integer) is transferred to Oracle and returned from Oracle // successfully as a native integer. //----------------------------------------------------------------------------- int dpiTest_1101(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numQueryColumns, bufferRowIndex; const char *sql = "select :1 from dual"; dpiData *varData; dpiConn *conn; dpiStmt *stmt; dpiVar *var; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_UINT, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); varData->isNull = 0; varData->value.asUint64 = 18446744073709551614UL; if (dpiStmt_bindByPos(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, varData->value.asBytes.ptr, varData->value.asBytes.length, "18446744073709551614", 20) < 0) return DPI_FAILURE; if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1102() // Verify that a large unsigned integer (larger than can be represented by // a signed integer) can be fetched from Oracle successfully as an Oracle // number. //----------------------------------------------------------------------------- int dpiTest_1102(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select 18446744073709551612 from dual"; uint32_t numQueryColumns, bufferRowIndex; dpiData *varData; dpiConn *conn; dpiStmt *stmt; dpiVar *var; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, varData->value.asUint64, 18446744073709551612UL) < 0) return DPI_FAILURE; if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1103() // Verify that a large unsigned integer (larger than can be represented by // a signed integer) can be fetched from Oracle successfully as a native // unsigned integer. //----------------------------------------------------------------------------- int dpiTest_1103(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select 18446744073709551613 from dual"; uint32_t numQueryColumns, bufferRowIndex; dpiData *varData; dpiConn *conn; dpiStmt *stmt; dpiVar *var; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_UINT, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, varData->value.asUint64, 18446744073709551613UL) < 0) return DPI_FAILURE; if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1104() // Verify that the value zero is returned properly when converted from a // string representing the number zero. Test with varying numbers of trailing // zeroes, with and without a decimal point. //----------------------------------------------------------------------------- int dpiTest_1104(dpiTestCase *testCase, dpiTestParams *params) { const char *values[] = { "0", "0.0", "0.00", "0.000" }; const char *sql = "select :1 from dual"; uint32_t numQueryColumns, bufferRowIndex; dpiData *inputVarData, *resultVarData; dpiVar *inputVar, *resultVar; dpiConn *conn; dpiStmt *stmt; int found, i; // create variables and prepare statement for execution if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &inputVar, &inputVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &resultVar, &resultVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); // test each of 4 different values for zero for (i = 0; i < 4; i++) { if (dpiVar_setFromBytes(inputVar, 0, values[i], strlen(values[i])) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, resultVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, resultVarData->value.asDouble, 0.0) < 0) return DPI_FAILURE; } // cleanup if (dpiVar_release(inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(resultVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1105() // Verify that values are bound as string and returned from the database with // the same value. //----------------------------------------------------------------------------- int dpiTest_1105(dpiTestCase *testCase, dpiTestParams *params) { const char *outValues[] = { "400000000", "1521000000000000", "5478000000000000000", "100000000000", "-1234567890123456789012345678901234567.8", "0", "0", "0", "0", "0.00000001", "0.000000001", NULL }; const char *inValues[] = { "4E+8", "1.521E+15", "5.478E+18", "1E+11", "-1234567890123456789012345678901234567.8", "0", "-0", "0.0", "-0.0", "1e-08", "1e-09", NULL }; const char *sql = "select :1 from dual"; dpiData *inputVarData, *resultVarData; dpiVar *inputVar, *resultVar; uint32_t bufferRowIndex; dpiConn *conn; dpiStmt *stmt; int found, i; // create variables and prepare statement for execution if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &inputVar, &inputVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &resultVar, &resultVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); // test each of the different values for (i = 0; inValues[i]; i++) { if (dpiVar_setFromBytes(inputVar, 0, inValues[i], strlen(inValues[i])) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, resultVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, resultVarData->value.asBytes.ptr, resultVarData->value.asBytes.length, outValues[i], strlen(outValues[i])) < 0) return DPI_FAILURE; } // cleanup if (dpiVar_release(inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(resultVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1100); dpiTestSuite_addCase(dpiTest_1100, "bind large unsigned integer as Oracle number"); dpiTestSuite_addCase(dpiTest_1101, "bind large unsigned integer as native unsigned integer"); dpiTestSuite_addCase(dpiTest_1102, "fetch large unsigned integer as Oracle number"); dpiTestSuite_addCase(dpiTest_1103, "fetch large unsigned integer as native unsigned integer"); dpiTestSuite_addCase(dpiTest_1104, "bind zero as a string value with trailing zeroes"); dpiTestSuite_addCase(dpiTest_1105, "bind numbers as strings and verify round trip"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1200_conn.c000066400000000000000000001011251510466437300162530ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1200_conn.c // Test suite for testing dpiConn functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__callFunctionsWithError() [INTERNAL] // Test all public functions with the specified connection and expect an // error for each one of them. //----------------------------------------------------------------------------- int dpiTest__callFunctionsWithError(dpiTestCase *testCase, dpiTestParams *params, dpiConn *conn, const char *expectedError) { uint32_t msgIdLength, valueLength, releaseStringLength, cacheSize; const char *sql = "SELECT count(*) FROM TestNumbers"; const char *msgId, *value, *releaseString; dpiSubscrCreateParams subscrParams; dpiVersionInfo versionInfo; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiEncodingInfo info; dpiMsgProps *props; dpiSubscr *subscr; dpiData *data; dpiStmt *stmt; void *handle; dpiLob *lob; dpiVar *var; dpiConn_breakExecution(conn); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_changePassword(conn, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, "X", 1); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_commit(conn); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_deqObject(conn, "X", 1, NULL, NULL, NULL, &msgId, &msgIdLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_enqObject(conn, "X", 1, NULL, NULL, NULL, &msgId, &msgIdLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getCurrentSchema(conn, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getEdition(conn, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getEncodingInfo(conn, &info); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getExternalName(conn, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getHandle(conn, &handle); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getInternalName(conn, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getLTXID(conn, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getObjectType(conn, NULL, 0, &objType); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getServerVersion(conn, &releaseString, &releaseStringLength, &versionInfo); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_getStmtCacheSize(conn, &cacheSize); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_newDeqOptions(conn, &deqOptions); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_newEnqOptions(conn, &enqOptions); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_newMsgProps(conn, &props); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_subscribe(conn, &subscrParams, &subscr); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_NUMBER, &lob); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 5, 50000, 0, 0, NULL, &var, &data); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_ping(conn); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_rollback(conn); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setAction(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setClientIdentifier(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setClientInfo(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setCurrentSchema(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setDbOp(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setExternalName(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setInternalName(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setModule(conn, value, valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_setStmtCacheSize(conn, 5); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_shutdownDatabase(conn, DPI_MODE_SHUTDOWN_DEFAULT); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_startupDatabase(conn, DPI_MODE_STARTUP_DEFAULT); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcBegin(conn, NULL, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcCommit(conn, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcEnd(conn, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcForget(conn, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcPrepare(conn, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcRollback(conn, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1200() // Verify that dpiConn_create() succeeds when valid credentials are passed // and both the dpiCommonParams and dpiConnCreateParams structures are NULL. //----------------------------------------------------------------------------- int dpiTest_1200(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1201() // Verify that dpiConn_create() fails when invalid credentials are passed. //----------------------------------------------------------------------------- int dpiTest_1201(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); dpiConn_create(context, "X", 1, "X", 1, params->connectString, params->connectStringLength, NULL, NULL, &conn); return dpiTestCase_expectError(testCase, "ORA-01017:"); } //----------------------------------------------------------------------------- // dpiTest_1202() // Call dpiConn_create() with valid credentials and both the parameters // commonParams and createParams initialize to all default values (no error). //----------------------------------------------------------------------------- int dpiTest_1202(dpiTestCase *testCase, dpiTestParams *params) { dpiCommonCreateParams commonParams; dpiConnCreateParams createParams; dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, &createParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1203() // Call dpiConn_create() with valid credentials; call dpiConn_getHandle() // to get the handle of the connection; call dpiConn_create() with // createParams->externalHandle set to that value; perform queries on both // connections to verify that they both work (no error). //----------------------------------------------------------------------------- int dpiTest_1203(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select count(*) from TestNumbers"; uint32_t numQueryColumns, bufferRowIndex; dpiConnCreateParams createParams; dpiNativeTypeNum nativeTypeNum; dpiConn *conn, *conn2; dpiContext *context; uint64_t count; dpiData *data; dpiStmt *stmt; void *handle; int found; // create first connection and get handle if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getHandle(conn, &handle) < 0) return dpiTestCase_setFailedFromError(testCase); // create second connection using handle of first connection dpiTestSuite_getContext(&context); if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.externalHandle = handle; if (dpiConn_create(context, NULL, 0, NULL, 0, NULL, 0, NULL, &createParams, &conn2) < 0) return dpiTestCase_setFailedFromError(testCase); // perform query on first connection if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); count = data->value.asUint64; dpiStmt_release(stmt); // perform query on second connection if (dpiConn_prepareStmt(conn2, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, data->value.asUint64, count) < 0) return DPI_FAILURE; dpiStmt_release(stmt); dpiConn_release(conn2); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1204() // Call dpiConn_create() with valid credentials; call dpiConn_getHandle() // to get the handle of the connection; call dpiConn_create() with // createParams->externalHandle set to that value; call dpiConn_close() on the // second connection (error DPI-1034). //----------------------------------------------------------------------------- int dpiTest_1204(dpiTestCase *testCase, dpiTestParams *params) { dpiConnCreateParams createParams; dpiConn *conn, *conn2; dpiContext *context; void *handle; // create first connection and get handle if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getHandle(conn, &handle) < 0) return dpiTestCase_setFailedFromError(testCase); // create second connection using handle of first connection dpiTestSuite_getContext(&context); if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.externalHandle = handle; if (dpiConn_create(context, NULL, 0, NULL, 0, NULL, 0, NULL, &createParams, &conn2) < 0) return dpiTestCase_setFailedFromError(testCase); // attempt to close second connection dpiConn_close(conn2, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0); if (dpiTestCase_expectError(testCase, "DPI-1034:") < 0) return DPI_FAILURE; dpiConn_release(conn2); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1205() // Call dpiConn_create() specifying a valid pool handle in // createParams->pool (no error). //----------------------------------------------------------------------------- int dpiTest_1205(dpiTestCase *testCase, dpiTestParams *params) { dpiConnCreateParams createParams; dpiContext *context; dpiConn *conn; dpiPool *pool; // create pool dpiTestSuite_getContext(&context); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // create connection from pool if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.pool = pool; if (dpiConn_create(context, NULL, 0, NULL, 0, NULL, 0, NULL, &createParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(conn); dpiPool_release(pool); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1206() // Call dpiConn_create() specifying an invalid pool handle in // createParams->pool (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1206(dpiTestCase *testCase, dpiTestParams *params) { dpiConnCreateParams createParams; dpiContext *context; dpiConn *conn; dpiPool *pool; // create and immediately destroy pool dpiTestSuite_getContext(&context); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); dpiPool_release(pool); // attempt to create connection using destroyed pool if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.pool = pool; dpiConn_create(context, NULL, 0, NULL, 0, NULL, 0, NULL, &createParams, &conn); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1207() // Call dpiConn_create() with valid credentials; call dpiConn_close() // and then call each of the public functions for dpiConn except for // dpiConn_addRef() and dpiConn_release() (error DPI-1010). //----------------------------------------------------------------------------- int dpiTest_1207(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__callFunctionsWithError(testCase, params, conn, "DPI-1010:"); } //----------------------------------------------------------------------------- // dpiTest_1208() // Call dpiConn_create() with NULL context (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1208(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiConn_create(NULL, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &conn); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1209() // Call dpiConn_create() with valid credentials; call dpiConn_release() // twice (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1209(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); testCase->conn = NULL; dpiConn_release(conn); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1210() // Call each of the public functions for dpiConn with the connection // parameter set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1210(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__callFunctionsWithError(testCase, params, NULL, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1211() // Call dpiPool_acquireConnection() with pool set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1211(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiPool_acquireConnection(NULL, NULL, 0, NULL, 0, NULL, &conn); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1212() // Call dpiPool_acquireConnection() with pool created using the common // session pool creation method (no error). //----------------------------------------------------------------------------- int dpiTest_1212(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiConn *conn; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiPool_release(pool); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1213() // Call dpiConn_create() and specify a new password in the // dpiConnCreateParams structure; create a new connection using the new // password to verify that the password was indeed changed (no error). //----------------------------------------------------------------------------- int dpiTest_1213(dpiTestCase *testCase, dpiTestParams *params) { dpiConnCreateParams createParams; const char *newPassword = "abc"; dpiContext *context; dpiConn *conn; // create connection and change password at the same time dpiTestSuite_getContext(&context); if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.newPassword = newPassword; createParams.newPasswordLength = strlen(newPassword); if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(conn); // create connection and change password back to original password createParams.newPassword = params->mainPassword; createParams.newPasswordLength = params->mainPasswordLength; if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, newPassword, strlen(newPassword), params->connectString, params->connectStringLength, NULL, &createParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1214() // Call dpiConn_create() and specify application context in the // dpiConnCreateParams structure; verify that the application context was // indeed set correctly (no error). //----------------------------------------------------------------------------- int dpiTest_1214(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context(:1, :2) from dual"; dpiData *namespaceData, *keyData, *valueData; dpiVar *namespaceVar, *keyVar, *valueVar; uint32_t numQueryColumns, bufferRowIndex; dpiConnCreateParams createParams; dpiAppContext appContext; dpiContext *context; dpiStmt *stmt; dpiConn *conn; int found; // initialize application context appContext.namespaceName = "E2E_CONTEXT"; appContext.namespaceNameLength = strlen(appContext.namespaceName); appContext.name = "MY_NAME"; appContext.nameLength = strlen(appContext.name); appContext.value = "MY_VAL"; appContext.valueLength = strlen(appContext.value); // create connection using application context dpiTestSuite_getContext(&context); if (dpiContext_initConnCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.appContext = &appContext; createParams.numAppContext = 1; if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); // perform query to determine if application context was set correctly if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 30, 1, 0, NULL, &namespaceVar, &namespaceData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 30, 1, 0, NULL, &keyVar, &keyData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 30, 1, 0, NULL, &valueVar, &valueData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(namespaceVar, 0, appContext.namespaceName, appContext.namespaceNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(keyVar, 0, appContext.name, appContext.nameLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, namespaceVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, keyVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, valueVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, valueData->value.asBytes.ptr, valueData->value.asBytes.length, appContext.value, appContext.valueLength) < 0) return DPI_FAILURE; dpiVar_release(namespaceVar); dpiVar_release(keyVar); dpiVar_release(valueVar); dpiStmt_release(stmt); dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1215() // Call dpiConn_create() and close connection twice expected error. //----------------------------------------------------------------------------- int dpiTest_1215(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0); return dpiTestCase_expectError(testCase, "DPI-1010:"); } //----------------------------------------------------------------------------- // dpiTest_1216() // Call dpiConn_setCallTimeout() and verify it works as expected by returning // a timeout error or connection closed error (DPI-1067/DPI-1080). //----------------------------------------------------------------------------- int dpiTest_1216(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "DPI-1067:", "DPI-1080:", NULL }; const char *sql = "begin dbms_session.sleep(10); end;"; uint32_t setTimeout = 250; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 18, 5) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setCallTimeout(conn, setTimeout) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1217() // Call dpiConn_setCallTimeout() and dpiConn_getCallTimeout() and verify // they work as expected. //----------------------------------------------------------------------------- int dpiTest_1217(dpiTestCase *testCase, dpiTestParams *params) { uint32_t expectedValue = 738, actualValue; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 18, 5) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setCallTimeout(conn, expectedValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getCallTimeout(conn, &actualValue) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, actualValue, expectedValue); } //----------------------------------------------------------------------------- // dpiTest_1218() // Verify that dpiConn_create() fails with ORA-12154 error when connection // failure occurs. //----------------------------------------------------------------------------- int dpiTest_1218(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-12154:", "ORA-12262:", NULL }; dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, "invalid/orclpdb", strlen("invalid/orclpdb"), NULL, NULL, &conn); return dpiTestCase_expectAnyError(testCase, expectedErrors); } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1200); dpiTestSuite_addCase(dpiTest_1200, "dpiConn_create() with valid credentials, no parameters"); dpiTestSuite_addCase(dpiTest_1201, "dpiConn_create() with invalid credentials fails"); dpiTestSuite_addCase(dpiTest_1202, "dpiConn_create() with valid credentials and params"); dpiTestSuite_addCase(dpiTest_1203, "dpiConn_create() with external handle"); dpiTestSuite_addCase(dpiTest_1204, "dpiConn_create() with external handle and close"); dpiTestSuite_addCase(dpiTest_1205, "dpiConn_create() with valid pool handle"); dpiTestSuite_addCase(dpiTest_1206, "dpiConn_create() with an invalid pool handle"); dpiTestSuite_addCase(dpiTest_1207, "call connection functions with closed connection"); dpiTestSuite_addCase(dpiTest_1208, "dpiConn_create() with NULL context"); dpiTestSuite_addCase(dpiTest_1209, "dpiConn_create() with dpiConn_release() twice"); dpiTestSuite_addCase(dpiTest_1210, "call connection functions with NULL connection"); dpiTestSuite_addCase(dpiTest_1211, "dpiPool_acquireConnection() with NULL pool"); dpiTestSuite_addCase(dpiTest_1212, "dpiPool_acquireConnection() with valid pool"); dpiTestSuite_addCase(dpiTest_1213, "dpiConn_create() with new password"); dpiTestSuite_addCase(dpiTest_1214, "dpiConn_create() with application context"); dpiTestSuite_addCase(dpiTest_1215, "dpiConn_create() and call dpiConn_close() twice"); dpiTestSuite_addCase(dpiTest_1216, "verify dpiConn_setCallTimeout()"); dpiTestSuite_addCase(dpiTest_1217, "verify dpiConn_setCallTimeout()/dpiConn_getCallTimeout()"); dpiTestSuite_addCase(dpiTest_1218, "verify dpiConn_create() fails with ORA error during conn failure"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1300_conn_properties.c000066400000000000000000000714521510466437300205410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1300_conn_properties.c // Test suite for testing connection properties. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__checkAttribute() // Using the provided SQL, check that the value returned matches the value // that was set. //----------------------------------------------------------------------------- static int dpiTest__checkAttribute(dpiTestCase *testCase, dpiConn *conn, const char *sql, const char *setValue, uint32_t setValueLength) { dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiData *getValue; dpiStmt *stmt; int found; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (setValueLength == 0) setValueLength = (uint32_t) strlen(setValue); if (dpiTestCase_expectStringEqual(testCase, getValue->value.asBytes.ptr, getValue->value.asBytes.length, setValue, setValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__checkServerVersionInfo() // Check the server version information, taking into account the changes made // to how the server version is reported in different versions of the database. //----------------------------------------------------------------------------- static int dpiTest__checkServerVersionInfo(dpiTestCase *testCase, const char **releaseString, uint32_t *releaseStringLength) { const char *sql = "select version_full from product_component_version " "where product like 'Oracle Database%'"; const char *sqlPre18 = "select version from product_component_version " "where product like 'Oracle Database%'"; const char *versionFormat = "%d.%d.%d.%d.%02d"; const char *versionFormatPre23 = "%d.%d.%d.%d.%d"; dpiVersionInfo versionInfo, *clientVersionInfo; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; char tempVersion[40]; dpiData *getValue; dpiConn *conn; dpiStmt *stmt; int found; dpiTestSuite_getClientVersionInfo(&clientVersionInfo); if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getServerVersion(conn, releaseString, releaseStringLength, &versionInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (versionInfo.versionNum < 23) versionFormat = versionFormatPre23; snprintf(tempVersion, sizeof(tempVersion), versionFormat, versionInfo.versionNum, versionInfo.releaseNum, versionInfo.updateNum, versionInfo.portReleaseNum, versionInfo.portUpdateNum); if (versionInfo.versionNum < 18 || clientVersionInfo->versionNum < 18) sql = sqlPre18; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, tempVersion, strlen(tempVersion), getValue->value.asBytes.ptr, getValue->value.asBytes.length) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1300() // Call dpiConn_setCurrentSchema() with an invalid schema name; perform any // query (error ORA-01435/ORA-28726). //----------------------------------------------------------------------------- int dpiTest_1300(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-01435:", "ORA-28726:", NULL }; const char *sql_query = "SELECT count(*) FROM TestNumbers"; uint32_t numQueryColumns; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setCurrentSchema(conn, "x", strlen("x")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql_query, strlen(sql_query), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_execute(stmt, 0, &numQueryColumns); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1301() // Call dpiConn_getEdition() and verify that the value returned is an empty // string. //----------------------------------------------------------------------------- int dpiTest_1301(dpiTestCase *testCase, dpiTestParams *params) { uint32_t valueLength; const char *value; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getEdition(conn, &value, &valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectStringEqual(testCase, value, valueLength, "", 0); } //----------------------------------------------------------------------------- // dpiTest_1302() // Call dpiConn_create() specifying a value for the encoding and nencoding // attributes of the dpiCommonCreateParams structure and then call // dpiConn_getEncodingInfo() to verify that the values match (no error). //----------------------------------------------------------------------------- int dpiTest_1302(dpiTestCase *testCase, dpiTestParams *params) { const char *charSet = "ISO-8859-13"; dpiCommonCreateParams commonParams; dpiEncodingInfo info; dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.encoding = charSet; commonParams.nencoding = charSet; if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(conn, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.encoding, strlen(info.encoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, info.nencoding, strlen(info.nencoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1303() // Call dpiConn_create() specifying an invalid value for the encoding or // nencoding attributes of the dpiCommonCreateParams structure // (error DPI-1026). //----------------------------------------------------------------------------- int dpiTest_1303(dpiTestCase *testCase, dpiTestParams *params) { dpiCommonCreateParams commonParams; const char *charSet = "xx"; dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.encoding = charSet; commonParams.nencoding = charSet; dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &conn); return dpiTestCase_expectError(testCase, "DPI-1026:"); } //----------------------------------------------------------------------------- // dpiTest_1304() // Call dpiConn_getExternalName() and verify that the value returned is an // empty string; call dpiConn_setExternalName() with any value and then call // dpiConn_getExternalName() to verify that the values match (no error). //----------------------------------------------------------------------------- int dpiTest_1304(dpiTestCase *testCase, dpiTestParams *params) { const char *value, *setValue = "xx"; uint32_t valueLength; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getExternalName(conn, &value, &valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, value, valueLength, "", 0) < 0) return DPI_FAILURE; if (dpiConn_setExternalName(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getExternalName(conn, &value, &valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectStringEqual(testCase, value, valueLength, setValue, strlen(setValue)); } //----------------------------------------------------------------------------- // dpiTest_1305() // Call dpiConn_getInternalName() and verify that the value returned is an // empty string; call dpiConn_setInternalName() with any value and then call // dpiConn_getInternalName() to verify that the values match (no error). //----------------------------------------------------------------------------- int dpiTest_1305(dpiTestCase *testCase, dpiTestParams *params) { const char *value, *setValue = "xyz"; uint32_t valueLength; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getInternalName(conn, &value, &valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, value, valueLength, "", 0) < 0) return DPI_FAILURE; if (dpiConn_setInternalName(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getInternalName(conn, &value, &valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectStringEqual(testCase, value, valueLength, setValue, strlen(setValue)); } //----------------------------------------------------------------------------- // dpiTest_1306() // Call dpiConn_getStmtCacheSize() and verify that the value returned matches // the default value (20) (no error), verify that the value returned matches // the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_1306(dpiTestCase *testCase, dpiTestParams *params) { uint32_t cacheSize, defCacheSize = 20, setCacheSize = 22; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getStmtCacheSize(conn, &cacheSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, cacheSize, defCacheSize) < 0) return DPI_FAILURE; if (dpiConn_setStmtCacheSize(conn, setCacheSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getStmtCacheSize(conn, &cacheSize) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, cacheSize, setCacheSize); } //----------------------------------------------------------------------------- // dpiTest_1307() // Call dpiConn_create() specifying a value for the encoding and null for // nencoding of the dpiCommonCreateParams structure and then call // dpiConn_getEncodingInfo() to verify that the values are as expected. //----------------------------------------------------------------------------- int dpiTest_1307(dpiTestCase *testCase, dpiTestParams *params) { const char *charSet = "ISO-8859-13"; dpiCommonCreateParams commonParams; dpiEncodingInfo info, defaultInfo; dpiConn *conn, *defaultConn; dpiContext *context; // get default encodings dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &defaultConn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(defaultConn, &defaultInfo) < 0) return dpiTestCase_setFailedFromError(testCase); // get connection with just the encoding specified if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.encoding = charSet; if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(conn, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.encoding, strlen(info.encoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, info.nencoding, strlen(info.nencoding), defaultInfo.nencoding, strlen(defaultInfo.nencoding)) < 0) return DPI_FAILURE; if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // get connection with just the nencoding specified if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.nencoding = charSet; if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(conn, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.encoding, strlen(info.encoding), defaultInfo.encoding, strlen(defaultInfo.encoding)) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, info.nencoding, strlen(info.nencoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiConn_release(defaultConn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1308() // Call dpiConn_setClientIdentifier() and check that the value has been set // correctly by querying the value from the database (no error). //----------------------------------------------------------------------------- int dpiTest_1308(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context('userenv', 'client_identifier') from dual"; const char *setValue = "ODPIC_TEST_CLIENT_IDENTIFIER"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setClientIdentifier(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__checkAttribute(testCase, conn, sql, setValue, 0); } //----------------------------------------------------------------------------- // dpiTest_1309() // Call dpiConn_setClientInfo() and check that the value has been set // correctly by querying the value from the database (no error). //----------------------------------------------------------------------------- int dpiTest_1309(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context('userenv', 'client_info') from dual"; const char *setValue = "ODPIC_TEST_CLIENTINFO"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setClientInfo(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__checkAttribute(testCase, conn, sql, setValue, 0); } //----------------------------------------------------------------------------- // dpiTest_1310() // Call dpiConn_setAction() and check that the value has been set correctly // by querying the value from the database (no error) //----------------------------------------------------------------------------- int dpiTest_1310(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context('userenv', 'action') from dual"; const char *setValue = "ODPIC_TEST_ACTION"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setAction(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__checkAttribute(testCase, conn, sql, setValue, 0); } //----------------------------------------------------------------------------- // dpiTest_1311() // Call dpiConn_setModule() and check that the value has been set correctly // by querying the value from the database (no error). //----------------------------------------------------------------------------- int dpiTest_1311(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context('userenv', 'module') from dual"; const char *setValue = "ODPIC_TEST_MODULE"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setModule(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__checkAttribute(testCase, conn, sql, setValue, 0); } //----------------------------------------------------------------------------- // dpiTest_1312() // Call dpiConn_setCurrentSchema() with a valid schema name and check that // the value has been set correctly by querying the value from the database // (no error). //----------------------------------------------------------------------------- int dpiTest_1312(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sys_context('userenv', 'current_schema') from dual"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setCurrentSchema(conn, params->editionUserName, params->editionUserNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__checkAttribute(testCase, conn, sql, params->editionUserName, params->editionUserNameLength); } //----------------------------------------------------------------------------- // dpiTest_1313() // Call dpiConn_getCurrentSchema() and verify that the value returned is an // empty string; call dpiConn_setCurrentSchema() followed by // dpiConn_getCurrentSchema() and verify that the value is identical to // what was set (no error). //----------------------------------------------------------------------------- int dpiTest_1313(dpiTestCase *testCase, dpiTestParams *params) { uint32_t getValueLength; const char *getValue; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getCurrentSchema(conn, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, "", 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_setCurrentSchema(conn, params->editionUserName, params->editionUserNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getCurrentSchema(conn, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, params->editionUserName, params->editionUserNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1314() // Call dpiConn_create() specifying a value for the edition attribute of the // dpiCommonCreateParams structure and then call dpiConn_getEdition() and // verify that the value returned matches the value passed to the connection // creation routine (no error). //----------------------------------------------------------------------------- int dpiTest_1314(dpiTestCase *testCase, dpiTestParams *params) { dpiCommonCreateParams commonParams; uint32_t getValueLength; const char *getValue; dpiContext *context; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.edition = params->editionName; commonParams.editionLength = params->editionNameLength; if (dpiConn_create(context, params->editionUserName, params->editionUserNameLength, params->editionPassword, params->editionPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEdition(conn, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, params->editionName, params->editionNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1315() // Call dpiConn_setDbOp() and check that the value has been set correctly by // querying the value from the database (no error). //----------------------------------------------------------------------------- int dpiTest_1315(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select dbop_name from v$sql_monitor " "where sid = sys_context('userenv', 'sid') " "and status = 'EXECUTING'"; const char *setValue = "ODPIC_TEST_DBOP"; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_setDbOp(conn, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__checkAttribute(testCase, conn, sql, setValue, 0); } //----------------------------------------------------------------------------- // dpiTest_1316() // Call dpiConn_getLTXID() and verify that the value returned is an empty // string (no error). //----------------------------------------------------------------------------- int dpiTest_1316(dpiTestCase *testCase, dpiTestParams *params) { uint32_t getValueLength; const char *getValue; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getLTXID(conn, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, "", 0); } //----------------------------------------------------------------------------- // dpiTest_1317() // Call dpiConn_getServerVersion() and verify that the values returned // matches the database version that is being used (no error). //----------------------------------------------------------------------------- int dpiTest_1317(dpiTestCase *testCase, dpiTestParams *params) { uint32_t releaseStringLength; const char *releaseString; return dpiTest__checkServerVersionInfo(testCase, &releaseString, &releaseStringLength); } //----------------------------------------------------------------------------- // dpiTest_1318() // Call dpiConn_getServerVersion() with release string as NULL and verify // that the values returned matches the database version that is being used (no // error). //----------------------------------------------------------------------------- int dpiTest_1318(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__checkServerVersionInfo(testCase, NULL, 0); } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1300); dpiTestSuite_addCase(dpiTest_1300, "dpiConn_setCurrentSchema() with an invalid schema name"); dpiTestSuite_addCase(dpiTest_1301, "dpiConn_getEdition() with no edition set"); dpiTestSuite_addCase(dpiTest_1302, "dpiConn_create() specifying a value for the encoding"); dpiTestSuite_addCase(dpiTest_1303, "dpiConn_create() specifying an invalid value for the encoding"); dpiTestSuite_addCase(dpiTest_1304, "check get / set external name"); dpiTestSuite_addCase(dpiTest_1305, "check get / set internal name"); dpiTestSuite_addCase(dpiTest_1306, "check get / set statement cache size"); dpiTestSuite_addCase(dpiTest_1307, "specifying a value for the encoding and null for nencoding"); dpiTestSuite_addCase(dpiTest_1308, "verify client identifier attr is set as expected"); dpiTestSuite_addCase(dpiTest_1309, "verify client info attr is set as expected"); dpiTestSuite_addCase(dpiTest_1310, "verify action attr is set as expected"); dpiTestSuite_addCase(dpiTest_1311, "verify module attr is set as expected"); dpiTestSuite_addCase(dpiTest_1312, "verify current schema is set as expected"); dpiTestSuite_addCase(dpiTest_1313, "verify dpiConn_getCurrentSchema() works as expected"); dpiTestSuite_addCase(dpiTest_1314, "verify dpiConn_getEdition() works as expected"); dpiTestSuite_addCase(dpiTest_1315, "verify DBOP attr is set as expected"); dpiTestSuite_addCase(dpiTest_1316, "verify dpiConn_getLTXID() works as expected"); dpiTestSuite_addCase(dpiTest_1317, "verify dpiConn_getServerVersion() with release string"); dpiTestSuite_addCase(dpiTest_1318, "verify dpiConn_getServerVersion() with NULL release string"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1400_pool.c000066400000000000000000001213301510466437300162710ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1400_pool.c // Test suite for testing dpiPool functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__callFunctionsWithError() [INTERNAL] // Call all public functions with the specified pool and expect an error for // each of them. //----------------------------------------------------------------------------- int dpiTest__callFunctionsWithError(dpiTestCase *testCase, dpiTestParams *params, dpiPool *pool, const char *expectedError) { dpiEncodingInfo info; dpiPoolGetMode value; int pingInterval; uint32_t count; dpiConn *conn; dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_close(pool, DPI_MODE_POOL_CLOSE_DEFAULT); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getBusyCount(pool, &count); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getEncodingInfo(pool, &info); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getGetMode(pool, &value); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getMaxLifetimeSession(pool, &count); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getOpenCount(pool, &count); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getTimeout(pool, &count); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_setGetMode(pool, value); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_setMaxLifetimeSession(pool, 5); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_setTimeout(pool, 5); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_setMaxSessionsPerShard(pool, 5); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getMaxSessionsPerShard(pool, &count); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_setPingInterval(pool, 30); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_getPingInterval(pool, &pingInterval); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiPool_reconfigure(pool, 1, 5, 1); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__acquireAndVerifySession() [INTERNAL] // Acquire a session from the pool using the given credentials and then // verify that the session user and proxy user are the expected values. //----------------------------------------------------------------------------- static int dpiTest__acquireAndVerifySession(dpiTestCase *testCase, dpiPool *pool, const char *userName, uint32_t userNameLength, const char *password, uint32_t passwordLength, const char *expectedSessionUser, uint32_t expectedSessionUserLength, const char *proxyUser, uint32_t proxyUserLength) { const char *sql = "select sys_context('userenv', 'session_user'), " "sys_context('userenv', 'proxy_user') from dual"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiData *getValue; dpiStmt *stmt; dpiConn *conn; int found; // acquire connection from the pool if (dpiPool_acquireConnection(pool, userName, userNameLength, password, passwordLength, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch session user and proxy user if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue->value.asBytes.ptr, getValue->value.asBytes.length, expectedSessionUser, expectedSessionUserLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue->value.asBytes.ptr, getValue->value.asBytes.length, proxyUser, proxyUserLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1400() // Verify that dpiPool_create() succeeds when valid credentials are passed // and both the dpiCommonParams and dpiPoolCreateParams structures are NULL. //----------------------------------------------------------------------------- int dpiTest_1400(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1401() // Verify that dpiPool_create() succeeds when valid credentials are passed // and dpiCommonParams structure set to NULL. //----------------------------------------------------------------------------- int dpiTest_1401(dpiTestCase *testCase, dpiTestParams *params) { dpiCommonCreateParams commonParams; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1402() // Verify that dpiPool_create() succeeds when valid credentials are passed // and dpiPoolCreateParams structure set to NULL. //----------------------------------------------------------------------------- int dpiTest_1402(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1403() // Verify that dpiPool_create() succeeds when valid credentials are passed // and both the dpiCommonParams and dpiPoolCreateParams structures are set. //----------------------------------------------------------------------------- int dpiTest_1403(dpiTestCase *testCase, dpiTestParams *params) { dpiCommonCreateParams commonParams; dpiPoolCreateParams createParams; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1404() // Verify that dpiPool_create() fails when invalid credentials are passed. //----------------------------------------------------------------------------- int dpiTest_1404(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); dpiPool_create(context, "X", 1, "X", 1, params->connectString, params->connectStringLength, NULL, NULL, &pool); return dpiTestCase_expectError(testCase, "ORA-01017:"); } //----------------------------------------------------------------------------- // dpiTest_1405() // Verify that dpiPool_create() specifying a non-default value for // minSessions and confirm that this number of sessions is created (no error). //----------------------------------------------------------------------------- int dpiTest_1405(dpiTestCase *testCase, dpiTestParams *params) { uint32_t count; dpiPool *pool; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // verify open count matches the minimum number of sessions if (dpiPool_getOpenCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, DPI_TEST_POOL_MIN_SESSIONS) < 0) return DPI_FAILURE; // cleanup if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1406() // Verify that dpiPool_create() specifying a non-default value for // maxSessions and confirm that this number of sessions is the maximum that is // created (no error). //----------------------------------------------------------------------------- int dpiTest_1406(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-24418:", "ORA-24496:", NULL }; dpiConn *conn[DPI_TEST_POOL_MAX_SESSIONS], *tempConn; uint32_t count, i; dpiPool *pool; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // acquire connections up to the maximum for (i = 0; i < DPI_TEST_POOL_MAX_SESSIONS; i++) { if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // verify that the open count matches if (dpiPool_getOpenCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, DPI_TEST_POOL_MAX_SESSIONS) < 0) return DPI_FAILURE; // attempt to acquire one more connection dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &tempConn); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; // cleanup for (i = 0; i < DPI_TEST_POOL_MAX_SESSIONS; i++) { if (dpiConn_release(conn[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1407() // Verify that dpiPool_create() specifying a non-default value for // sessionIncrement and confirm that this number of sessions is created each // time more session are needed (no error). //----------------------------------------------------------------------------- int dpiTest_1407(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn[DPI_TEST_POOL_MIN_SESSIONS + 1]; uint32_t count, i; dpiPool *pool; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // acquire connections up to the minimum number of sessions for (i = 0; i < DPI_TEST_POOL_MIN_SESSIONS; i++) { if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // verify that the number of open connections matches if (dpiPool_getOpenCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, DPI_TEST_POOL_MIN_SESSIONS) < 0) return DPI_FAILURE; // acquire one more connection; this should create the number of // connections defined by the session increment if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn[DPI_TEST_POOL_MIN_SESSIONS]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getOpenCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, DPI_TEST_POOL_MIN_SESSIONS + DPI_TEST_POOL_SESSION_INCREMENT) < 0) return DPI_FAILURE; // cleanup for (i = 0; i < DPI_TEST_POOL_MIN_SESSIONS + 1; i++) { if (dpiConn_release(conn[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1408() // Verify that dpiPool_create() specifying no wait for the get mode works as // expected (no error). //----------------------------------------------------------------------------- int dpiTest_1408(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-24418:", "ORA-24496:", NULL }; dpiPoolCreateParams createParams; dpiConn *conn1, *conn2; dpiContext *context; dpiPool *pool; // create a pool that can contain only one connection dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.minSessions = 0; createParams.maxSessions = 1; createParams.sessionIncrement = 1; createParams.getMode = DPI_MODE_POOL_GET_NOWAIT; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire that connection from the pool if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn1) < 0) return dpiTestCase_setFailedFromError(testCase); // attempt to acquire a second connection from the pool; this should fail dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn2); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; // cleanup if (dpiConn_release(conn1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1409() // Verify that dpiPool_create() specifying force get for the get mode works // as expected (no error). //----------------------------------------------------------------------------- int dpiTest_1409(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; dpiConn *conn1, *conn2; dpiContext *context; dpiPool *pool; // create a pool that can contain only one connection dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.minSessions = 0; createParams.maxSessions = 1; createParams.sessionIncrement = 1; createParams.getMode = DPI_MODE_POOL_GET_FORCEGET; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire that connection from the pool if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn1) < 0) return dpiTestCase_setFailedFromError(testCase); // attempt to acquire a second connection from the pool; this should // succeed, even though the maximum number of sessions has been reached if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn2) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiConn_release(conn1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1410() // Verify that dpiPool_create() with NULL context (error DPI-1002) //----------------------------------------------------------------------------- int dpiTest_1410(dpiTestCase *testCase, dpiTestParams *params) { dpiPool *pool; dpiPool_create(NULL, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1411() // Verify that dpiPool_create() followed by dpiPool_release() twice // (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1411(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool) < 0) return DPI_SUCCESS; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); dpiPool_release(pool); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_1412() // Call dpiPool_create() with valid credentials and call dpiPool_close(); // then call all other public dpiPool functions except for dpiPool_addRef() and // dpiPool_release() (error DPI-1010). //----------------------------------------------------------------------------- int dpiTest_1412(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_close(pool, DPI_MODE_POOL_CLOSE_DEFAULT) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__callFunctionsWithError(testCase, params, pool, "DPI-1010: not connected") < 0) return DPI_FAILURE; dpiPool_release(pool); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1413() // Call each of the public functions for dpiPool with the pool parameter set // to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1413(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__callFunctionsWithError(testCase, params, NULL, "DPI-1002: invalid dpiPool handle"); } //----------------------------------------------------------------------------- // dpiTest_1414() // Verify that proxy authentication can be used with a pool (no error). //----------------------------------------------------------------------------- int dpiTest_1414(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.homogeneous = 0; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__acquireAndVerifySession(testCase, pool, params->proxyUserName, params->proxyUserNameLength, NULL, 0, params->proxyUserName, params->proxyUserNameLength, params->mainUserName, params->mainUserNameLength) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1415() // Verify that proxy authentication cannot be used with a homogeneous pool // (error DPI-1012). //----------------------------------------------------------------------------- int dpiTest_1415(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; dpiContext *context; dpiPool *pool; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.homogeneous = 1; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); dpiPool_acquireConnection(pool, params->proxyUserName, params->proxyUserNameLength, NULL, 0, NULL, &conn); if (dpiTestCase_expectError(testCase, "DPI-1012:") < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1416() // Call dpiPool_create with valid credentials and NULL pool (error DPI-1046). //----------------------------------------------------------------------------- int dpiTest_1416(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiTestSuite_getContext(&context); dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, NULL); return dpiTestCase_expectError(testCase, "DPI-1046:"); } //----------------------------------------------------------------------------- // dpiTest_1417() // Call dpiPool_create with no credentials (error ORA-24415). //----------------------------------------------------------------------------- int dpiTest_1417(dpiTestCase *testCase, dpiTestParams *params) { dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); dpiPool_create(context, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, &pool); return dpiTestCase_expectError(testCase, "ORA-24415:"); } //----------------------------------------------------------------------------- // dpiTest_1418() // Verify that dpiPool_create() fails when an invalid connect string // is passed (error ORA-12154). //----------------------------------------------------------------------------- int dpiTest_1418(dpiTestCase *testCase, dpiTestParams *params) { const char *connectString = "an_invalid_connect_string"; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, connectString, strlen(connectString), NULL, NULL, &pool); return dpiTestCase_expectError(testCase, "ORA-12154:"); } //----------------------------------------------------------------------------- // dpiTest_1419() // Create a heterogeneous pool with credentials and verify that acquiring // connections from it works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_1419(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; uint32_t userNameLength; dpiContext *context; char *userName; dpiPool *pool; // create heterogeneous pool with credentials specified dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.homogeneous = 0; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // acquiring connection without password if (dpiTest__acquireAndVerifySession(testCase, pool, NULL, 0, NULL, 0, params->mainUserName, params->mainUserNameLength, NULL, 0) < 0) return DPI_FAILURE; // acquiring connection with the same user name and pasword specified if (dpiTest__acquireAndVerifySession(testCase, pool, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->mainUserName, params->mainUserNameLength, NULL, 0) < 0) return DPI_FAILURE; // acquiring connection with a different user name and pasword specified if (dpiTest__acquireAndVerifySession(testCase, pool, params->proxyUserName, params->proxyUserNameLength, params->proxyPassword, params->proxyPasswordLength, params->proxyUserName, params->proxyUserNameLength, NULL, 0) < 0) return DPI_FAILURE; // acquiring connection with proxy syntax userNameLength = params->mainUserNameLength + params->proxyUserNameLength + 2; userName = malloc(userNameLength + 1); if (!userName) return dpiTestCase_setFailed(testCase, "Out of memory!"); sprintf(userName, "%.*s[%.*s]", params->mainUserNameLength, params->mainUserName, params->proxyUserNameLength, params->proxyUserName); if (dpiTest__acquireAndVerifySession(testCase, pool, userName, userNameLength, params->mainPassword, params->mainPasswordLength, params->proxyUserName, params->proxyUserNameLength, params->mainUserName, params->mainUserNameLength) < 0) return DPI_FAILURE; free(userName); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1420() // Create a heterogeneous pool with no credentials and verify that acquiring // connections from it works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_1420(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; uint32_t userNameLength; dpiContext *context; char *userName; dpiPool *pool; // create heterogeneous pool with no credentials specified dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.homogeneous = 0; if (dpiPool_create(context, NULL, 0, NULL, 0, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // acquiring connection with the main user name and pasword specified if (dpiTest__acquireAndVerifySession(testCase, pool, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->mainUserName, params->mainUserNameLength, NULL, 0) < 0) return DPI_FAILURE; // acquiring connection with the proxy user name and pasword specified if (dpiTest__acquireAndVerifySession(testCase, pool, params->proxyUserName, params->proxyUserNameLength, params->proxyPassword, params->proxyPasswordLength, params->proxyUserName, params->proxyUserNameLength, NULL, 0) < 0) return DPI_FAILURE; // acquiring connection with proxy syntax userNameLength = params->mainUserNameLength + params->proxyUserNameLength + 2; userName = malloc(userNameLength + 1); if (!userName) return dpiTestCase_setFailed(testCase, "Out of memory!"); sprintf(userName, "%.*s[%.*s]", params->mainUserNameLength, params->mainUserName, params->proxyUserNameLength, params->proxyUserName); if (dpiTest__acquireAndVerifySession(testCase, pool, userName, userNameLength, params->mainPassword, params->mainPasswordLength, params->proxyUserName, params->proxyUserNameLength, params->mainUserName, params->mainUserNameLength) < 0) return DPI_FAILURE; free(userName); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1421() // Verify that attempting to acquire a connection from a heterogeneous pool // with invalid or missing credentials fails as expected (ORA-24415, ORA-01017, // and ORA-24419). //----------------------------------------------------------------------------- int dpiTest_1421(dpiTestCase *testCase, dpiTestParams *params) { const char *invalidPassword = "an_invalid_password"; dpiPoolCreateParams createParams; dpiContext *context; dpiPool *pool; dpiConn *conn; // create heterogeneous pool without credentials dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); createParams.homogeneous = 0; if (dpiPool_create(context, NULL, 0, NULL, 0, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire connection without specifying credentials dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn); if (dpiTestCase_expectError(testCase, "ORA-24415:") < 0) return DPI_FAILURE; // acquire connection with invalid password dpiPool_acquireConnection(pool, params->mainUserName, params->mainUserNameLength, invalidPassword, strlen(invalidPassword), NULL, &conn); if (dpiTestCase_expectError(testCase, "ORA-01017:") < 0) return DPI_FAILURE; // acquire connection with user name but no password dpiPool_acquireConnection(pool, params->proxyUserName, params->proxyUserNameLength, NULL, 0, NULL, &conn); if (dpiTestCase_expectError(testCase, "ORA-24419:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1422() // Verify that dpiPool_setPingInterval() and dpiPool_getPingInterval() work // as expected. //----------------------------------------------------------------------------- int dpiTest_1422(dpiTestCase *testCase, dpiTestParams *params) { int getVal, setVal; dpiPool *pool; if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; if (dpiPool_getPingInterval(pool, &getVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getVal, DPI_DEFAULT_PING_INTERVAL) < 0) return DPI_FAILURE; setVal = -1; if (dpiPool_setPingInterval(pool, setVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getPingInterval(pool, &getVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getVal, setVal) < 0) return DPI_FAILURE; setVal = 30; if (dpiPool_setPingInterval(pool, setVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getPingInterval(pool, &getVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getVal, setVal) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1423() // Verify dpiPool_reconfigure() adjusts maximum sessions correctly. //----------------------------------------------------------------------------- int dpiTest_1423(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-24418:", "ORA-24496:", NULL }; uint32_t minSessions = 1, maxSessions = 3, sessionIncrement = 1; dpiConn *connections[3], *tempConn; dpiPool *pool; int i; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // acquire 3 connections from the pool for (i = 0; i < 3; i++) { if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &connections[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // the fourth connection should be able to be acquired as well if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &tempConn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(tempConn) < 0) return dpiTestCase_setFailedFromError(testCase); // reconfigure the pool to only allow a maximum of 3 sessions if (dpiPool_reconfigure(pool, minSessions, maxSessions, sessionIncrement) < 0) return dpiTestCase_setFailedFromError(testCase); // now attempt to acquire the fourth connection, which should fail dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &tempConn); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; // release the third connection; an attempt to acquire the third connection // should now succeed if (dpiConn_release(connections[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &tempConn) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiConn_release(tempConn) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < 2; i++) { if (dpiConn_release(connections[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1400); dpiTestSuite_addCase(dpiTest_1400, "dpiPool_create() with valid credentials, no parameters"); dpiTestSuite_addCase(dpiTest_1401, "dpiPool_create() with valid credentials and common params"); dpiTestSuite_addCase(dpiTest_1402, "dpiPool_create() with valid credentials and create params"); dpiTestSuite_addCase(dpiTest_1403, "dpiPool_create() with valid credentials and both params"); dpiTestSuite_addCase(dpiTest_1404, "dpiPool_create() with invalid credentials fails"); dpiTestSuite_addCase(dpiTest_1405, "dpiPool_create() with Min Sessions"); dpiTestSuite_addCase(dpiTest_1406, "dpiPool_create() with Max Sessions"); dpiTestSuite_addCase(dpiTest_1407, "dpiPool_create() with Session Increment"); dpiTestSuite_addCase(dpiTest_1408, "dpiPool_create() with get mode set to no wait"); dpiTestSuite_addCase(dpiTest_1409, "dpiPool_create() with get mode set to force get"); dpiTestSuite_addCase(dpiTest_1410, "dpiPool_create() with NULL context"); dpiTestSuite_addCase(dpiTest_1411, "dpiPool_create() and release twice"); dpiTestSuite_addCase(dpiTest_1412, "call all pool functions with closed pool"); dpiTestSuite_addCase(dpiTest_1413, "call all pool functions with NULL pool"); dpiTestSuite_addCase(dpiTest_1414, "proxy authentication with pool"); dpiTestSuite_addCase(dpiTest_1415, "proxy authentication cannot be used with homogeneous pool"); dpiTestSuite_addCase(dpiTest_1416, "dpiPool_create() with NULL pool"); dpiTestSuite_addCase(dpiTest_1417, "dpiPool_create() with no credentials"); dpiTestSuite_addCase(dpiTest_1418, "dpiPool_create() with invalid connect string"); dpiTestSuite_addCase(dpiTest_1419, "dpiPool_acquireConnection() from hetero pool with credentials"); dpiTestSuite_addCase(dpiTest_1420, "dpiPool_acquireConnection() from hetero pool without credentials"); dpiTestSuite_addCase(dpiTest_1421, "dpiPool_acquireConnection() from hetero pool invalid credentials"); dpiTestSuite_addCase(dpiTest_1422, "dpiPool_getPingInterval() and dpiPool_setPingInterval()"); dpiTestSuite_addCase(dpiTest_1423, "dpiPool_reconfigure() adjusting max sessions"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1500_pool_properties.c000066400000000000000000000345451510466437300205610ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1500_pool_properties.c // Test suite for testing pool properties. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_1500() // Call dpiPool_getBusyCount() in various scenarios to verify that the busy // count is being returned correctly (no error). //----------------------------------------------------------------------------- int dpiTest_1500(dpiTestCase *testCase, dpiTestParams *params) { uint32_t count, i; dpiConn *conn[3]; dpiPool *pool; // create pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // busy count should start at 0 if (dpiPool_getBusyCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, 0) < 0) return DPI_FAILURE; // busy count should increment as connections are acquired from the pool for (i = 0; i < 3; i++) { if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getBusyCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, i + 1) < 0) return DPI_FAILURE; } // busy count should decrement as connections are released back to the pool for (i = 0; i < 3; i++) { if (dpiConn_release(conn[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getBusyCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, 2 - i) < 0) return DPI_FAILURE; } // cleanup if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1501() // Call dpiPool_getOpenCount() in various scenarios to verify that the open // count is being returned correctly (no error). //----------------------------------------------------------------------------- int dpiTest_1501(dpiTestCase *testCase, dpiTestParams *params) { uint32_t count; dpiPool *pool; // create pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // verify open count matches the minimum number of sessions if (dpiPool_getOpenCount(pool, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, DPI_TEST_POOL_MIN_SESSIONS) < 0) return DPI_FAILURE; // cleanup if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1502() // Call dpiPool_create() specifying a value for the encoding and nencoding // attributes of the dpiCommonCreateParams structure and then call // dpiPool_getEncodingInfo() to verify that the values match (no error). //----------------------------------------------------------------------------- int dpiTest_1502(dpiTestCase *testCase, dpiTestParams *params) { const char *charSet = "ISO-8859-13"; dpiCommonCreateParams commonParams; dpiEncodingInfo info; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.encoding = charSet; commonParams.nencoding = charSet; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getEncodingInfo(pool, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.encoding, strlen(info.encoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, info.nencoding, strlen(info.nencoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1503() // Call dpiPool_setGetMode(); call dpiPool_getGetMode() and verify that the // value returned matches (no error). //----------------------------------------------------------------------------- int dpiTest_1503(dpiTestCase *testCase, dpiTestParams *params) { dpiPoolCreateParams createParams; dpiPoolGetMode value; dpiContext *context; dpiPool *pool; dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &createParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &createParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_setGetMode(pool, DPI_MODE_POOL_GET_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getGetMode(pool, &value) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, value, DPI_MODE_POOL_GET_WAIT) < 0) return DPI_FAILURE; if (dpiPool_setGetMode(pool, DPI_MODE_POOL_GET_NOWAIT) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getGetMode(pool, &value) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, value, DPI_MODE_POOL_GET_NOWAIT) < 0) return DPI_FAILURE; if (dpiPool_setGetMode(pool, DPI_MODE_POOL_GET_FORCEGET) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getGetMode(pool, &value) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, value, DPI_MODE_POOL_GET_FORCEGET) < 0) return DPI_FAILURE; dpiPool_release(pool); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1504() // Call dpiPool_setMaxLifetimeSession(); call dpiPool_getMaxLifetimeSession() // and verify that the value returned matches (no error). //----------------------------------------------------------------------------- int dpiTest_1504(dpiTestCase *testCase, dpiTestParams *params) { uint32_t value, valueToSet = 10; dpiPool *pool; // only supported in 12.1 and higher if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // test getting and setting the attribute if (dpiPool_setMaxLifetimeSession(pool, valueToSet) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getMaxLifetimeSession(pool, &value) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, value, valueToSet) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1505() // Call dpiPool_setTimeout(); call dpiPool_getTimeout() and verify that the // value returned matches (no error). //----------------------------------------------------------------------------- int dpiTest_1505(dpiTestCase *testCase, dpiTestParams *params) { uint32_t value, valueToSet = 12; dpiPool *pool; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // test getting and setting the attribute if (dpiPool_setTimeout(pool, valueToSet) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getTimeout(pool, &value) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, value, valueToSet) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1506() // Call dpiPool_create() specifying a value for the encoding and null for // nencoding of the dpiCommonCreateParams structure and then call // dpiPool_getEncodingInfo() to verify that the values are as expected. //----------------------------------------------------------------------------- int dpiTest_1506(dpiTestCase *testCase, dpiTestParams *params) { const char *charSet = "ISO-8859-13"; dpiCommonCreateParams commonParams; dpiEncodingInfo info, defaultInfo; dpiConn *defaultConn; dpiContext *context; dpiPool *pool; // get default encodings dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &defaultConn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(defaultConn, &defaultInfo) < 0) return dpiTestCase_setFailedFromError(testCase); // create pool with just the encoding specified if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.encoding = charSet; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getEncodingInfo(pool, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.encoding, strlen(info.encoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, info.nencoding, strlen(info.nencoding), defaultInfo.nencoding, strlen(defaultInfo.nencoding)) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); // create pool with just the nencoding specified if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.nencoding = charSet; if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_getEncodingInfo(pool, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.encoding, strlen(info.encoding), defaultInfo.encoding, strlen(defaultInfo.encoding)) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, info.nencoding, strlen(info.nencoding), charSet, strlen(charSet)) < 0) return DPI_FAILURE; if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiConn_release(defaultConn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1500); dpiTestSuite_addCase(dpiTest_1500, "dpiPool_getBusyCount() with various scenarios"); dpiTestSuite_addCase(dpiTest_1501, "dpiPool_getOpenCount() with various scenarios"); dpiTestSuite_addCase(dpiTest_1502, "dpiPool_getEncodingInfo() to verify that the values match"); dpiTestSuite_addCase(dpiTest_1503, "check get / set mode for getting connections from pool"); dpiTestSuite_addCase(dpiTest_1504, "check get / set maximum lifetime session of pool"); dpiTestSuite_addCase(dpiTest_1505, "check get / set pool timeout"); dpiTestSuite_addCase(dpiTest_1506, "specifying a value for nencoding and null for encoding"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1600_queries.c000066400000000000000000000640541510466437300170100ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1600_queries.c // Test suite for testing queries. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__execStatement() [INTERNAL] // Prepare and execute statements and, if necessary, check number of rows. //----------------------------------------------------------------------------- int dpiTest__execStatement(dpiTestCase *testCase, dpiConn *conn, const char *sql, int cols) { uint32_t numQueryColumns; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_release(stmt); if (cols >= 0) { if (dpiTestCase_expectUintEqual(testCase, numQueryColumns, cols) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__insertIntoTestLongs() [INTERNAL] // Inserts rows into table. //----------------------------------------------------------------------------- int dpiTest__insertIntoTestLongs(dpiTestCase *testCase, dpiConn *conn) { uint32_t longValueLength, numQueryColumns, arraySize =3, numOfRows = 2; const char *insertSql = "insert into TestLongs values (:1, :2)"; const char *dropSql = "delete from TestLongs"; uint32_t iter, sizeIncrement = 50000; dpiData *intColValue, *longColValue; dpiVar *intColVar, *longColVar; char *longValue; dpiStmt *stmt; if (dpiTest__execStatement(testCase, conn, dropSql, -1) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, arraySize, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, arraySize, 0, 0, 0, NULL, &longColVar, &longColValue) < 0) return dpiTestCase_setFailedFromError(testCase); // insert the requested number of rows if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (iter = 1; iter <= numOfRows; iter++) { if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, longColVar) < 0) return dpiTestCase_setFailedFromError(testCase); longValueLength = iter * sizeIncrement; longValue = malloc(longValueLength); if (!longValue) return dpiTestCase_setFailed(testCase, "Out of memory!"); memset(longValue, 'A', longValueLength); intColValue->isNull = 0; intColValue->value.asInt64 = iter; if (dpiVar_setFromBytes(longColVar, 0, longValue, longValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); free(longValue); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_release(stmt); dpiVar_release(intColVar); dpiVar_release(longColVar); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1600() // Prepare any statement; call dpiStmt_getFetchArraySize() and verify the // value returned is the default value of 100; call dpiStmt_setFetchArraySize() // with any value except zero and then call dpiStmt_getFetchArraySize() to // verify the value returned matches the value that was set; call // dpiStmt_setFetchArraySize() with the value 0 and then call // dpiStmt_getFetchArraySize() and verify the value returned is the default // value of 100 (no error). //----------------------------------------------------------------------------- int dpiTest_1600(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs order by IntCol"; uint32_t arraySize, setArraySize = 3; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getFetchArraySize(stmt, &arraySize)< 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, arraySize, 100) < 0) return DPI_FAILURE; if (dpiStmt_setFetchArraySize(stmt, setArraySize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getFetchArraySize(stmt, &arraySize)< 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, arraySize, setArraySize) < 0) return DPI_FAILURE; setArraySize = 0; if (dpiStmt_setFetchArraySize(stmt, setArraySize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getFetchArraySize(stmt, &arraySize)< 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, arraySize, 100) < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1601() // Prepare and execute any query; create and define variables needed to // support the query; call dpiStmt_setFetchArraySize() with a value that is // larger than the array size used to create at least one of the variables // (error DPI-1015). //----------------------------------------------------------------------------- int dpiTest_1601(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs order by IntCol"; uint32_t arraySize = 3, setArraySize = 3333; uint32_t numQueryColumns; dpiData *intColValue; dpiVar *intColVar; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, arraySize, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_setFetchArraySize(stmt, setArraySize); if (dpiTestCase_expectError(testCase, "DPI-1015:") < 0) return DPI_FAILURE; dpiVar_release(intColVar); dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1602() // Prepare and execute any query; call dpiStmt_setFetchArraySize() with any // value; create and define a variable with an array size smaller than the // value used to call dpiStmt_setFetchArraySize(); call dpiStmt_fetch() // (error DPI-1018). //----------------------------------------------------------------------------- int dpiTest_1602(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs order by IntCol"; uint32_t numQueryColumns, bufferRowIndex; uint32_t arraySize = 3, setArraySize = 5; dpiData *intColValue; dpiVar *intColVar; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, arraySize, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, setArraySize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_fetch(stmt, &found, &bufferRowIndex); if (dpiTestCase_expectError(testCase, "DPI-1018:") < 0) return DPI_FAILURE; dpiVar_release(intColVar); dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1603() // Prepare and execute any query but do not create any variables or perform // any defines; call dpiStmt_fetch() followed by dpiStmt_getQueryValue() and // verify that the values returned match the expected values (no error). //----------------------------------------------------------------------------- int dpiTest_1603(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; uint32_t numQueryColumns, bufferRowIndex; dpiNativeTypeNum nativeTypeNum; dpiConn *conn; dpiStmt *stmt; dpiData *data; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__insertIntoTestLongs(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, nativeTypeNum, DPI_NATIVE_TYPE_INT64) < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1604() // Prepare and execute any query; call dpiStmt_fetch(), then call // dpiStmt_getQueryValue() with position 0 as well as a position that exceeds // the number of columns being fetched (error DPI-1028). //----------------------------------------------------------------------------- int dpiTest_1604(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; uint32_t numQueryColumns, bufferRowIndex; dpiNativeTypeNum nativeTypeNum; dpiData *data; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getQueryValue(stmt, 0, &nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, "DPI-1028:") < 0) return DPI_FAILURE; dpiStmt_getQueryValue(stmt, 3, &nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, "DPI-1028:") < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1605() // Prepare any query; call dpiStmt_getQueryValue() with any position // (error DPI-1007). //----------------------------------------------------------------------------- int dpiTest_1605(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; dpiNativeTypeNum nativeTypeNum; dpiData *data; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getQueryValue(stmt, 0, &nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, "DPI-1007:") < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1606() // Prepare and execute any query; call dpiStmt_fetch() until no rows are // found; call dpiStmt_getQueryValue() with any valid position // (error DPI-1029). //----------------------------------------------------------------------------- int dpiTest_1606(dpiTestCase *testCase, dpiTestParams *params) { const char *querySql = "select * from TestLongs"; const char *deleteSql = "delete from TestLongs"; uint32_t numQueryColumns, bufferRowIndex; dpiNativeTypeNum nativeTypeNum; dpiData *data; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, deleteSql, -1) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, querySql, strlen(querySql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, "DPI-1029:") < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1607() // Prepare and execute any query; call dpiStmt_getQueryInfo() and verify // that the type information returned matches that expected (no error). //----------------------------------------------------------------------------- int dpiTest_1607(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; uint32_t numQueryColumns, bufferRowIndex; dpiQueryInfo info; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryInfo(stmt, 1, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.defaultNativeTypeNum, DPI_NATIVE_TYPE_INT64) < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1608() // Prepare and execute a "select *" type query and fetch from it, then close // the statement; execute an alter statement that removes a column from the // table or view being queried; prepare, execute and fetch from the first query // again and confirm the number of columns has changed and no error has been // raised (no error). //----------------------------------------------------------------------------- int dpiTest_1608(dpiTestCase *testCase, dpiTestParams *params) { const char *querySql = "select * from TestLongsAlter"; const char *alterDropSql = "alter table TestLongsAlter drop column IntCol"; const char *dropSql = "drop table TestLongsAlter"; const char *createSql = "create table TestLongsAlter (IntCol number(9), LongCol long)"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, dropSql, -1) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, createSql, -1) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, querySql, 2) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, alterDropSql, -1) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, querySql, 1) < 0) return DPI_FAILURE; if (dpiTest__execStatement(testCase, conn, querySql, -1) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1609() // Prepare and execute any query; call dpiStmt_fetch() multiple times and // confirm that after each call a call to dpiStmt_getRowCount() results in a // row count that is one larger than the previous iteration (no error). //----------------------------------------------------------------------------- int dpiTest_1609(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numQueryColumns, bufferRowIndex, iter, numOfRows = 2; const char *sql = "select * from TestLongs"; uint64_t rowCount; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); for (iter = 1; iter <= numOfRows; iter++) { if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, rowCount, iter) < 0) return DPI_FAILURE; if (!found) return DPI_FAILURE; } dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1610() // Prepare and execute any query; call dpiStmt_fetchRows() and confirm that // the value returned by dpiStmt_getRowCount() increases by the number of rows // that were returned (no error). //----------------------------------------------------------------------------- int dpiTest_1610(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numQueryColumns, bufferRowIndex, numRowsFetched, maxRows = 2; const char *sql = "select * from TestLongs"; uint64_t rowCount; dpiConn *conn; dpiStmt *stmt; int moreRows; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__insertIntoTestLongs(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetchRows(stmt, maxRows, &bufferRowIndex, &numRowsFetched, &moreRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, rowCount, maxRows) < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1611() // Prepare any query but do not execute it; call dpiStmt_fetch(), // dpiStmt_getQueryInfo() and dpiStmt_define() and confirm each receives // an error (error ORA-24338). //----------------------------------------------------------------------------- int dpiTest_1611(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "ORA-24338:"; const char *sql = "select * from TestLongs"; uint32_t bufferRowIndex; dpiQueryInfo info; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_fetch(stmt, &found, &bufferRowIndex); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getQueryInfo(stmt, 1, &info); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_define(stmt, 1, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1612() // Create a string variable with a size that is smaller than at least some // of the data that is subsequently fetched (error DPI-1037) //----------------------------------------------------------------------------- int dpiTest_1612(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestTempTable values(1,'TestString')"; const char *selectSql = "select StringCol from TestTempTable"; const char *truncateSql = "truncate table TestTempTable"; uint32_t bufferRowIndex; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); // insert a row with a string of known size into the table if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); // perform fetch into string of smaller size if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 2, 1, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_fetch(stmt, &found, &bufferRowIndex); if (dpiTestCase_expectError(testCase, "DPI-1037:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1600); dpiTestSuite_addCase(dpiTest_1600, "check get / set array size with various values"); dpiTestSuite_addCase(dpiTest_1601, "dpiStmt_setFetchArraySize() with value too large"); dpiTestSuite_addCase(dpiTest_1602, "dpiStmt_setFetchArraySize() with value too small"); dpiTestSuite_addCase(dpiTest_1603, "dpiStmt_getQueryValue() without define"); dpiTestSuite_addCase(dpiTest_1604, "dpiStmt_getQueryValue() with invalid position values"); dpiTestSuite_addCase(dpiTest_1605, "dpiStmt_getQueryValue() called when no query has been executed"); dpiTestSuite_addCase(dpiTest_1606, "dpiStmt_getQueryValue() called after all rows fetched"); dpiTestSuite_addCase(dpiTest_1607, "dpiStmt_getQueryInfo() information is correct"); dpiTestSuite_addCase(dpiTest_1608, "query all columns from table before and after column dropped"); dpiTestSuite_addCase(dpiTest_1609, "dpiStmt_fetch() increments rowcount"); dpiTestSuite_addCase(dpiTest_1610, "dpiStmt_fetchRows() increments rowcount"); dpiTestSuite_addCase(dpiTest_1611, "dpiStmt_fetchRows() increments rowcount"); dpiTestSuite_addCase(dpiTest_1612, "fetch data to a string variable which is smaller and verify"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1700_transactions.c000066400000000000000000000365551510466437300200510ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1700_transactions.c // Test suite for testing Transactions. //----------------------------------------------------------------------------- #include "TestLib.h" #define FORMAT_ID 100 #define TRANSACTION_ID "txn-odpic" #define BRANCH_QUALIFIER "bqual-odpic" //----------------------------------------------------------------------------- // dpiTest__insertRowsInTable() [INTERNAL] // Inserts rows into the test table. //----------------------------------------------------------------------------- int dpiTest__insertRowsInTable(dpiTestCase *testCase, dpiConn *conn) { const char *sql = "insert into TestTempTable values (:1, :2)"; dpiData intColValue, stringColValue; char *strValue = "String 1"; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&intColValue, 1); dpiData_setBytes(&stringColValue, strValue, strlen(strValue)); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &stringColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__populateXid() [INTERNAL] // Populate the XID structure. //----------------------------------------------------------------------------- void dpiTest__populateXid(dpiXid *xid) { xid->formatId = FORMAT_ID; xid->globalTransactionId = TRANSACTION_ID; xid->globalTransactionIdLength = strlen(TRANSACTION_ID); xid->branchQualifier = BRANCH_QUALIFIER; xid->branchQualifierLength = strlen(BRANCH_QUALIFIER); } //----------------------------------------------------------------------------- // dpiTest__truncateTable() [INTERNAL] // Truncate the rows in the test table. //----------------------------------------------------------------------------- int dpiTest__truncateTable(dpiTestCase *testCase, dpiConn *conn) { const char *sql = "truncate table TestTempTable"; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyData() [INTERNAL] // Verify that the table contains the expected number of rows. A new // connection is established to ensure the transaction was truly committed or // rolled back. //----------------------------------------------------------------------------- int dpiTest__verifyData(dpiTestCase *testCase, int64_t expectedNumRows) { const char *sql = "select count(*) from TestTempTable"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiData *data; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 0, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(data), expectedNumRows) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1700() // Call dpiConn_tpcBegin() with parameters globalTransactionIdLength and // branchQualifierLength <= 64 (no error). //----------------------------------------------------------------------------- int dpiTest_1700(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiXid xid; dpiTest__populateXid(&xid); if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1701() // Call dpiConn_tpcBegin() with parameter globalTransactionIdLength > 64 // (error DPI-1035). //----------------------------------------------------------------------------- int dpiTest_1701(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiXid xid; dpiTest__populateXid(&xid); xid.globalTransactionIdLength = 65; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0); return dpiTestCase_expectError(testCase, "DPI-1035:"); } //----------------------------------------------------------------------------- // dpiTest_1702() // Call dpiConn_tpcBegin() with parameter branchQualifierLength > 64 // (error DPI-1036). //----------------------------------------------------------------------------- int dpiTest_1702(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiXid xid; dpiTest__populateXid(&xid); xid.branchQualifierLength = 65; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0); return dpiTestCase_expectError(testCase, "DPI-1036:"); } //----------------------------------------------------------------------------- // dpiTest_1703() // Call dpiConn_tpcBegin(), then call dpiConn_tpcPrepare() and verify that // commitNeeded has the value 0 (no error). //----------------------------------------------------------------------------- int dpiTest_1703(dpiTestCase *testCase, dpiTestParams *params) { int commitNeeded; dpiConn *conn; dpiXid xid; dpiTest__populateXid(&xid); if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_tpcPrepare(conn, NULL, &commitNeeded) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, commitNeeded, 0) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1704() // Call dpiConn_tpcBegin(), then call dpiConn_tpcPrepare(), then call // dpiConn_tpcCommit() (error ORA-24756). //----------------------------------------------------------------------------- int dpiTest_1704(dpiTestCase *testCase, dpiTestParams *params) { int commitNeeded; dpiConn *conn; dpiXid xid; dpiTest__populateXid(&xid); if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_tpcPrepare(conn, NULL, &commitNeeded) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_tpcCommit(conn, NULL, 1); return dpiTestCase_expectError(testCase, "ORA-24756:"); } //----------------------------------------------------------------------------- // dpiTest_1705() // Call dpiConn_tpcBegin(), then execute some DML, then call // dpiConn_tpcPrepare() and verify that commitNeeded has the value 1; // call dpiConn_tpcCommit() and create a new connection using the common // connection creation method and verify that the changes have been committed // to the database (no error). //----------------------------------------------------------------------------- int dpiTest_1705(dpiTestCase *testCase, dpiTestParams *params) { int commitNeeded; dpiConn *conn; dpiXid xid; // setup table if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateTable(testCase, conn) < 0) return DPI_FAILURE; // perform transaction dpiTest__populateXid(&xid); if (dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__insertRowsInTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_tpcPrepare(conn, NULL, &commitNeeded) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, commitNeeded, 1) < 0) return DPI_FAILURE; if (dpiConn_tpcCommit(conn, NULL, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // verify commit succeeded if (dpiTest__verifyData(testCase, 1) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1706() // Call dpiConn_tpcBegin(), then execute some DML, then call // dpiConn_tpcPrepare(); call dpiConn_tpcRollback() and create a new // connection using the common connection creation method and verify that the // changes have been rolled back (no error). //----------------------------------------------------------------------------- int dpiTest_1706(dpiTestCase *testCase, dpiTestParams *params) { int commitNeeded; dpiConn *conn; dpiXid xid; // setup table if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateTable(testCase, conn) < 0) return DPI_FAILURE; // perform transaction dpiTest__populateXid(&xid); if (dpiConn_tpcBegin(conn, &xid, DPI_TPC_BEGIN_NEW, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__insertRowsInTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_tpcPrepare(conn, NULL, &commitNeeded) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, commitNeeded, 1) < 0) return DPI_FAILURE; if (dpiConn_tpcRollback(conn, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // verify rollback succeeded if (dpiTest__verifyData(testCase, 0) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1707() // Call TPC functions with NULL connection (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1707(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiConn_tpcBegin(NULL, NULL, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcCommit(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcEnd(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcForget(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcPrepare(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcRollback(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1708() // Call TPC functions that expect a valid XID with a null value (error // DPI-1046). //----------------------------------------------------------------------------- int dpiTest_1708(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1046:"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_tpcBegin(conn, NULL, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcForget(conn, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_tpcPrepare(conn, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1700); dpiTestSuite_addCase(dpiTest_1700, "dpiConn_tpcBegin() with valid parameters"); dpiTestSuite_addCase(dpiTest_1701, "dpiConn_tpcBegin() with transactionIdLength > 64"); dpiTestSuite_addCase(dpiTest_1702, "dpiConn_tpcBegin() with branchQualifierLength > 64"); dpiTestSuite_addCase(dpiTest_1703, "dpiConn_tpcPrepare() with no transaction"); dpiTestSuite_addCase(dpiTest_1704, "dpiConn_tpcCommit() of transaction with no DML"); dpiTestSuite_addCase(dpiTest_1705, "dpiConn_tpcCommit() of transaction with DML"); dpiTestSuite_addCase(dpiTest_1706, "dpiConn_tpcRollback() of transaction with DML"); dpiTestSuite_addCase(dpiTest_1707, "verify tpc functions with NULL connection"); dpiTestSuite_addCase(dpiTest_1708, "verify tpc functions with NULL XID"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_1800_misc.c000066400000000000000000000403261510466437300162640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1800_misc.c // Test suite of miscellenous test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__verifySqlId() [INTERNAL] // This function retrieves the SQL_ID of the provided SQL query from v$sql // and compares it with the SQL_ID fetched from dpiStmt_getInfo(). //----------------------------------------------------------------------------- int dpiTest__verifySqlId(dpiTestCase *testCase, dpiConn *conn, dpiStmt *stmt, const char *sql) { const char *querySql = "select dbms_sql_translator.sql_id(:1) from dual"; dpiNativeTypeNum nativeTypeNum; dpiData *queryData, bindData; uint32_t bufferRowIndex; dpiStmt *queryStmt; dpiStmtInfo info; dpiBytes *bytes; int found; // acquire SQL_ID from the statement that was executed if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire SQL_ID from v$sql if (dpiConn_prepareStmt(conn, 0, querySql, strlen(querySql), NULL, 0, &queryStmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&bindData, (char*) sql, strlen(sql)); if (dpiStmt_bindValueByPos(queryStmt, 1, DPI_NATIVE_TYPE_BYTES, &bindData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(queryStmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(queryStmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(queryStmt, 1, &nativeTypeNum, &queryData) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(queryData); if (dpiTestCase_expectStringEqual(testCase, info.sqlId, info.sqlIdLength, bytes->ptr, bytes->length) < 0) return DPI_FAILURE; if (dpiStmt_release(queryStmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1800() // Call dpiConn_changePassword() and create a new connection using the new // password to verify that the password was indeed changed (no error). //----------------------------------------------------------------------------- int dpiTest_1800(dpiTestCase *testCase, dpiTestParams *params) { const char *newpwd = "newpwd"; dpiContext *context; dpiConn *conn; // get first connection and change password if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_changePassword(conn, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, newpwd, strlen(newpwd)) < 0) return dpiTestCase_setFailedFromError(testCase); // get second connection and change password back dpiTestSuite_getContext(&context); if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, newpwd, strlen(newpwd), params->connectString, params->connectStringLength, NULL, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_changePassword(conn, params->mainUserName, params->mainUserNameLength, newpwd, strlen(newpwd), params->mainPassword, params->mainPasswordLength) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1801() [INTERNAL] // call dpiConn_ping() (no error) //----------------------------------------------------------------------------- int dpiTest_1801(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_ping(conn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1802() [INTERNAL] // Prepare and execute a query which fetches an XMLType object and verify // that it is returned as a string (no error). //----------------------------------------------------------------------------- int dpiTest_1802(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select XMLElement(\"String\", StringCol) from " "TestStrings where IntCol = 1"; const char *expectedValue = "String 1"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiData *strColValue; dpiConn *conn; dpiStmt *stmt; int found; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare select statement and execute it if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &strColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, strColValue->value.asBytes.ptr, strColValue->value.asBytes.length, expectedValue, strlen(expectedValue)) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1803() [INTERNAL] // Insert data into XMLCol. Fetch the data from XMLCol and verify(no error). //----------------------------------------------------------------------------- int dpiTest_1803(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select XMLCol from TestXML where IntCol = 1"; const char *insertSql = "insert into TestXML (IntCol, XMLCol) values (1, :1)"; const char *truncateSql = "truncate table TestXML"; dpiNativeTypeNum nativeTypeNum; dpiData xmlData, *fetchedData; uint32_t bufferRowIndex, i; char xmlVal[1038], *ptr; dpiConn *conn; dpiStmt *stmt; int found; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // generate random XML string strcpy(xmlVal, ""); ptr = xmlVal + strlen(xmlVal); for (i = 0; i < 1024; i++) *ptr++ = 'A' + (rand() % 26); strcpy(ptr, ""); // perform insert if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&xmlData, xmlVal, strlen(xmlVal)); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_BYTES, &xmlData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch the data and compare if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &fetchedData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, fetchedData->value.asBytes.ptr, fetchedData->value.asBytes.length - 1, xmlVal, strlen(xmlVal)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1804() // Verify dpiData_setNull() and dpiData_getIsNull() are working properly // (no error). //----------------------------------------------------------------------------- int dpiTest_1804(dpiTestCase *testCase, dpiTestParams *params) { dpiData data; dpiData_setNull(&data); if (dpiTestCase_expectUintEqual(testCase, dpiData_getIsNull(&data), 1) < 0) return DPI_FAILURE; dpiData_setInt64(&data, 5); if (dpiTestCase_expectUintEqual(testCase, dpiData_getIsNull(&data), 0) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1805() // Verify SQL_ID is NULL after dpiConn_prepareStmt() and that the value // returned after dpiStmt_execute() matches the value found in v$sql. This // requires 12.2 or higher. //----------------------------------------------------------------------------- int dpiTest_1805(dpiTestCase *testCase, dpiTestParams *params) { char *sql = "select 100 from dual"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 2) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (info.sqlId && info.sqlIdLength > 0) return dpiTestCase_setFailed(testCase, "SQL_ID is not NULL"); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifySqlId(testCase, conn, stmt, sql) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1806() // Verify SQL_ID is NULL when dpiStmt_execute() fails. This requires 12.2 or // higher. //----------------------------------------------------------------------------- int dpiTest_1806(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestDummy"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 2) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (info.sqlId && info.sqlIdLength > 0) return dpiTestCase_setFailed(testCase, "SQL_ID is not NULL"); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1807() // Verify SQL_ID value when using bind variables. This requires 12.2 or // higher. //----------------------------------------------------------------------------- int dpiTest_1807(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable values (:1, 'test1')"; const char *truncateSql = "truncate table TestTempTable"; uint32_t iter, numOfRows = 3, numQueryColumns; dpiData *intColValue; dpiVar *intColVar; dpiConn *conn; dpiStmt *stmt; // truncate table if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 2) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // perform insert with binds and verify SQL_ID if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 4, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (iter = 1; iter <= numOfRows; iter++) { if (dpiStmt_bindByPos(stmt, 1, intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(intColValue, iter); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifySqlId(testCase, conn, stmt, sql) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1800); dpiTestSuite_addCase(dpiTest_1800, "change password and verify (no error)"); dpiTestSuite_addCase(dpiTest_1801, "dpiConn_ping() (no error)"); dpiTestSuite_addCase(dpiTest_1802, "fetch an XMLType object as a string"); dpiTestSuite_addCase(dpiTest_1803, "insert data into table containing XMLType and verify fetch"); dpiTestSuite_addCase(dpiTest_1804, "verify dpiData_setNull() & dpiData_getIsNull()"); dpiTestSuite_addCase(dpiTest_1805, "verify SQL_ID with simple query"); dpiTestSuite_addCase(dpiTest_1806, "verify SQL_ID is NULL when exec stmt fails"); dpiTestSuite_addCase(dpiTest_1807, "verify SQL_ID values matches with binds"); dpiTestSuite_run(); return 0; } odpi-5.6.4/test/test_1900_variables.c000066400000000000000000001101171510466437300172760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_1900_variables.c // Test suite for testing variable creation and binding. //----------------------------------------------------------------------------- #include "TestLib.h" #define MAX_ARRAY_SIZE 3 //----------------------------------------------------------------------------- // dpiTest_1900() // Create a variable specifying the maxArraySize parameter as 0 // (error DPI-1031). //----------------------------------------------------------------------------- int dpiTest_1900(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 0, 0, 0, 0, NULL, &var, &data); return dpiTestCase_expectError(testCase, "DPI-1031:"); } //----------------------------------------------------------------------------- // dpiTest_1901() // Create a variable specifying a value for the parameter oracleTypeNum // which is not part of the enumeration dpiOracleTypeNum (error DPI-1021). //----------------------------------------------------------------------------- int dpiTest_1901(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newVar(conn, 1000, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data); return dpiTestCase_expectError(testCase, "DPI-1021:"); } //----------------------------------------------------------------------------- // dpiTest_1902() // Create a variable specifying values for the parameters oracleTypeNum and // nativeTypeNum which are not compatible with each other (error DPI-1014). //----------------------------------------------------------------------------- int dpiTest_1902(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data); return dpiTestCase_expectError(testCase, "DPI-1014:"); } //----------------------------------------------------------------------------- // dpiTest_1903() // Create a variable specifying isArray as 1 and valid values for the // parameters oracleTypeNum and nativeTypeNum, but that are not supported in // arrays (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1903(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newVar(conn, DPI_ORACLE_TYPE_BOOLEAN, DPI_NATIVE_TYPE_BOOLEAN, MAX_ARRAY_SIZE, 0, 0, 1, NULL, &var, &data); return dpiTestCase_expectError(testCase, "DPI-1013:"); } //----------------------------------------------------------------------------- // dpiTest_1904() // Create a variable specifying values for maxArraySize and sizeInBytes that // when multiplied together would result in an integer that exceeds INT_MAX // (error DPI-1015). //----------------------------------------------------------------------------- int dpiTest_1904(dpiTestCase *testCase, dpiTestParams *params) { uint32_t maxArrSize = 4294967295, size = 2; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, maxArrSize, size, 0, 0, NULL, &var, &data); return dpiTestCase_expectError(testCase, "DPI-1015:"); } //----------------------------------------------------------------------------- // dpiTest_1905() // Create a variable that does not use native type DPI_NATIVE_TYPE_BYTES and // then call dpiVar_setFromBytes() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1905(dpiTestCase *testCase, dpiTestParams *params) { const char *strVal = "string1"; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromBytes(var, 0, strVal, strlen(strVal)); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1906() // Create a variable that does use native type DPI_NATIVE_TYPE_BYTES and then // call dpiVar_setFromBytes() with a valueLength that exceeds the size // specified when the variable was created (error DPI-1019). //----------------------------------------------------------------------------- int dpiTest_1906(dpiTestCase *testCase, dpiTestParams *params) { const char *strVal = "string_that_is_too_long"; dpiData *data; dpiVar *var; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, MAX_ARRAY_SIZE, 2, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromBytes(var, 0, strVal, strlen(strVal)); if (dpiTestCase_expectError(testCase, "DPI-1019:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1907() // Create a variable that uses native type DPI_NATIVE_TYPE_BYTES; call // dpiVar_setFromBytes() with position >= the value for maxArraySize used when // the variable was created (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1907(dpiTestCase *testCase, dpiTestParams *params) { const char *strVal = "string1"; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromBytes(var, 4, strVal, strlen(strVal)); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1908() // Create a variable that does not use native type DPI_NATIVE_TYPE_LOB and // then call dpiVar_setFromLob() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1908(dpiTestCase *testCase, dpiTestParams *params) { const char *lobStr = "dpiTest"; dpiConn *conn; dpiData *data; dpiVar *var; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_setFromBytes(lob, lobStr, strlen(lobStr)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromLob(var, 0, lob); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiLob_release(lob); dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1909() // Create a variable that uses native type DPI_NATIVE_TYPE_LOB; call // dpiVar_setFromLob() with position >= the value for maxArraySize used when // the variable was created (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1909(dpiTestCase *testCase, dpiTestParams *params) { const char *lobStr = "dpiTest"; dpiData *lobValue; dpiVar *lobVar; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_setFromBytes(lob, lobStr, strlen(lobStr)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_CLOB, DPI_NATIVE_TYPE_LOB, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &lobVar, &lobValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromLob(lobVar, 3, lob); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; dpiVar_release(lobVar); dpiLob_release(lob); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1910() // Create a variable that does not use native type DPI_NATIVE_TYPE_OBJECT and // then call dpiVar_setFromObject() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1910(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromObject(var, 0, obj); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(var); dpiObject_release(obj); dpiObjectType_release(objType); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1911() // Create a variable that uses native type DPI_NATIVE_TYPE_OBJECT; call // dpiVar_setFromObject() with position >= the value for maxArraySize used when // the variable was created (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1911(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_OBJECT"; uint32_t maxArrSize = 1; dpiObjectType *objType; dpiData *objectValue; dpiVar *objectVar; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, maxArrSize, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromObject(objectVar, 1, obj); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; dpiVar_release(objectVar); dpiObject_release(obj); dpiObjectType_release(objType); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1912() // Create a variable that does not use native type DPI_NATIVE_TYPE_ROWID and // then call dpiVar_setFromRowid() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1912(dpiTestCase *testCase, dpiTestParams *params) { dpiRowid *rowid = NULL; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromRowid(var, 0, rowid); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1913() // Create a variable that uses native type DPI_NATIVE_TYPE_ROWID; call // dpiVar_setFromRowid() with position >= the value for maxArraySize used when // the variable was created (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1913(dpiTestCase *testCase, dpiTestParams *params) { dpiRowid *rowid = NULL; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_ROWID, DPI_NATIVE_TYPE_ROWID, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromRowid(var, 3, rowid); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1914() // Create a variable that does not use native type DPI_NATIVE_TYPE_STMT and // then call dpiVar_setFromStmt() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1914(dpiTestCase *testCase, dpiTestParams *params) { dpiStmt *stmt = NULL; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromStmt(var, 0, stmt); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1915() // Create a variable that uses native type DPI_NATIVE_TYPE_STMT; call // dpiVar_setFromStmt() with position >= the value for maxArraySize used when // the variable was created (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1915(dpiTestCase *testCase, dpiTestParams *params) { dpiStmt *stmt = NULL; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_STMT, DPI_NATIVE_TYPE_STMT, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromStmt(var, 3, stmt); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1916() // Create a variable that uses native type DPI_NATIVE_TYPE_OBJECT but the // object type parameter is set to NULL (error DPI-1025). //----------------------------------------------------------------------------- int dpiTest_1916(dpiTestCase *testCase, dpiTestParams *params) { dpiData *objectValue; dpiVar *objectVar; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &objectVar, &objectValue); if (dpiTestCase_expectError(testCase, "DPI-1025:") < 0) return DPI_FAILURE; dpiVar_release(objectVar); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1917() // Prepare and execute a query; call dpiStmt_define() with position set to 0 // and with position set to a value that exceeds the number of columns that are // available in the query (error DPI-1028). //----------------------------------------------------------------------------- int dpiTest_1917(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; uint32_t numQueryColumns; dpiConn *conn; dpiStmt *stmt; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_define(stmt, 0, var); if (dpiTestCase_expectError(testCase, "DPI-1028:") < 0) return DPI_FAILURE; dpiStmt_define(stmt, 3, var); if (dpiTestCase_expectError(testCase, "DPI-1028:") < 0) return DPI_FAILURE; dpiVar_release(var); dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1918() // Prepare and execute a query; call dpistmt_define() with the variable set // to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1918(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; uint32_t numQueryColumns; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_define(stmt, 1, NULL); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1919() // Prepare and execute a statement with bind variables identified in the // statement text; create a variable and call dpiStmt_bindByPos() with the // position parameter set to 0 (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1919(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select :1 from dual"; uint32_t maxArrSize = 1; dpiData *varData; dpiConn *conn; dpiStmt *stmt; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, maxArrSize, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_bindByPos(stmt, 0, var); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(var); dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1920() // Create two variables with the same native type; call dpiVar_copyData() // with the position parameter set to a value that exceeds the maxArraySize of // at least one of the variables (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1920(dpiTestCase *testCase, dpiTestParams *params) { dpiData *data1, *data2; dpiVar *var1, *var2; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var1, &data1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var2, &data2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_copyData(var1, 3, var2, 0); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; dpiVar_release(var1); dpiVar_release(var2); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1921() // Create two variables with different native types; call dpiVar_copyData() // with either variable as the source (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1921(dpiTestCase *testCase, dpiTestParams *params) { dpiData *intColValue, *longColValue; dpiVar *intColVar, *longColVar; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &longColVar, &longColValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_copyData(longColVar, 0, intColVar, 0); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(intColVar); dpiVar_release(longColVar); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1922() // Create an array variable of any type; call dpiVar_setNumElementsInArray() // with a value for the numElements parameter that exceeds the maxArraySize // value that was used to create the variable (DPI-1018). //----------------------------------------------------------------------------- int dpiTest_1922(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numElements = 4; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setNumElementsInArray(var, numElements); if (dpiTestCase_expectError(testCase, "DPI-1018:") < 0) return DPI_FAILURE; dpiVar_release(var); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1923() // Prepare and execute a statement with bind variables identified in the // statement text; create a variable and call dpiStmt_bindByName() with the // nameLength parameter set to 0 (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1923(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select :test from dual"; dpiData *varData; dpiConn *conn; dpiStmt *stmt; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_bindByName(stmt, "test", 0, var); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; dpiVar_release(var); dpiStmt_release(stmt); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1924() // Verify dpiVar_setFromBytes() allows the value parameter to be NULL when // the valueLength parameter is zero. //----------------------------------------------------------------------------- int dpiTest_1924(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, MAX_ARRAY_SIZE, 100, 1, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(var, 0, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1925() // Verify dpiVar_setFromBytes() does not allow the value parameter to be NULL // when the valueLength is set to a non-zero value. //----------------------------------------------------------------------------- int dpiTest_1925(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, MAX_ARRAY_SIZE, 100, 1, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromBytes(var, 0, NULL, 1); if (dpiTestCase_expectError(testCase, "DPI-1053:") < 0) return DPI_FAILURE; if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1926() // Create a variable that does not use native type DPI_NATIVE_TYPE_JSON and // then call dpiVar_setFromJson() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_1926(dpiTestCase *testCase, dpiTestParams *params) { const char *strVal = "{\"key\":1026}"; dpiData *intData, *jsonData; dpiVar *intVar, *jsonVar; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &jsonVar, &jsonData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_setFromText(dpiData_getJson(jsonData), strVal, strlen(strVal), 0) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromJson(intVar, 0, dpiData_getJson(jsonData)); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; if (dpiVar_release(jsonVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1927() // Create a variable that uses native type DPI_NATIVE_TYPE_JSON; call // dpiVar_setFromJson() with position >= the value for maxArraySize used when // the variable was created (error DPI-1009). //----------------------------------------------------------------------------- int dpiTest_1927(dpiTestCase *testCase, dpiTestParams *params) { const char *strVal = "{\"key\":1027}"; dpiData *jsonData1, *jsonData2; dpiVar *jsonVar1, *jsonVar2; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &jsonVar1, &jsonData1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &jsonVar2, &jsonData2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_setFromText(dpiData_getJson(jsonData1), strVal, strlen(strVal), 0) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromJson(jsonVar2, 3, dpiData_getJson(jsonData1)); if (dpiTestCase_expectError(testCase, "DPI-1009:") < 0) return DPI_FAILURE; if (dpiVar_release(jsonVar1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(jsonVar2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1928() // Create a variable that uses native type DPI_NATIVE_TYPE_JSON; call // dpiVar_setFromJson() with valid arguments. //----------------------------------------------------------------------------- int dpiTest_1928(dpiTestCase *testCase, dpiTestParams *params) { const char *strVal = "{\"key\":1028}"; dpiData *jsonData1, *jsonData2; dpiVar *jsonVar1, *jsonVar2; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &jsonVar1, &jsonData1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, MAX_ARRAY_SIZE, 0, 0, 0, NULL, &jsonVar2, &jsonData2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_setFromText(dpiData_getJson(jsonData1), strVal, strlen(strVal), 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromJson(jsonVar2, 0, dpiData_getJson(jsonData1)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(jsonVar1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(jsonVar2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_1929() // Call each of the dpiJson public functions with the json parameter set to // NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_1929(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; dpiVar_setFromJson(NULL, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(1900); dpiTestSuite_addCase(dpiTest_1900, "dpiConn_newVar() with max array size as 0"); dpiTestSuite_addCase(dpiTest_1901, "dpiConn_newVar() with an invalid value for Oracle type"); dpiTestSuite_addCase(dpiTest_1902, "dpiConn_newVar() with incompatible values for Oracle and native " "types"); dpiTestSuite_addCase(dpiTest_1903, "dpiConn_newVar() with invalid array type for array"); dpiTestSuite_addCase(dpiTest_1904, "dpiConn_newVar() with max array size that is too large"); dpiTestSuite_addCase(dpiTest_1905, "dpiVar_setFromBytes() with unsupported variable"); dpiTestSuite_addCase(dpiTest_1906, "dpiVar_setFromBytes() with value too large"); dpiTestSuite_addCase(dpiTest_1907, "dpiVar_setFromBytes() with position too large"); dpiTestSuite_addCase(dpiTest_1908, "dpiVar_setFromLob() with unsupported type"); dpiTestSuite_addCase(dpiTest_1909, "dpiVar_setFromLob() with position too large"); dpiTestSuite_addCase(dpiTest_1910, "dpiVar_setFromObject() with unsupported type"); dpiTestSuite_addCase(dpiTest_1911, "dpiVar_setFromObject() with position too large"); dpiTestSuite_addCase(dpiTest_1912, "dpiVar_setFromRowid() with unsupported type"); dpiTestSuite_addCase(dpiTest_1913, "dpiVar_setFromRowid() with position too large"); dpiTestSuite_addCase(dpiTest_1914, "dpiVar_setFromStmt() with unsupported type"); dpiTestSuite_addCase(dpiTest_1915, "dpiVar_setFromStmt() with position too large"); dpiTestSuite_addCase(dpiTest_1916, "dpiConn_newVar() with NULL object type for object variable"); dpiTestSuite_addCase(dpiTest_1917, "dpiStmt_define() with invalid positions"); dpiTestSuite_addCase(dpiTest_1918, "dpiStmt_define() with NULL variable"); dpiTestSuite_addCase(dpiTest_1919, "dpiStmt_bindByPos() with position 0"); dpiTestSuite_addCase(dpiTest_1920, "dpiVar_copyData() with invalid position"); dpiTestSuite_addCase(dpiTest_1921, "dpiVar_copyData() with different variable types"); dpiTestSuite_addCase(dpiTest_1922, "dpiVar_setNumElementsInArray() with value too large"); dpiTestSuite_addCase(dpiTest_1923, "dpiStmt_bindByName() with name length parameter 0"); dpiTestSuite_addCase(dpiTest_1924, "dpiVar_setFromBytes() with value NULL and valueLength zero"); dpiTestSuite_addCase(dpiTest_1925, "dpiVar_setFromBytes() with value not NULL and valueLength " "non zero"); dpiTestSuite_addCase(dpiTest_1926, "dpiVar_setFromJson() with unsupported type"); dpiTestSuite_addCase(dpiTest_1927, "dpiVar_setFromJson() with position too large"); dpiTestSuite_addCase(dpiTest_1928, "dpiVar_setFromJson() with valid arguments"); dpiTestSuite_addCase(dpiTest_1929, "verify dpiVar_setFromJson() with NULL"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2000_statements.c000066400000000000000000002520211510466437300175060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2000_statements.c // Test suite for testing all the statement related cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__callFunctionsWithError() [INTERNAL] // Test all public functions with the specified statement and expect the // given error for each of them. //----------------------------------------------------------------------------- int dpiTest__callFunctionsWithError(dpiTestCase *testCase, dpiStmt *stmt, const char *expectedError) { dpiStmt_bindByName(stmt, NULL, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_bindByPos(stmt, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_bindValueByName(stmt, NULL, 0, DPI_NATIVE_TYPE_INT64, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_bindValueByPos(stmt, 0, DPI_NATIVE_TYPE_INT64, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_define(stmt, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_defineValue(stmt, 0, DPI_ORACLE_TYPE_NATIVE_INT, DPI_NATIVE_TYPE_INT64, 0, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_fetch(stmt, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_fetchRows(stmt, 1, NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getBatchErrorCount(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getBatchErrors(stmt, 1, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getBindCount(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getBindNames(stmt, NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getFetchArraySize(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getImplicitResult(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getInfo(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getNumQueryColumns(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getQueryInfo(stmt, 1, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getQueryValue(stmt, 1, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getRowCount(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getRowCounts(stmt, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_getSubscrQueryId(stmt, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_scroll(stmt, DPI_MODE_FETCH_FIRST, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_setFetchArraySize(stmt, 1); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__getRoundTripCnt() [INTERNAL] // Get the total number of round trips in a session. //----------------------------------------------------------------------------- int dpiTest__getRoundTripCnt(dpiTestCase *testCase, dpiTestParams *params, dpiConn *conn, uint64_t *roundTripCnt) { const char *sql = "select ss.value from v$sesstat ss, v$statname sn" " where ss.sid = :sid and ss.statistic# = sn.statistic#" " and sn.name like '%roundtrip%client%'"; const char *sidSql = "select sys_context('userenv', 'sid') from dual"; dpiData *sidData, *cntData; uint32_t bufferRowIndex; dpiVar *sidVar, *cntVar; dpiContext *context; dpiConn *sysConn; dpiStmt *stmt; uint64_t sid; int found; // Get the session id. if (dpiConn_prepareStmt(conn, 0, sidSql, strlen(sidSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &sidVar, &sidData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, sidVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); sid = dpiData_getInt64(sidData); if (dpiVar_release(sidVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // Get the round trip count. dpiTestSuite_getContext(&context); if (dpiConn_create(context, params->adminUserName, params->adminUserNameLength, params->adminPassword, params->adminPasswordLength, params->connectString, params->connectStringLength, NULL, NULL, &sysConn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(sysConn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &cntVar, &cntData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(sysConn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &sidVar, &sidData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(sidData, sid); if (dpiStmt_bindByPos(stmt, 1, sidVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, cntVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "No rows found!"); *roundTripCnt = dpiData_getInt64(cntData); // cleanup. if (dpiVar_release(sidVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(cntVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_release(sysConn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyBindCount() [INTERNAL] // Determines the number of bind variables for the given statement and // verifies that it matches the expected value. //----------------------------------------------------------------------------- int dpiTest__verifyBindCount(dpiTestCase *testCase, dpiConn *conn, const char *sql, uint32_t expectedCount) { uint32_t count; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBindCount(stmt, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, count, expectedCount); } //----------------------------------------------------------------------------- // dpiTest_2000() // Prepare any statement; call dpiStmt_release() twice (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2000(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_release(stmt); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2001() // Prepare any query; call dpiStmt_executeMany() (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_2001(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; const uint32_t numIters = 2; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numIters); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2002() // Prepare any CALL statement; call dpiStmt_getInfo() and verify that the // isPLSQL value in the dpiStmtInfo structure is set to 1 and that the // statementType value is set to DPI_STMT_TYPE_CALL (no error). //----------------------------------------------------------------------------- int dpiTest_2002(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "call proc_TestNoArgs();"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 1) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_CALL); } //----------------------------------------------------------------------------- // dpiTest_2003() // Prepare multiple statements with differing numbers of bind variables; call // dpiStmt_getBindCount() and confirm that the value returned is as expected, // for both SQL and PL/SQL statements (no error). //----------------------------------------------------------------------------- int dpiTest_2003(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "select * from TestDataTypes", 0) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "select :1 from TestDataTypes", 1) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "select :1, :2, :3, :4, :5, :6, :7 from TestDataTypes", 7) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "select :1, :2, :3, :4, :5, :6, :7, :8 from TestDataTypes", 8) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "select :1, :2, :3, :4, :5, :6, :7, :8, :9, :9 from TestDataTypes", 10) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "select :1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, " ":13, :14, :15, :16, :17 from TestDataTypes", 17) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "begin select :1, :1 from dual; end;", 1) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "begin select :1, :2, :3, :4, :5, :6, :7 from dual; end;", 7) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "begin select :1, :2, :3, :4, :5, :6, :7, :8, :8 from dual; end;", 8) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "begin select :1, :2, :3, :4, :5, :6, :7, :8, :8, :9, :9, :10 " "from dual; end;", 10) < 0) return DPI_FAILURE; if (dpiTest__verifyBindCount(testCase, conn, "begin select :1, :2, :3, :4, :5, :6, :7, :8, :8, :9, :10, " ":11, :12, :13, :14, :15, :16, :17 from dual; end;", 17) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2004() // Prepare any statement with duplicate bind variable names; call // dpiStmt_getBindNames() and verify that the names of the bind variables match // what is expected, without duplicates (no error). //----------------------------------------------------------------------------- int dpiTest_2004(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select :a, :a, :xy, :xy from TestLongs", **bindNames; uint32_t numBindNames, *bindNameLengths; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBindCount(stmt, &numBindNames) < 0) return dpiTestCase_setFailedFromError(testCase); bindNames = malloc(sizeof(const char *) * numBindNames); bindNameLengths = malloc(sizeof(uint32_t) * numBindNames); if (!bindNames || !bindNameLengths) return dpiTestCase_setFailed(testCase, "Out of memory!"); if (dpiStmt_getBindNames(stmt, &numBindNames, bindNames, bindNameLengths) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numBindNames, 2) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, bindNames[0], bindNameLengths[0], "A", 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, bindNames[1], bindNameLengths[1], "XY", 2) < 0) return DPI_FAILURE; free(bindNames); free(bindNameLengths); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2005() // Prepare any query; call dpiStmt_getInfo() and verify that the isQuery // value in the dpiStmtInfo structure is set to 1 and all other values are set // to zero and that the statementType value is set to DPI_STMT_TYPE_SELECT (no // error). //----------------------------------------------------------------------------- int dpiTest_2005(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_SELECT); } //----------------------------------------------------------------------------- // dpiTest_2006() // Prepare any anonymous PL/SQL block without any declaration section; call // dpiStmt_getInfo() and verify that the isPLSQL value in the dpiStmtInfo // structure is set to 1 and all other values are set to zero and that the // statementType value is set to DPI_STMT_TYPE_BEGIN (no error). //----------------------------------------------------------------------------- int dpiTest_2006(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin NULL; end;"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_BEGIN); } //----------------------------------------------------------------------------- // dpiTest_2007() // Prepare any anonymous PL/SQL block with a declaration section; call // dpiStmt_getInfo() and verify that the isPLSQL value in the dpiStmtInfo // structure is set to 1 and all other values are set to zero and that the // statementType value is set to DPI_STMT_TYPE_DECLARE (no error). //----------------------------------------------------------------------------- int dpiTest_2007(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "declare t number; begin NULL; end;"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_DECLARE); } //----------------------------------------------------------------------------- // dpiTest_2008() // Prepare any insert statement; call dpiStmt_getInfo() and verify that the // isDML value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_INSERT (no error). //----------------------------------------------------------------------------- int dpiTest_2008(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestLongs values (:1, :2)"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_INSERT); } //----------------------------------------------------------------------------- // dpiTest_2009() // Prepare any update statement; call dpiStmt_getInfo() and verify that the // isDML value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_UPDATE (no error). //----------------------------------------------------------------------------- int dpiTest_2009(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "update TestLongs set longcol = :1 where intcol = :2"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_UPDATE); } //----------------------------------------------------------------------------- // dpiTest_2010() // Prepare any delete statement; call dpiStmt_getInfo() and verify that the // isDML value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_DELETE (no error). //----------------------------------------------------------------------------- int dpiTest_2010(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "delete TestLongs"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_DELETE); } //----------------------------------------------------------------------------- // dpiTest_2011() // Prepare any create statement; call dpiStmt_getInfo() and verify that the // isDDL value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_CREATE (no error). //----------------------------------------------------------------------------- int dpiTest_2011(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "create table Test (IntCol number(9))"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_CREATE); } //----------------------------------------------------------------------------- // dpiTest_2012() // Prepare any drop statement; call dpiStmt_getInfo() and verify that the // isDDL value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_DROP (no error). //----------------------------------------------------------------------------- int dpiTest_2012(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "drop table Test"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_DROP); } //----------------------------------------------------------------------------- // dpiTest_2013() // Prepare any alter statement; call dpiStmt_getInfo() and verify that the // isDDL value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_ALTER (no error). //----------------------------------------------------------------------------- int dpiTest_2013(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "alter table Test add X number"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_ALTER); } //----------------------------------------------------------------------------- // dpiTest_2014() // Prepare and execute any query; call dpiStmt_getNumQueryColumns() and // verify that the value returned matches the number of columns expected to be // returned by the query (no error). //----------------------------------------------------------------------------- int dpiTest_2014(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; uint32_t numQueryColumns; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getNumQueryColumns(stmt, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, numQueryColumns, 2); } //----------------------------------------------------------------------------- // dpiTest_2015() // Prepare and execute any non-query; call dpiStmt_getNumQueryColumns() and // verify that the value returned is 0 (no error). //----------------------------------------------------------------------------- int dpiTest_2015(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "delete from TestLongs"; uint32_t numQueryColumns; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getNumQueryColumns(stmt, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, numQueryColumns, 0); } //----------------------------------------------------------------------------- // dpiTest_2016() // Prepare and execute any non-query; call dpiStmt_getQueryInfo() for any // non-zero position (error DPI-1028). //----------------------------------------------------------------------------- int dpiTest_2016(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "delete from TestLongs"; uint32_t numQueryColumns; dpiQueryInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getQueryInfo(stmt, 1, &info); if (dpiTestCase_expectError(testCase, "DPI-1028:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2017() // Prepare and execute any query; call dpiStmt_getQueryInfo() for each of the // columns and verify that the metadata returned is accurate (no error). //----------------------------------------------------------------------------- int dpiTest_2017(dpiTestCase *testCase, dpiTestParams *params) { const char *col1 = "INTCOL", *col2 = "STRINGCOL"; const char *sql = "select * from TestTempTable"; uint32_t numQueryColumns; dpiQueryInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); // verify column 1 if (dpiStmt_getQueryInfo(stmt, 1, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.name, info.nameLength, col1, strlen(col1)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.oracleTypeNum, DPI_ORACLE_TYPE_NUMBER) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.defaultNativeTypeNum, DPI_NATIVE_TYPE_INT64) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.dbSizeInBytes, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.clientSizeInBytes, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.precision, 9) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.scale, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.nullOk, 0) < 0) return DPI_FAILURE; // verify column 2 if (dpiStmt_getQueryInfo(stmt, 2, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, info.name, info.nameLength, col2, strlen(col2)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.oracleTypeNum, DPI_ORACLE_TYPE_VARCHAR) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.defaultNativeTypeNum, DPI_NATIVE_TYPE_BYTES) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.dbSizeInBytes, 100) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.clientSizeInBytes, 100) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.precision, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.typeInfo.scale, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.nullOk, 1) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2018() // Prepare any DML statement; call dpiStmt_executeMany() with an array of // data and mode set to DPI_MODE_EXEC_DEFAULT; call dpiStmt_getRowCounts() // (error ORA-24349). //----------------------------------------------------------------------------- int dpiTest_2018(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestTempTable values (:1, :2)"; const char *truncateSql = "truncate table TestTempTable"; uint32_t numRows = 5, i, numQueryColumns, numRowCounts; dpiData *intData, *strData; dpiVar *intVar, *strVar; uint64_t *rowCounts; char buffer[100]; dpiConn *conn; dpiStmt *stmt; // only supported in 12.1 and higher if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; // truncate table if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare and bind insert statement if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // populate some dummy data for (i = 0; i < numRows; i++) { intData[i].isNull = 0; intData[i].value.asInt64 = i + 1; sprintf(buffer, "Test data %d", i + 1); if (dpiVar_setFromBytes(strVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } // perform execute many in default mode and attempt to get row counts if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getRowCounts(stmt, &numRowCounts, &rowCounts); if (dpiTestCase_expectError(testCase, "ORA-24349:") < 0) return DPI_FAILURE; if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2019() // Prepare any DML statement; call dpiStmt_executeMany() with an array of // data and mode set to DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS; call // dpiStmt_getRowCounts() and verify that the row counts returned matches // expectations; ensure that a value other than 1 is returned for at least one // of the rowcounts (no error). //----------------------------------------------------------------------------- int dpiTest_2019(dpiTestCase *testCase, dpiTestParams *params) { const char *deleteSql = "delete from TestTempTable where IntCol < :1"; const char *insertSql = "insert into TestTempTable values (:1, :2)"; const char *truncateSql = "truncate table TestTempTable"; uint32_t numRows = 5, i, numQueryColumns, numRowCounts; dpiData *intData, *strData; dpiVar *intVar, *strVar; uint64_t *rowCounts; char buffer[100]; dpiConn *conn; dpiStmt *stmt; // only supported in 12.1 and higher if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; // truncate table if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare and bind insert statement if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // populate some dummy data for (i = 0; i < numRows; i++) { intData[i].isNull = 0; intData[i].value.asInt64 = i + 1; sprintf(buffer, "Dummy data %d", i + 1); if (dpiVar_setFromBytes(strVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } // perform insert and verify all row counts are 1 if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCounts(stmt, &numRowCounts, &rowCounts) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numRowCounts, numRows) < 0) return DPI_FAILURE; for (i = 0; i < numRows; i++) { if (dpiTestCase_expectUintEqual(testCase, rowCounts[i], 1) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // perform delete and verify row counts are as expected numRows = 2; if (dpiConn_prepareStmt(conn, 0, deleteSql, strlen(deleteSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); intData[0].isNull = 0; intData[0].value.asInt64 = 2; intData[1].isNull = 0; intData[1].value.asInt64 = 5; if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_ARRAY_DML_ROWCOUNTS, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCounts(stmt, &numRowCounts, &rowCounts) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numRowCounts, numRows) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, rowCounts[0], 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, rowCounts[1], 3) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2020() // Prepare any statement with at least one duplicate bind variable repeated // in sql, call dpiStmt_getBindCount() and confirm that the value returned is // the value expected (no error). //----------------------------------------------------------------------------- int dpiTest_2020(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select :1, :1 from TestLongs"; uint32_t count; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBindCount(stmt, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, count, 2); } //----------------------------------------------------------------------------- // dpiTest_2021() // Prepare any non query with more than one bind variable; call // dpiStmt_executeMany() with the parameter numIters set to a value that is // greater than the maxArraySize for at least one of the variables that // were bound to the statement (error DPI-1018). //----------------------------------------------------------------------------- int dpiTest_2021(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestLongs values (:1, :2)"; dpiData *intdata, *strData; dpiVar *intVar, *strVar; uint32_t numIters = 4; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numIters, 0, 0, 0, NULL, &intVar, &intdata) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numIters - 1, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numIters); if (dpiTestCase_expectError(testCase, "DPI-1018:") < 0) return DPI_FAILURE; if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2022() // Prepare any plsql statement with at least one duplicate bind variables // call dpiStmt_getBindCount() and confirm that the value returned is the value // expected (no error). //----------------------------------------------------------------------------- int dpiTest_2022(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin select :1, :1 from TestLongs; end;"; uint32_t count; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBindCount(stmt, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, count, 1); } //----------------------------------------------------------------------------- // dpiTest_2023() // Prepare any PL/SQL statement; call dpiStmt_getBindNames() and verify that // the names of the bind variables match what is expected, with duplicates // (bind variable name repeated in SQL text) (no error). //----------------------------------------------------------------------------- int dpiTest_2023(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :c := :a1 * :a1 + :a2 * :a2; end;", **bindNames; uint32_t numBindNames, *bindNameLengths; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBindCount(stmt, &numBindNames) < 0) return dpiTestCase_setFailedFromError(testCase); bindNames = malloc(sizeof(const char *) * numBindNames); bindNameLengths = malloc(sizeof(uint32_t) * numBindNames); if (!bindNames || !bindNameLengths) return dpiTestCase_setFailed(testCase, "Out of memory!"); if (dpiStmt_getBindNames(stmt, &numBindNames, bindNames, bindNameLengths) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numBindNames, 3) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, bindNames[0], bindNameLengths[0], "C", 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, bindNames[1], bindNameLengths[1], "A1", 2) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, bindNames[2], bindNameLengths[2], "A2", 2) < 0) return DPI_FAILURE; free(bindNames); free(bindNameLengths); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2024() // Prepare any statement; call dpiStmt_close() and then call each public // function for dpiStmt except for dpiStmt_addRef() and dpiStmt_release() // (error DPI-1039). //----------------------------------------------------------------------------- int dpiTest_2024(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestLongs"; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_close(stmt, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTest__callFunctionsWithError(testCase, stmt, "DPI-1039:"); } //----------------------------------------------------------------------------- // dpiTest_2025() // Call each of the public functions for dpiStmt with the stmt parameter // set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2025(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__callFunctionsWithError(testCase, NULL, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2026() // Prepare any statement; call dpiStmt_getBindNames() with the parameter // numBindNames set to a value less than the number of bind names that are // expected (error DPI-1018). //----------------------------------------------------------------------------- int dpiTest_2026(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select :a, :xy from TestLongs", *bindName; uint32_t numBindNames = 1, bindNameLength; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getBindNames(stmt, &numBindNames, &bindName, &bindNameLength); if (dpiTestCase_expectError(testCase, "DPI-1018:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2027() // Prepare and execute any statement with bind variables; rebind one or more // of the bind variables with different variables and verify that the results // match what is expected (no error). //----------------------------------------------------------------------------- int dpiTest_2027(dpiTestCase *testCase, dpiTestParams *params) { dpiData *inVarData1, *inVarData2, *inVarData3, *outData; const char *sql = "select :1 + :2 from dual"; dpiVar *inVar1, *inVar2, *inVar3; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &inVar1, &inVarData1) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setUint64(inVarData1, 23); if (dpiStmt_bindByPos(stmt, 1, inVar1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &inVar2, &inVarData2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setUint64(inVarData2, 33); if (dpiStmt_bindByPos(stmt, 2, inVar2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &inVar3, &inVarData3) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setUint64(inVarData3, 130); if (dpiStmt_bindByPos(stmt, 1, inVar3) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 0, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "No rows found!"); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, outData->value.asUint64, 163) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar3) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2028() // Call any PL/SQL stored procedure and verify the arguments are passed // correctly (no error). //----------------------------------------------------------------------------- int dpiTest_2028(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin proc_Test(:1, :2, :3); end;"; dpiData *inOutValue, *outValue, inValue; dpiVar *inOutVar, *outVar; uint32_t numQueryColumns; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&inValue, "Test String", strlen("Test String")); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_BYTES, &inValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &inOutVar, &inOutValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(inOutValue, 10); if (dpiStmt_bindByPos(stmt, 2, inOutVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &outVar, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, outVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, inOutValue->value.asInt64, 110) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, outValue->value.asInt64, 11) < 0) return DPI_FAILURE; if (dpiVar_release(inOutVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(outVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2029() // Prepare and execute any statement with at least 17 bind variables with // batch errors enabled and some batch errors expected (no error). //----------------------------------------------------------------------------- int dpiTest_2029(dpiTestCase *testCase, dpiTestParams *params) { const char *truncateSql = "truncate table TestDataTypes"; const char *insertSql = "insert into TestDataTypes (StringCol, " "UnicodeCol, FixedCharCol, FixedUnicodeCol, RawCol, FloatCol, " "DoublePrecCol, IntCol, NumberCol, DateCol, TimestampCol, " "TimestampTZCol, TimestampLTZCol, IntervalDSCol, IntervalYMCol, " "BinaryFltCol, BinaryDoubleCol, LongCol, UnconstrainedCol) values " "(:1, :2, :3, :4, '12AB', :5, :6, :7, :8, :9, :10, :11, :12, :13," " :14, :15, :16, 1.454, :17)"; uint32_t numQueryColumns, numRows = 3, numCols = 17, numErrs = 3, i, count; dpiErrorInfo errorInfo[3]; dpiData *colData[17]; dpiVar *colVar[17]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[0], &colData[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[1], &colData[1]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[2], &colData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[3], &colData[3]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, numRows, 0, 0, 0, NULL, &colVar[4], &colData[4]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, numRows, 0, 0, 0, NULL, &colVar[5], &colData[5]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &colVar[6], &colData[6]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, numRows, 0, 0, 0, NULL, &colVar[7], &colData[7]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, numRows, 0, 0, 0, NULL, &colVar[8], &colData[8]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_TIMESTAMP, numRows, 0, 0, 0, NULL, &colVar[9], &colData[9]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP_TZ, DPI_NATIVE_TYPE_TIMESTAMP, numRows, 0, 0, 0, NULL, &colVar[10], &colData[10]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP_LTZ, DPI_NATIVE_TYPE_TIMESTAMP, numRows, 0, 0, 0, NULL, &colVar[11], &colData[11]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_INTERVAL_DS, DPI_NATIVE_TYPE_INTERVAL_DS, numRows, 0, 0, 0, NULL, &colVar[12], &colData[12]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_INTERVAL_YM, DPI_NATIVE_TYPE_INTERVAL_YM, numRows, 0, 0, 0, NULL, &colVar[13], &colData[13]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_FLOAT, DPI_NATIVE_TYPE_FLOAT, numRows, 0, 0, 0, NULL, &colVar[14], &colData[14]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_DOUBLE, DPI_NATIVE_TYPE_DOUBLE, numRows, 0, 0, 0, NULL, &colVar[15], &colData[15]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, numRows, 0, 0, 0, NULL, &colVar[16], &colData[16]) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numCols; i++) { if (dpiStmt_bindByPos(stmt, i + 1, colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // populate data for (i = 0; i < numRows; i++) { dpiData_setBytes(&colData[0][i], "string", strlen("string")); dpiData_setBytes(&colData[1][i], "unistring", strlen("unistring")); dpiData_setBytes(&colData[2][i], "fixedchar", strlen("fixedchar")); dpiData_setBytes(&colData[3][i], "fixedunichar", strlen("fixedunichar")); dpiData_setDouble(&colData[4][i], 1.25); dpiData_setDouble(&colData[5][i], 1.44); if (i < 2) dpiData_setInt64(&colData[6][i], 1); else dpiData_setInt64(&colData[6][i], 12345678910); dpiData_setDouble(&colData[7][i], 1.35); dpiData_setTimestamp(&colData[8][i], 2017, 6, 1, 2, 2, 1, 0, 0, 0); dpiData_setTimestamp(&colData[9][i], 2017, 6, 1, 2, 2, 1, 0, 0, 0); dpiData_setTimestamp(&colData[10][i], 2017, 6, 1, 2, 2, 1, 0, 0, 0); dpiData_setTimestamp(&colData[11][i], 2017, 6, 1, 2, 2, 1, 0, 0, 0); dpiData_setIntervalDS(&colData[12][i], 3, 2, 1, 1, 0); dpiData_setIntervalYM(&colData[13][i], 1, 1); dpiData_setDouble(&colData[14][i], 1.34); dpiData_setDouble(&colData[15][i], 1.95); dpiData_setDouble(&colData[16][i], 999); } // attempt to insert and validate errors received match expected errors if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_BATCH_ERRORS, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBatchErrorCount(stmt, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBatchErrors(stmt, numErrs, errorInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectErrorInfo(testCase, &errorInfo[0], "ORA-00001:") < 0) return DPI_FAILURE; if (dpiTestCase_expectErrorInfo(testCase, &errorInfo[1], "ORA-01438:") < 0) return DPI_FAILURE; // cleanup for (i = 0; i < numCols; i++) { if (dpiVar_release(colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2030() // Prepare and execute a query that fetches 1000 columns (no error) //----------------------------------------------------------------------------- int dpiTest_2030(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numQueryColumns; char sql[4000], *ptr; dpiConn *conn; dpiStmt *stmt; int i; // generate SQL statement strcpy(sql, "select "); ptr = sql + strlen(sql); for (i = 0; i < 1000; i++) { if (i > 0) *ptr++ = ','; ptr += sprintf(ptr, "%d", i + 1); } strcpy(ptr, " from dual"); // execute it and verify the number of columns returned is as expected if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return dpiTestCase_expectUintEqual(testCase, numQueryColumns, 1000); } //----------------------------------------------------------------------------- // dpiTest_2031() // Prepare any merge statement; call dpiStmt_getInfo() and verify that the // isDML value in the dpiStmtInfo structure is set to 1 and all other values // are set to zero and that the statementType value is set to // DPI_STMT_TYPE_MERGE (no error). //----------------------------------------------------------------------------- int dpiTest_2031(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "merge into t1 a using t1 b on (a.intcol = 1) " "when matched then update set a.longcol = 1 " "when not matched then insert values(1,2)"; dpiStmtInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getInfo(stmt, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, info.isQuery, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isPLSQL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDDL, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isDML, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, info.isReturning, 0) < 0) return DPI_FAILURE; return dpiTestCase_expectUintEqual(testCase, info.statementType, DPI_STMT_TYPE_MERGE); } //----------------------------------------------------------------------------- // dpiTest_2032() // Call any PL/SQL stored function and verify the arguments are passed // correctly and the return value is valid (no error). //----------------------------------------------------------------------------- int dpiTest_2032(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := func_Test(:2, :3); end;"; char *testStr = "Test String"; dpiData *retValue, inputData; uint32_t numQueryColumns; dpiVar *retVar; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&inputData, testStr, strlen(testStr)); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &inputData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&inputData, 10); if (dpiStmt_bindValueByPos(stmt, 3, DPI_NATIVE_TYPE_INT64, &inputData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &retVar, &retValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, retVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, retValue->value.asInt64, strlen(testStr)+10) < 0) return DPI_FAILURE; if (dpiVar_release(retVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2033() // Prepare and execute any query with mode set to DPI_MODE_EXEC_PARSE_ONLY. // Call dpiStmt_getQueryInfo() and verify it does not return any metadata // (error ORA-24338). //----------------------------------------------------------------------------- int dpiTest_2033(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select * from TestTempTable"; dpiQueryInfo info; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_PARSE_ONLY, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getQueryInfo(stmt, 1, &info); if (dpiTestCase_expectError(testCase, "ORA-24338:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2034() // Prepare a statement which attempts to bind the same statement to itself // (error DPI-1013). //----------------------------------------------------------------------------- int dpiTest_2034(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable values(1, :1)"; dpiConn *conn; dpiData *data; dpiStmt *stmt; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_STMT, DPI_NATIVE_TYPE_STMT, 3, 0, 0, 0, NULL, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromStmt(var, 1, stmt); if (dpiTestCase_expectError(testCase, "DPI-1013:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2035() // Prepare any PL/SQL statement; call dpiStmt_executeMany() with an array of // data; call dpiStmt_getRowCount() and verify that the row count returned // matches expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2035(dpiTestCase *testCase, dpiTestParams *params) { const char *deleteSql = "begin delete from TestTempTable where IntCol < :1; end;"; const char *insertSql = "begin insert into TestTempTable values (:1, :2); end;"; const char *truncateSql = "truncate table TestTempTable"; dpiData *intData, *strData; uint32_t numRows = 5, i; dpiVar *intVar, *strVar; uint64_t rowCount; char buffer[100]; dpiConn *conn; dpiStmt *stmt; // truncate table if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare and bind insert statement if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // populate some dummy data for (i = 0; i < numRows; i++) { dpiData_setInt64(&intData[i], i + 1); sprintf(buffer, "Dummy data %d", i + 1); if (dpiVar_setFromBytes(strVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } // perform insert and verify row count if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, rowCount, numRows) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare and bind delete statement numRows = 2; if (dpiConn_prepareStmt(conn, 0, deleteSql, strlen(deleteSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); // set up bind data dpiData_setInt64(&intData[0], 2); dpiData_setInt64(&intData[1], 5); // perform delete and verify row count is as expected; note that the number // of rows actually deleted by the PL/SQL statement is 4, but the row count // returned by PL/SQL will always match the number of iterations executed if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, rowCount, numRows) < 0) return DPI_FAILURE; // clean up if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2036() // Verify that calling dpiStmt_setPrefetchRows() affects the number of // round trips that a particular statement requires. // // NOTE: this test requires administrative credentials and will be skipped if // they are not available. //----------------------------------------------------------------------------- int dpiTest_2036(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select sysdate from dual"; uint32_t bufferRowIndex, prefetchRows; dpiConn *conn; dpiStmt *stmt; int found; // setup for tests if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTestCase_setupRoundTripChecker(testCase, params) < 0) return DPI_FAILURE; // first perform a single row query with the default prefetch which should // only require a single round trip (and first verify that the default // prefetch is indeed set!) if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getPrefetchRows(stmt, &prefetchRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, prefetchRows, DPI_DEFAULT_PREFETCH_ROWS) < 0) return DPI_FAILURE; if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectRoundTripsEqual(testCase, 1) < 0) return DPI_FAILURE; // then perform the same query after setting the prefetch to 0 and verify // that two round trips are now required if (dpiStmt_setPrefetchRows(stmt, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectRoundTripsEqual(testCase, 2) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2000); dpiTestSuite_addCase(dpiTest_2000, "dpiStmt_release() twice"); dpiTestSuite_addCase(dpiTest_2001, "dpiStmt_executeMany() with invalid parameters"); dpiTestSuite_addCase(dpiTest_2002, "dpiStmt_getInfo() for call statement"); dpiTestSuite_addCase(dpiTest_2003, "dpiStmt_getBindCount() with variable binds"); dpiTestSuite_addCase(dpiTest_2004, "dpiStmt_getBindNames() strips duplicates (SQL)"); dpiTestSuite_addCase(dpiTest_2005, "dpiStmt_getInfo() for select statement"); dpiTestSuite_addCase(dpiTest_2006, "dpiStmt_getInfo() for PL/SQL block starting with BEGIN"); dpiTestSuite_addCase(dpiTest_2007, "dpiStmt_getInfo() for PL/SQL block starting with DECLARE"); dpiTestSuite_addCase(dpiTest_2008, "dpiStmt_getInfo() for insert statement"); dpiTestSuite_addCase(dpiTest_2009, "dpiStmt_getInfo() for update statement"); dpiTestSuite_addCase(dpiTest_2010, "dpiStmt_getInfo() for delete statement"); dpiTestSuite_addCase(dpiTest_2011, "dpiStmt_getInfo() for create statement"); dpiTestSuite_addCase(dpiTest_2012, "dpiStmt_getInfo() for drop statement"); dpiTestSuite_addCase(dpiTest_2013, "dpiStmt_getInfo() for alter statement"); dpiTestSuite_addCase(dpiTest_2014, "dpiStmt_getNumQueryColumn() for query"); dpiTestSuite_addCase(dpiTest_2015, "dpiStmt_getNumQueryColumn() for non-query"); dpiTestSuite_addCase(dpiTest_2016, "dpiStmt_getQueryInfo() for non-query"); dpiTestSuite_addCase(dpiTest_2017, "dpiStmt_getQueryInfo() for query"); dpiTestSuite_addCase(dpiTest_2018, "dpiStmt_executeMany() without array DML row counts mode"); dpiTestSuite_addCase(dpiTest_2019, "dpiStmt_executeMany() with array DML row counts mode"); dpiTestSuite_addCase(dpiTest_2020, "dpiStmt_getBindCount() with duplicate binds (SQL)"); dpiTestSuite_addCase(dpiTest_2021, "dpiStmt_executeMany() with invalid number of iterations"); dpiTestSuite_addCase(dpiTest_2022, "dpiStmt_getBindCount() with duplicate binds (PL/SQL)"); dpiTestSuite_addCase(dpiTest_2023, "dpiStmt_getBindNames() strips duplicates (PL/SQL)"); dpiTestSuite_addCase(dpiTest_2024, "dpiStmt_close and call public functions"); dpiTestSuite_addCase(dpiTest_2025, "call pub functions with stmt set to NULL"); dpiTestSuite_addCase(dpiTest_2026, "dpiStmt_getBindNames() with numBindNames set to less value"); dpiTestSuite_addCase(dpiTest_2027, "rebind the variable and verify"); dpiTestSuite_addCase(dpiTest_2028, "call PL/SQL procedure and verify the args are passed properly"); dpiTestSuite_addCase(dpiTest_2029, "bind many variables with batch errors enabled and verify"); dpiTestSuite_addCase(dpiTest_2030, "execute query that fetches 1000 columns"); dpiTestSuite_addCase(dpiTest_2031, "dpiStmt_getInfo() for merge statement"); dpiTestSuite_addCase(dpiTest_2032, "call PL/SQL function & verify the args are passed properly"); dpiTestSuite_addCase(dpiTest_2033, "verify getQueryInfo returns no metadata if mode is parse only"); dpiTestSuite_addCase(dpiTest_2034, "bind a stmt to itself and verify it throws an appropriate error"); dpiTestSuite_addCase(dpiTest_2035, "dpiStmt_executeMany() with PL/SQL statement row count"); dpiTestSuite_addCase(dpiTest_2036, "verify round trips for prefetch values"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2100_data_types.c000066400000000000000000002373061510466437300174660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2100_data_types.c // Test suite for testing all the possible combinations of data types. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__setTimeZone() // Set the session time zone to UTC in order to avoid any discrepancies when // run in different time zones. //----------------------------------------------------------------------------- int dpiTest__setTimeZone(dpiTestCase *testCase, dpiConn *conn) { const char *sql = "alter session set time_zone = 'UTC'"; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyQueryInfo() [INTERNAL] // Verifies each field of dpiQueryInfo. //----------------------------------------------------------------------------- int dpiTest__verifyQueryInfo(dpiTestCase *testCase, dpiStmt *stmt, uint32_t pos, const char *expectedName, dpiOracleTypeNum expectedOracleTypeNum, dpiNativeTypeNum expectedDefaultNativeTypeNum, uint32_t expectedDbSizeInBytes, uint32_t expectedClientSizeInBytes, uint32_t expectedSizeInChars, int16_t expectedPrecision, int8_t expectedScale, uint8_t expectedFsPrecision, int expectedNullOk) { dpiQueryInfo queryInfo; if (dpiStmt_getQueryInfo(stmt, pos, &queryInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, queryInfo.name, queryInfo.nameLength, expectedName, strlen(expectedName)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, queryInfo.typeInfo.oracleTypeNum, expectedOracleTypeNum) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, queryInfo.typeInfo.defaultNativeTypeNum, expectedDefaultNativeTypeNum) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, queryInfo.typeInfo.dbSizeInBytes, expectedDbSizeInBytes) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, queryInfo.typeInfo.clientSizeInBytes, expectedClientSizeInBytes) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, queryInfo.typeInfo.sizeInChars, expectedSizeInChars) < 0) return DPI_FAILURE; if (dpiTestCase_expectIntEqual(testCase, queryInfo.typeInfo.precision, expectedPrecision) < 0) return DPI_FAILURE; if (dpiTestCase_expectIntEqual(testCase, queryInfo.typeInfo.fsPrecision, expectedFsPrecision) < 0) return DPI_FAILURE; if (dpiTestCase_expectIntEqual(testCase, queryInfo.typeInfo.scale, expectedScale) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, queryInfo.nullOk, expectedNullOk) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyLongColsBindByPos() [INTERNAL] // Bind long raw/long varchar datatype by position and verify. //----------------------------------------------------------------------------- int dpiTest__verifyLongColsBindByPos(dpiTestCase *testCase, dpiConn *conn, const char *tableName, const char *colName) { char *dataToSet = "1234ABCD"; char truncateSql[100]; char insertSql[200]; dpiStmt *stmt; dpiData data; sprintf(truncateSql, "truncate table %s", tableName); if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row into table sprintf(insertSql, "insert into %s (IntCol, %s) values (:1, :2)", tableName, colName); if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, dataToSet, strlen(dataToSet)); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyLongColsBindByName() [INTERNAL] // Bind long raw/long varchar datatype by name and verify. //----------------------------------------------------------------------------- int dpiTest__verifyLongColsBindByName(dpiTestCase *testCase, dpiConn *conn, const char *tableName, const char *colName) { char *dataToSet = "1234ABCD"; char truncateSql[100]; char insertSql[200]; dpiStmt *stmt; dpiData data; sprintf(truncateSql, "truncate table %s", tableName); if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row into table sprintf(insertSql, "insert into %s(IntCol, %s) values (:intCol, :longCol)", tableName, colName); if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); if (dpiStmt_bindValueByName(stmt, "intCol", strlen("intCol"), DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, dataToSet, strlen(dataToSet)); if (dpiStmt_bindValueByName(stmt, "longCol", strlen("longCol"), DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2100() // Prepare and execute a query that returns each of the possible combinations // of data types and verify that the metadata returned by // dpiStmt_getQueryInfo() matches expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2100(dpiTestCase *testCase, dpiTestParams *params) { const char *longRawSql = "select LongRawCol from TestLongRaws"; const char *longVarSql = "select LongCol from TestLongs"; const char *urowidSql = "select rowid from TestOrgIndex"; const char *rowidSql = "select rowid from TestNumbers"; const char *baseSql = "select * from TestDataTypes"; dpiConn *conn; dpiStmt *stmt; // connect to database if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // base sql with most data types if (dpiConn_prepareStmt(conn, 0, baseSql, strlen(baseSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyQueryInfo(testCase, stmt, 1, "STRINGCOL", DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 100, 100, 100, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 2, "UNICODECOL", DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, 200, 400, 100, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 3, "FIXEDCHARCOL", DPI_ORACLE_TYPE_CHAR, DPI_NATIVE_TYPE_BYTES, 100, 100, 100, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 4, "FIXEDUNICODECOL", DPI_ORACLE_TYPE_NCHAR, DPI_NATIVE_TYPE_BYTES, 200, 400, 100, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 5, "RAWCOL", DPI_ORACLE_TYPE_RAW, DPI_NATIVE_TYPE_BYTES, 30, 30, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 6, "FLOATCOL", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 0, 0, 0, 126, -127, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 7, "DOUBLEPRECCOL", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 0, 0, 0, 126, -127, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 8, "INTCOL", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 0, 0, 0, 9, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 9, "NUMBERCOL", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 0, 0, 0, 9, 2, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 10, "DATECOL", DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 11, "TIMESTAMPCOL", DPI_ORACLE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_TIMESTAMP, 0, 0, 0, 0, 0, 6, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 12, "TIMESTAMPTZCOL", DPI_ORACLE_TYPE_TIMESTAMP_TZ, DPI_NATIVE_TYPE_TIMESTAMP, 0, 0, 0, 0, 0, 6, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 13, "TIMESTAMPLTZCOL", DPI_ORACLE_TYPE_TIMESTAMP_LTZ, DPI_NATIVE_TYPE_TIMESTAMP, 0, 0, 0, 0, 0, 6, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 14, "INTERVALDSCOL", DPI_ORACLE_TYPE_INTERVAL_DS, DPI_NATIVE_TYPE_INTERVAL_DS, 0, 0, 0, 2, 0, 6, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 15, "INTERVALYMCOL", DPI_ORACLE_TYPE_INTERVAL_YM, DPI_NATIVE_TYPE_INTERVAL_YM, 0, 0, 0, 2, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 16, "BINARYFLTCOL", DPI_ORACLE_TYPE_NATIVE_FLOAT, DPI_NATIVE_TYPE_FLOAT, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 17, "BINARYDOUBLECOL", DPI_ORACLE_TYPE_NATIVE_DOUBLE, DPI_NATIVE_TYPE_DOUBLE, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 18, "CLOBCOL", DPI_ORACLE_TYPE_CLOB, DPI_NATIVE_TYPE_LOB, 0, 0, 0, 0, 0, 0, 1) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 19, "NCLOBCOL", DPI_ORACLE_TYPE_NCLOB, DPI_NATIVE_TYPE_LOB, 0, 0, 0, 0, 0, 0, 1) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 20, "BLOBCOL", DPI_ORACLE_TYPE_BLOB, DPI_NATIVE_TYPE_LOB, 0, 0, 0, 0, 0, 0, 1) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 21, "BFILECOL", DPI_ORACLE_TYPE_BFILE, DPI_NATIVE_TYPE_LOB, 0, 0, 0, 0, 0, 0, 1) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 22, "LONGCOL", DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 23, "UNCONSTRAINEDCOL", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 0, 0, 0, 0, -127, 0, 0) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 24, "SIGNEDINTCOL", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 0, 0, 0, 38, 0, 0, 1) < 0) return DPI_FAILURE; if (dpiTest__verifyQueryInfo(testCase, stmt, 25, "SUBOBJECTCOL", DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 0, 0, 0, 0, 0, 0, 1) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // sql testing rowid column if (dpiConn_prepareStmt(conn, 0, rowidSql, strlen(rowidSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyQueryInfo(testCase, stmt, 1, "ROWID", DPI_ORACLE_TYPE_ROWID, DPI_NATIVE_TYPE_ROWID, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // sql testing urowid column if (dpiConn_prepareStmt(conn, 0, urowidSql, strlen(urowidSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyQueryInfo(testCase, stmt, 1, "ROWID", DPI_ORACLE_TYPE_ROWID, DPI_NATIVE_TYPE_ROWID, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // sql testing long raw column if (dpiConn_prepareStmt(conn, 0, longRawSql, strlen(longRawSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyQueryInfo(testCase, stmt, 1, "LONGRAWCOL", DPI_ORACLE_TYPE_LONG_RAW, DPI_NATIVE_TYPE_BYTES, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // sql testing long varchar column if (dpiConn_prepareStmt(conn, 0, longVarSql, strlen(longVarSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyQueryInfo(testCase, stmt, 1, "LONGCOL", DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, 0, 0, 0, 0, 0, 0, 0) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2101() // Prepare and execute a statement that binds each data type and verify that // the value is bound correctly using dpiStmt_bindValueByPos() (no error). //----------------------------------------------------------------------------- int dpiTest_2101(dpiTestCase *testCase, dpiTestParams *params) { const char *truncateSql = "truncate table TestDataTypes"; const char *insertSql = "insert into TestDataTypes (StringCol, " "UnicodeCol, FixedCharCol, FixedUnicodeCol, RawCol, FloatCol, " "DoublePrecCol, IntCol, NumberCol, DateCol, TimestampCol, " "TimestampTZCol, TimestampLTZCol, IntervalDSCol, IntervalYMCol, " "BinaryFltCol, BinaryDoubleCol, LongCol, UnconstrainedCol, " "SignedIntCol, SubObjectCol) values " "(:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, " ":15, :16, :17, :18, :19, :20, :21)"; const char *subObjName = "UDT_SUBOBJECT"; dpiObjectType *subObjType; dpiObject *subObj; dpiStmt *stmt; dpiConn *conn; dpiData data; // connect to database if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row into table containing all data types if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "string", strlen("string")); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "unistring", strlen("unistring")); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "fixedchar", strlen("fixedchar")); if (dpiStmt_bindValueByPos(stmt, 3, DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "fixedunichar", strlen("fixedunichar")); if (dpiStmt_bindValueByPos(stmt, 4, DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "12AB", strlen("12AB")); if (dpiStmt_bindValueByPos(stmt, 5, DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.25); if (dpiStmt_bindValueByPos(stmt, 6, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.44); if (dpiStmt_bindValueByPos(stmt, 7, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); if (dpiStmt_bindValueByPos(stmt, 8, DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.35); if (dpiStmt_bindValueByPos(stmt, 9, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&data, 2017, 6, 1, 2, 2, 1, 0, 0, 0); if (dpiStmt_bindValueByPos(stmt, 10, DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 11, DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 12, DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 13, DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setIntervalDS(&data, 3, 2, 1, 1, 0); if (dpiStmt_bindValueByPos(stmt, 14, DPI_NATIVE_TYPE_INTERVAL_DS, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setIntervalYM(&data, 1, 1); if (dpiStmt_bindValueByPos(stmt, 15, DPI_NATIVE_TYPE_INTERVAL_YM, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.34); if (dpiStmt_bindValueByPos(stmt, 16, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.95); if (dpiStmt_bindValueByPos(stmt, 17, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.45); if (dpiStmt_bindValueByPos(stmt, 18, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 999); if (dpiStmt_bindValueByPos(stmt, 19, DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 123); if (dpiStmt_bindValueByPos(stmt, 20, DPI_NATIVE_TYPE_UINT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); // get sub object type and create object if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(subObjType, &subObj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, subObj); if (dpiStmt_bindValueByPos(stmt, 21, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(subObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); // verify long raw data type if (dpiTest__verifyLongColsBindByPos(testCase, conn, "TestLongRaws", "LongRawCol") < 0) return DPI_FAILURE; // verify long varchar data type if (dpiTest__verifyLongColsBindByPos(testCase, conn, "TestLongs", "LongCol") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2102() // Prepare and execute a statement that binds each data type and verify that // the value is bound correctly using dpiStmt_bindValueByName() (no error). //----------------------------------------------------------------------------- int dpiTest_2102(dpiTestCase *testCase, dpiTestParams *params) { const char *truncateSql = "truncate table TestDataTypes"; const char *insertSql = "insert into TestDataTypes (StringCol, " "UnicodeCol, FixedCharCol, FixedUnicodeCol, RawCol, FloatCol, " "DoublePrecCol, IntCol, NumberCol, DateCol, TimestampCol, " "TimestampTZCol, TimestampLTZCol, IntervalDSCol, IntervalYMCol, " "BinaryFltCol, BinaryDoubleCol, LongCol, UnconstrainedCol, " "SignedIntCol, SubObjectCol) values " "(:stringCol, :unicodeCol, :fixedCharCol, :fixedUnicodeCol, " ":rawCol, :floatCol, :doublePrecCol, :intCol, :numberCol, " ":dateCol, :timestampCol, :timestampTZCol, :timestampLTZCol, " ":intervalDSCol, :intervalYMCol, :binaryFltCol, :binaryDoubleCol, " ":longCol, :unconstrainedCol, :signedIntCol, :subObjectCol)"; const char *subObjName = "UDT_SUBOBJECT"; dpiObjectType *subObjType; dpiObject *subObj; dpiStmt *stmt; dpiConn *conn; dpiData data; // connect to database if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row into table containing all data types if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "string", strlen("string")); if (dpiStmt_bindValueByName(stmt, "stringCol", strlen("stringCol"), DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "unistring", strlen("unistring")); if (dpiStmt_bindValueByName(stmt, "unicodeCol", strlen("unicodeCol"), DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "fixedchar", strlen("fixedchar")); if (dpiStmt_bindValueByName(stmt, "fixedCharCol", strlen("fixedCharCol"), DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "fixedunichar", strlen("fixedunichar")); if (dpiStmt_bindValueByName(stmt, "fixedUnicodeCol", strlen("fixedUnicodeCol"), DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "12AB", strlen("12AB")); if (dpiStmt_bindValueByName(stmt, "rawCol", strlen("rawCol"), DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.25); if (dpiStmt_bindValueByName(stmt, "floatCol", strlen("floatCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.44); if (dpiStmt_bindValueByName(stmt, "doublePrecCol", strlen("doublePrecCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); if (dpiStmt_bindValueByName(stmt, "intCol", strlen("intCol"), DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.35); if (dpiStmt_bindValueByName(stmt, "numberCol", strlen("numberCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&data, 2017, 6, 1, 2, 2, 1, 0, 0, 0); if (dpiStmt_bindValueByName(stmt, "dateCol", strlen("dateCol"), DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByName(stmt, "timestampCol", strlen("timestampCol"), DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByName(stmt, "timestampTZCol", strlen("timestampTZCol"), DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByName(stmt, "timestampLTZCol", strlen("timestampLTZCol"), DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setIntervalDS(&data, 3, 2, 1, 1, 0); if (dpiStmt_bindValueByName(stmt, "intervalDSCol", strlen("intervalDSCol"), DPI_NATIVE_TYPE_INTERVAL_DS, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setIntervalYM(&data, 1, 1); if (dpiStmt_bindValueByName(stmt, "intervalYMCol", strlen("intervalYMCol"), DPI_NATIVE_TYPE_INTERVAL_YM, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.34); if (dpiStmt_bindValueByName(stmt, "binaryFltCol", strlen("binaryFltCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.95); if (dpiStmt_bindValueByName(stmt, "binaryDoubleCol", strlen("binaryDoubleCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.45); if (dpiStmt_bindValueByName(stmt, "longCol", strlen("longCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 999); if (dpiStmt_bindValueByName(stmt, "unconstrainedCol", strlen("unconstrainedCol"), DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 123); if (dpiStmt_bindValueByName(stmt, "signedIntCol", strlen("signedIntCol"), DPI_NATIVE_TYPE_UINT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); // get sub object type and create object if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(subObjType, &subObj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, subObj); if (dpiStmt_bindValueByName(stmt, "subObjectCol", strlen("subObjectCol"), DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(subObj) < 0) return dpiTestCase_setFailedFromError(testCase); // verify long raw data type if (dpiTest__verifyLongColsBindByName(testCase, conn, "TestLongRaws", "LongRawCol") < 0) return DPI_FAILURE; // verify long varchar data type if (dpiTest__verifyLongColsBindByName(testCase, conn, "TestLongs", "LongCol") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2103() // Prepare and execute a DML returning statement that returns each of the // possible combinations noted above and verify that the value is returned // correctly in each case (no error). //----------------------------------------------------------------------------- int dpiTest_2103(dpiTestCase *testCase, dpiTestParams *params) { const char *truncateSql = "delete from TestDataTypes"; const char *insertSql = "insert into TestDataTypes (StringCol, " "UnicodeCol, FixedCharCol, FixedUnicodeCol, RawCol, FloatCol, " "DoublePrecCol, IntCol, NumberCol, DateCol, TimestampCol, " "TimestampTZCol, TimestampLTZCol, IntervalDSCol, IntervalYMCol, " "BinaryFltCol, BinaryDoubleCol, LongCol, UnconstrainedCol, " "SignedIntCol, SubObjectCol) " "values ('string', 'unistring', 'fixedchar', 'fixedunichar', " "'12AB', 1.25, 1.44, 6, 1.35, TO_DATE('2002/12/10 01:02:03', " "'yyyy/mm/dd hh24:mi:ss'), to_timestamp('20021210', 'YYYYMMDD'), " "to_timestamp_tz('20021210 01:02:03 00:00', " "'YYYYMMDD HH24:MI:SS TZH:TZM'), " "to_timestamp_tz('20021210 01:02:03 00:00', " "'YYYYMMDD HH24:MI:SS TZH:TZM'), INTERVAL '3' DAY, " " INTERVAL '1' YEAR, 1.75, 1.95, 1.454, 999, 567, " "udt_SubObject(1, 'element #1'))"; const char *deleteSql = "delete from TestDataTypes returning StringCol, " "UnicodeCol, FloatCol, DoublePrecCol, IntCol, NumberCol, DateCol, " "TimestampCol, TimestampTZCol, IntervalDSCol, IntervalYMCol, " "BinaryFltCol, BinaryDoubleCol, UnconstrainedCol, SignedIntCol, " "SubObjectCol into " ":stringCol, :unicodeCol, :floatCol, :doublePrecCol, :intCol, " ":numberCol, :dateCol, :timestampCol, :timestampTZCol, " ":intervalDSCol, :intervalYMCol, :binaryFltCol, :binaryDoubleCol, " ":unconstrainedCol, :signedIntCol, :subObjectCol"; const char *subObjName = "UDT_SUBOBJECT"; uint32_t numCols = 16, i, numAttr = 2, numReturnedRows; dpiData *colData[16], tempData; dpiObjectType *subObjType; dpiObjectAttr *attrs[2]; dpiVar *colVar[16]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // populate table if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 0, 0, NULL, &colVar[0], &colData[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 0, 0, NULL, &colVar[1], &colData[1]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &colVar[2], &colData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &colVar[3], &colData[3]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &colVar[4], &colData[4]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &colVar[5], &colData[5]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &colVar[6], &colData[6]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &colVar[7], &colData[7]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP_TZ, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &colVar[8], &colData[8]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_INTERVAL_DS, DPI_NATIVE_TYPE_INTERVAL_DS, 1, 0, 0, 0, NULL, &colVar[9], &colData[9]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_INTERVAL_YM, DPI_NATIVE_TYPE_INTERVAL_YM, 1, 0, 0, 0, NULL, &colVar[10], &colData[10]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_FLOAT, DPI_NATIVE_TYPE_FLOAT, 1, 0, 0, 0, NULL, &colVar[11], &colData[11]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_DOUBLE, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &colVar[12], &colData[12]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &colVar[13], &colData[13]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &colVar[14], &colData[14]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, subObjType, &colVar[15], &colData[15]) < 0) return dpiTestCase_setFailedFromError(testCase); // delete statement with DML returning if (dpiConn_prepareStmt(conn, 0, deleteSql, strlen(deleteSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numCols; i++) { if (dpiStmt_bindByPos(stmt, i + 1, colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numCols; i++) { if (dpiVar_getReturnedData(colVar[i], 0, &numReturnedRows, &colData[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // compare data returned to expected data if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(colData[0])->ptr, dpiData_getBytes(colData[0])->length, "string", strlen("string")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(colData[1])->ptr, dpiData_getBytes(colData[1])->length, "unistring", strlen("unistring")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(colData[2]), 1.25) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(colData[3]), 1.44) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getUint64(colData[4]), 6) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(colData[5]), 1.35) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2002, 12, 10, 1, 2, 3, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(colData[6]), dpiData_getTimestamp(&tempData)) < 0) return DPI_FAILURE; dpiData_setTimestamp(&tempData, 2002, 12, 10, 0, 0, 0, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(colData[7]), dpiData_getTimestamp(&tempData)) < 0) return DPI_FAILURE; dpiData_setTimestamp(&tempData, 2002, 12, 10, 1, 2, 3, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(colData[8]), dpiData_getTimestamp(&tempData)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, dpiData_getIntervalDS(colData[9])->days, 3) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getIntervalYM(colData[10])->years, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getFloat(colData[11]), 1.75) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(colData[12]), 1.95) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(colData[13]), 999) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getInt64(colData[14]), 567) < 0) return dpiTestCase_setFailedFromError(testCase); // get attribute values of the object and compare if (dpiObjectType_getAttributes(subObjType, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(dpiData_getObject(colData[15]), attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&tempData), 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(dpiData_getObject(colData[15]), attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(&tempData)->ptr, dpiData_getBytes(&tempData)->length, "element #1", strlen("element #1")) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup for (i = 0; i < numCols; i++) { if (dpiVar_release(colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiObjectType_release(subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2104() // Prepare and execute a PL/SQL statement that binds both in and out each // of the possible combinations of data types and verify that the value is // returned correctly in each case (no error). //----------------------------------------------------------------------------- int dpiTest_2104(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin proc_TestInOut(:1, :2, :3, :4, :5, :6, :7, :8, " ":9, :10, :11, :12, :13, :14); end;"; char *strValue = "TestData", *modifiedStrValue = "TestData (Modified)"; const char *boolSql = "begin proc_TestInOutBool(:1); end;"; char *modifiedUnicodeValue = "Unicode (Modified)"; const char *objName = "UDT_SUBOBJECT"; char *unicodeValue = "Unicode"; dpiData *inOutData[14], tempData; dpiVersionInfo *versionInfo; uint32_t numCols = 14, i; dpiObjectAttr *attrs[2]; dpiObjectType *objType; dpiVar *inOutVar[14]; dpiBytes *bytes; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variable for boolean dpiTestSuite_getClientVersionInfo(&versionInfo); if (versionInfo->versionNum >= 12) { if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_BOOLEAN, DPI_NATIVE_TYPE_BOOLEAN, 1, 0, 0, 0, NULL, &inOutVar[0], &inOutData[0]) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBool(inOutData[0], 1); // call stored procedure if (dpiConn_prepareStmt(conn, 0, boolSql, strlen(boolSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inOutVar[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); // compare results if (dpiTestCase_expectUintEqual(testCase, dpiData_getBool(inOutData[0]), 1) < 0) return DPI_FAILURE; if (dpiVar_release(inOutVar[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); } // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 1, 0, NULL, &inOutVar[0], &inOutData[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 1, 0, NULL, &inOutVar[1], &inOutData[1]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &inOutVar[2], &inOutData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &inOutVar[3], &inOutData[3]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &inOutVar[4], &inOutData[4]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &inOutVar[5], &inOutData[5]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &inOutVar[6], &inOutData[6]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_TIMESTAMP_TZ, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &inOutVar[7], &inOutData[7]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_INTERVAL_DS, DPI_NATIVE_TYPE_INTERVAL_DS, 1, 0, 0, 0, NULL, &inOutVar[8], &inOutData[8]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_INTERVAL_YM, DPI_NATIVE_TYPE_INTERVAL_YM, 1, 0, 0, 0, NULL, &inOutVar[9], &inOutData[9]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_FLOAT, DPI_NATIVE_TYPE_FLOAT, 1, 0, 0, 0, NULL, &inOutVar[10], &inOutData[10]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NATIVE_DOUBLE, DPI_NATIVE_TYPE_DOUBLE, 1, 0, 0, 0, NULL, &inOutVar[11], &inOutData[11]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_UINT64, 1, 0, 0, 0, NULL, &inOutVar[12], &inOutData[12]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, 2, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &inOutVar[13], &inOutData[13]) < 0) return dpiTestCase_setFailedFromError(testCase); // set input values if (dpiVar_setFromBytes(inOutVar[0], 0, strValue, strlen(strValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(inOutVar[1], 0, unicodeValue, strlen(unicodeValue)) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(inOutData[2], 1.5); dpiData_setDouble(inOutData[3], 1.5); dpiData_setInt64(inOutData[4], 1); dpiData_setTimestamp(inOutData[5], 2017, 6, 1, 1, 2, 1, 1, 0, 0); dpiData_setTimestamp(inOutData[6], 2017, 6, 1, 1, 2, 1, 1, 0, 0); dpiData_setTimestamp(inOutData[7], 2017, 6, 1, 1, 2, 1, 1, 0, 0); dpiData_setIntervalDS(inOutData[8], 3, 1, 1, 1, 1); dpiData_setIntervalYM(inOutData[9], 1, 1); dpiData_setFloat(inOutData[10], 1.34); dpiData_setDouble(inOutData[11], 1.95); dpiData_setUint64(inOutData[12], 123); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&tempData, 12.33); if (dpiObject_setAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&tempData, strValue, strlen(strValue)); if (dpiObject_setAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromObject(inOutVar[13], 0, obj) < 0) return dpiTestCase_setFailedFromError(testCase); // call stored procedure if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numCols; i++){ if (dpiStmt_bindByPos(stmt, i + 1, inOutVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); // compare results bytes = dpiData_getBytes(inOutData[0]); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, modifiedStrValue, strlen(modifiedStrValue)) < 0) return DPI_FAILURE; bytes = dpiData_getBytes(inOutData[1]); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, modifiedUnicodeValue, strlen(modifiedUnicodeValue)) < 0) return DPI_FAILURE; if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(inOutData[2]), 3) < 0) return DPI_FAILURE; if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(inOutData[3]), 3) < 0) return DPI_FAILURE; if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(inOutData[4]), 2) < 0) return DPI_FAILURE; dpiData_setTimestamp(&tempData, 2018, 6, 1, 1, 2, 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(inOutData[5]), dpiData_getTimestamp(&tempData)) < 0) return DPI_FAILURE; dpiData_setTimestamp(&tempData, 2017, 6, 1, 1, 32, 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(inOutData[6]), dpiData_getTimestamp(&tempData)) < 0) return DPI_FAILURE; if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(inOutData[7]), dpiData_getTimestamp(&tempData)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, dpiData_getIntervalDS(inOutData[8])->days, 6) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, dpiData_getIntervalYM(inOutData[9])->years, 2) < 0) return DPI_FAILURE; if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getFloat(inOutData[10]), (float) 2.68) < 0) return DPI_FAILURE; if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(inOutData[11]), 3.9) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, dpiData_getUint64(inOutData[12]), 246) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(inOutData[13]->value.asObject, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return DPI_FAILURE; if (dpiTestCase_expectDoubleEqual(testCase, tempData.value.asDouble, 36.99) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(inOutData[13]->value.asObject, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, tempData.value.asBytes.ptr, tempData.value.asBytes.length, modifiedStrValue, strlen(modifiedStrValue)) < 0) return DPI_FAILURE; // cleanup if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < 2; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } for (i = 0; i < numCols; i++) { if (dpiVar_release(inOutVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2105() // Get and set the attribute value of an object that uses each of the // possible combinations noted above and verify that the value is both set and // acquired correctly in each case (no error). //----------------------------------------------------------------------------- int dpiTest_2105(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestObjectDataTypes values (:1)"; const char *selectSql = "select ObjectCol from TestObjectDataTypes"; const char *objectName = "UDT_OBJECTDATATYPES"; dpiData data, *objColValue, attrValues[14]; uint32_t i, bufferRowIndex, numAttrs = 14; dpiNativeTypeNum nativeTypeNum; dpiObjectAttrInfo attrInfo; dpiObjectAttr *attrs[14]; dpiQueryInfo queryInfo; dpiObjectType *objType; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; int found; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__setTimeZone(testCase, conn) < 0) return DPI_FAILURE; // get object type and attributes if (dpiConn_getObjectType(conn, objectName, strlen(objectName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create object and populate attributes if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "StringData", strlen("StringData")); if (dpiObject_setAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "UnicodeData", strlen("UnicodeData")); if (dpiObject_setAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "FixedCharData", strlen("FixedCharData")); if (dpiObject_setAttributeValue(obj, attrs[2], DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "FixedUnicodeData", strlen("FixedUnicodeData")); if (dpiObject_setAttributeValue(obj, attrs[3], DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&data, "RawData", strlen("RawData")); if (dpiObject_setAttributeValue(obj, attrs[4], DPI_NATIVE_TYPE_BYTES, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 5); if (dpiObject_setAttributeValue(obj, attrs[5], DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 1.25); if (dpiObject_setAttributeValue(obj, attrs[6], DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&data, 2017, 6, 1, 2, 2, 1, 0, 0, 0); if (dpiObject_setAttributeValue(obj, attrs[7], DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_setAttributeValue(obj, attrs[8], DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_setAttributeValue(obj, attrs[9], DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_setAttributeValue(obj, attrs[10], DPI_NATIVE_TYPE_TIMESTAMP, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setFloat(&data, 13.25); if (dpiObject_setAttributeValue(obj, attrs[11], DPI_NATIVE_TYPE_FLOAT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 13.25); if (dpiObject_setAttributeValue(obj, attrs[12], DPI_NATIVE_TYPE_DOUBLE, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 123); if (dpiObject_setAttributeValue(obj, attrs[13], DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); // insert data if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) dpiObjectAttr_release(attrs[i]); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // retrieve data if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryInfo(stmt, 1, &queryInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(queryInfo.typeInfo.objectType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &objColValue) < 0) return dpiTestCase_setFailedFromError(testCase); obj = dpiData_getObject(objColValue); // retrieve all of the attributes for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_getInfo(attrs[i], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(obj, attrs[i], attrInfo.typeInfo.defaultNativeTypeNum, &attrValues[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // compare values if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(&attrValues[0])->ptr, dpiData_getBytes(&attrValues[0])->length, "StringData", strlen("StringData")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(&attrValues[1])->ptr, dpiData_getBytes(&attrValues[1])->length, "UnicodeData", strlen("UnicodeData")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(&attrValues[2])->ptr, dpiData_getBytes(&attrValues[2])->length, "FixedCharData ", strlen("FixedCharData ")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(&attrValues[3])->ptr, dpiData_getBytes(&attrValues[3])->length, "FixedUnicodeData ", strlen("FixedUnicodeData ")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, dpiData_getBytes(&attrValues[4])->ptr, dpiData_getBytes(&attrValues[4])->length, "RawData", strlen("RawData")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&attrValues[5]), 5) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&attrValues[6]), 1.25) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&data, 2017, 6, 1, 2, 2, 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&attrValues[7]), dpiData_getTimestamp(&data)) < 0) return DPI_FAILURE; if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&attrValues[8]), dpiData_getTimestamp(&data)) < 0) return DPI_FAILURE; if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&attrValues[9]), dpiData_getTimestamp(&data)) < 0) return DPI_FAILURE; if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&attrValues[10]), dpiData_getTimestamp(&data)) < 0) return DPI_FAILURE; if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getFloat(&attrValues[11]), 13.25) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&attrValues[12]), 13.25) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&attrValues[13]), 123) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2106() // For Oracle type DPI_ORACLE_TYPE_NUMBER and native type // DPI_NATIVE_TYPE_BYTES, verify binding and fetching for various string // values: // // 1. value 0. // 2. integers (+/-) with 38 digits without leading and trailing zeros. // 3. integers (+/-) that test the upper boundary (9e125) // 4. fractions (+/-) with 38 digits without leading and trailing zeros. // 5. fractions (+/-) that test the lower boundary (1e-130) //----------------------------------------------------------------------------- int dpiTest_2106(dpiTestCase *testCase, dpiTestParams *params) { const char *outValues[] = { "0", "92999999999999999999999999999999999999", "-92999999999999999999999999999999999999", "999999999999999999999999999999999999999", "-999999999999999999999999999999999999999", "9999999999999999999999999999999999999999", "-9999999999999999999999999999999999999999", "900000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000", "-90000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000", "3.0123456789012345678901234567890123456", "-3.0123456789012345678901234567890123456", "0.0000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000" "01", "-0.000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000" "001", }; const char *inValues[] = { "0", "92999999999999999999999999999999999999", "-92999999999999999999999999999999999999", "999999999999999999999999999999999999999", "-999999999999999999999999999999999999999", "9999999999999999999999999999999999999999", "-9999999999999999999999999999999999999999", "9E+125", "-9E+125", "3.0123456789012345678901234567890123456", "-3.0123456789012345678901234567890123456", "1E-130", "-1E-130", NULL }; const char *sql = "select :1 from dual"; dpiData *inputVarData, *resultVarData; dpiVar *inputVar, *resultVar; uint32_t bufferRowIndex; dpiConn *conn; dpiStmt *stmt; int found, i; // create variables and prepare statement for execution if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &inputVar, &inputVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &resultVar, &resultVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); // process each case for (i = 0; inValues[i]; i++) { if (dpiVar_setFromBytes(inputVar, 0, inValues[i], strlen(inValues[i])) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_define(stmt, 1, resultVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, resultVarData->value.asBytes.ptr, resultVarData->value.asBytes.length, outValues[i], strlen(outValues[i])) < 0) return DPI_FAILURE; } // cleanup if (dpiVar_release(inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(resultVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2107() // For Oracle type DPI_ORACLE_TYPE_NUMBER and native type // DPI_NATIVE_TYPE_BYTES, verify binding and fetching for various unexpected // string values that return errors: // // 1. integers (+/-) greater than the upper boundary fail (error DPI-1044) // 2. numbers that have more than 38 digits (error DPI-1044) // 3. string that is not a valid number (ex: www.json.org, non-numeric // characters, multiple decimal points (error DPI-1043) //----------------------------------------------------------------------------- int dpiTest_2107(dpiTestCase *testCase, dpiTestParams *params) { const char *outValues[] = { "DPI-1044:", "DPI-1044:", "DPI-1044:", "DPI-1044:", "DPI-1044:", "DPI-1044:", "DPI-1043:", "DPI-1043:", "DPI-1043:", "DPI-1043:", "DPI-1043:", "DPI-1043:" }; const char *inValues[] = { "1E+126", "-1E+126", "1E-131", "-1E-131", "99999999999999999999999999999999999999999", "-99999999999999999999999999999999999999999", "www.json.org", "1.2.3", "a", "inf", "-inf", "nan", NULL }; const char *sql = "select :1 from dual"; dpiData *inputVarData; dpiVar *inputVar; dpiConn *conn; dpiStmt *stmt; int i; // create variables and prepare statement for execution if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_BYTES, 1, 0, 0, 0, NULL, &inputVar, &inputVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); // process each case for (i = 0; inValues[i]; i++) { if (dpiVar_setFromBytes(inputVar, 0, inValues[i], strlen(inValues[i])) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, outValues[i]) < 0) return DPI_FAILURE; } // cleanup if (dpiVar_release(inputVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2108() // Verify that collections containing date and timestamp attributes work as // expected (no error). //----------------------------------------------------------------------------- int dpiTest_2108(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestDatesVarray values(:1)"; const char *selectSql = "select ObjectCol from TestDatesVarray"; uint32_t i, numElements = 10, numAttrs = 5, bufferRowIndex; dpiObjectType *arrayObjType, *elementObjType; const char *arrayObjName = "UDT_DATESARRAY"; const char *elementObjName = "UDT_DATES"; dpiObject *arrayObj, *elementObj; dpiNativeTypeNum nativeTypeNum; dpiTimestamp timestamps[10][4]; dpiData tempData, *arrayValue; dpiObjectAttr *attrs[5]; dpiVar *arrayVar; dpiStmt *stmt; dpiConn *conn; int32_t size; int found; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__setTimeZone(testCase, conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create objects if (dpiObjectType_createObject(arrayObjType, &arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(elementObjType, &elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variable if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate timestamps with expected values memset(timestamps, 0, sizeof(timestamps)); for (i = 0; i < numElements; i++) { // date timestamps[i][0].year = i + 1917; timestamps[i][0].month = i + 1; timestamps[i][0].day = i + 1; timestamps[i][0].hour = i; timestamps[i][0].minute = i; timestamps[i][0].second = i; // timestamp timestamps[i][1].year = i + 1986; timestamps[i][1].month = i + 2; timestamps[i][1].day = i + 5; timestamps[i][1].hour = i + 1; timestamps[i][1].minute = i * 2; timestamps[i][1].second = i * 3; timestamps[i][1].fsecond = 201000; // timestamp with time zone timestamps[i][2].year = i + 1989; timestamps[i][2].month = i + 1; timestamps[i][2].day = i + 8; timestamps[i][2].hour = i; timestamps[i][2].minute = i * 3; timestamps[i][2].second = i * 4; timestamps[i][2].fsecond = 45000; // timestamp with local time zone timestamps[i][3].year = i + 1999; timestamps[i][3].month = i + 2; timestamps[i][3].day = i + 15; timestamps[i][3].hour = i + 1; timestamps[i][3].minute = i * 2; timestamps[i][3].second = i * 3; timestamps[i][3].fsecond = 123456000; } // populate bind variables with values for (i = 0; i < numElements; i++) { dpiData_setInt64(&tempData, i + 1); if (dpiObject_setAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); tempData.value.asTimestamp = timestamps[i][0]; if (dpiObject_setAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); tempData.value.asTimestamp = timestamps[i][1]; if (dpiObject_setAttributeValue(elementObj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); tempData.value.asTimestamp = timestamps[i][2]; if (dpiObject_setAttributeValue(elementObj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); tempData.value.asTimestamp = timestamps[i][3]; if (dpiObject_setAttributeValue(elementObj, attrs[4], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&tempData, elementObj); if (dpiObject_appendElement(arrayObj, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare insert statement and perform binds if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // retrieve data if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); arrayObj = dpiData_getObject(arrayValue); // verify that returned object matches what was inserted if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; for (i = 0; i < size; i++) { if (dpiObject_getElementValueByIndex(arrayObj, i, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); elementObj = dpiData_getObject(&tempData); if (dpiObject_getAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i + 1) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), ×tamps[i][0]) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), ×tamps[i][1]) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), ×tamps[i][2]) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[4], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), ×tamps[i][3]) < 0) return DPI_FAILURE; if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2100); dpiTestSuite_addCase(dpiTest_2100, "verify metadata returned by dpiStmt_getQueryInfo()"); dpiTestSuite_addCase(dpiTest_2101, "bind all data types using position and verify"); dpiTestSuite_addCase(dpiTest_2102, "bind all data types using name and verify"); dpiTestSuite_addCase(dpiTest_2103, "verify DML returning stmt returns values correctly"); dpiTestSuite_addCase(dpiTest_2104, "verify in/out binds are handled correctly"); dpiTestSuite_addCase(dpiTest_2105, "verify get and set attributes of an object"); dpiTestSuite_addCase(dpiTest_2106, "verify oracle type number with diff string values"); dpiTestSuite_addCase(dpiTest_2107, "test conversion of string to number for invalid values"); dpiTestSuite_addCase(dpiTest_2108, "verify collection containing dates works as expected"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2200_object_types.c000066400000000000000000000516721510466437300200240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2200_object_types.c // Test suite for testing all the object type related cases. //----------------------------------------------------------------------------- #include "TestLib.h" #define NUM_ATTRS 7 //----------------------------------------------------------------------------- // dpiTest__verifyAttributeInfo() [INTERNAL] // Verifies each field of dpiObjectAttrInfo. //----------------------------------------------------------------------------- int dpiTest__verifyAttributeInfo(dpiTestCase *testCase, dpiObjectAttrInfo *attrInfo, const char *expectedName, dpiOracleTypeNum expectedOracleTypeNum, dpiNativeTypeNum expectedDefaultNativeTypeNum, const char *expectedObjectTypeName) { dpiObjectTypeInfo typeInfo; if (dpiTestCase_expectStringEqual(testCase, attrInfo->name, attrInfo->nameLength, expectedName, strlen(expectedName)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, attrInfo->typeInfo.oracleTypeNum, expectedOracleTypeNum) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, attrInfo->typeInfo.defaultNativeTypeNum, expectedDefaultNativeTypeNum) < 0) return DPI_FAILURE; if (expectedObjectTypeName && !attrInfo->typeInfo.objectType) return dpiTestCase_setFailed(testCase, "Expected object type but got NULL"); if (!expectedObjectTypeName && attrInfo->typeInfo.objectType) return dpiTestCase_setFailed(testCase, "Expected no object type but got one"); if (expectedObjectTypeName && attrInfo->typeInfo.objectType) { if (dpiObjectType_getInfo(attrInfo->typeInfo.objectType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, typeInfo.name, typeInfo.nameLength, expectedObjectTypeName, strlen(expectedObjectTypeName)) < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyObjectTypeInfo() [INTERNAL] // Verifies each field of dpiObjectTypeInfo. //----------------------------------------------------------------------------- int dpiTest__verifyObjectTypeInfo(dpiTestCase *testCase, dpiObjectTypeInfo *typeInfo, const char *expectedSchemaName, uint32_t expectedSchemaNameLength, const char * expectedName, int expectedIsCollection, dpiOracleTypeNum expectedOracleTypeNum, dpiNativeTypeNum expectedDefaultNativeTypeNum, dpiObjectType *expectedObjectType, uint16_t expectedNumAttrs) { if (dpiTestCase_expectStringEqual(testCase, typeInfo->schema, typeInfo->schemaLength, expectedSchemaName, expectedSchemaNameLength) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, typeInfo->name, typeInfo->nameLength, expectedName, strlen(expectedName)) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, typeInfo->isCollection, expectedIsCollection) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, typeInfo->numAttributes, expectedNumAttrs) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, typeInfo->elementTypeInfo.oracleTypeNum, expectedOracleTypeNum) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, typeInfo->elementTypeInfo.defaultNativeTypeNum, expectedDefaultNativeTypeNum) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2200() // Call dpiConn_getObjectType() with an invalid object type name (error). //----------------------------------------------------------------------------- int dpiTest_2200(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-04043:", "OCI-22303:", NULL }; const char *objStr = "INVALID_OBJECT_TYPE"; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType); return dpiTestCase_expectAnyError(testCase, expectedErrors); } //----------------------------------------------------------------------------- // dpiTest_2201() // Call dpiConn_getObjectType() with a valid object type name (no error). //----------------------------------------------------------------------------- int dpiTest_2201(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_OBJECTDATATYPES"; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2202() // Call dpiConn_getObjectType() with a valid object type name; call // dpiObjectType_release() twice (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2202(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_OBJECTDATATYPES"; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObjectType_release(objType); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2203() // Call each public function for dpiObjectType with the objType parameter // set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2203(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiObjectAttr *attributes[NUM_ATTRS]; dpiObjectTypeInfo info; dpiObject *obj; dpiObjectType_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObjectType_createObject(NULL, &obj); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObjectType_getAttributes(NULL, 0, attributes); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObjectType_getInfo(NULL, &info); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObjectType_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2204() // Call dpiConn_getObjectType() with any valid object type name that has // attributes; call dpiObjectType_getAttributes() with the numAttributes // parameter set to a value smaller than the actual number of // parameters (error DPI-1018). //----------------------------------------------------------------------------- int dpiTest_2204(dpiTestCase *testCase, dpiTestParams *params) { dpiObjectAttr *attributes[NUM_ATTRS]; const char *objStr = "UDT_OBJECT"; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObjectType_getAttributes(objType, 5, attributes); if (dpiTestCase_expectError(testCase, "DPI-1018:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2205() // Call dpiConn_getObjectType() with any valid object type name that has // attributes; call dpiObjectType_getAttributes() and call // dpiObjectAttr_getInfo() on each attribute returned, verifying that the // metadata matches expectations; ensure that at least one of the attributes is // also an object type (no error). //----------------------------------------------------------------------------- int dpiTest_2205(dpiTestCase *testCase, dpiTestParams *params) { dpiObjectAttr *attributes[NUM_ATTRS]; const char *objStr = "UDT_OBJECT"; dpiObjectAttrInfo attrInfo; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; uint32_t i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, typeInfo.numAttributes, attributes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectAttr_getInfo(attributes[0], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "NUMBERVALUE", DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, NULL) < 0) return DPI_FAILURE; if (dpiObjectAttr_getInfo(attributes[1], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "STRINGVALUE", DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiObjectAttr_getInfo(attributes[2], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "FIXEDCHARVALUE", DPI_ORACLE_TYPE_CHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiObjectAttr_getInfo(attributes[3], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "DATEVALUE", DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, NULL) < 0) return DPI_FAILURE; if (dpiObjectAttr_getInfo(attributes[4], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "TIMESTAMPVALUE", DPI_ORACLE_TYPE_TIMESTAMP, DPI_NATIVE_TYPE_TIMESTAMP, NULL) < 0) return DPI_FAILURE; if (dpiObjectAttr_getInfo(attributes[5], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "SUBOBJECTVALUE", DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, "UDT_SUBOBJECT") < 0) return DPI_FAILURE; if (dpiObjectAttr_getInfo(attributes[6], &attrInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyAttributeInfo(testCase, &attrInfo, "SUBOBJECTARRAY", DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, "UDT_OBJECTARRAY") < 0) return DPI_FAILURE; for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attributes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2206() // Call dpiConn_getObjectType() with a valid object type name that refers // to a collection containing an object; call dpiObjectType_getInfo() // and confirm that in the dpiObjectTypeInfo structure the isCollection // attribute is set to 1 and that the numAttributes attribute is set to 0; // verify the remaining attributes match expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2206(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_OBJECTARRAY"; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyObjectTypeInfo(testCase, &typeInfo, params->mainUserName, params->mainUserNameLength, objStr, 1, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, NULL, 0) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2207() // Call dpiConn_getObjectType() with a valid object type name that refers // to a collection containing scalar values; call dpiObjectType_getInfo() // and confirm that in the dpiObjectTypeInfo structure the isCollection // attribute is set to 1 and that the numAttributes attribute is set to 0; // verify the remaining attributes match expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2207(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_ARRAY"; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyObjectTypeInfo(testCase, &typeInfo, params->mainUserName, params->mainUserNameLength, objStr, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, NULL, 0) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2208() // Call dpiConn_getObjectType() with a valid object type name that refers to // a type that is not a collection; call dpiObjectType_getInfo() and confirm // that in the dpiObjectTypeInfo structure the isCollection attribute is set to // 0; verify the remaining attributes match expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2208(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "UDT_OBJECT"; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyObjectTypeInfo(testCase, &typeInfo, params->mainUserName, params->mainUserNameLength, objStr, 0, 0, 0, NULL, NUM_ATTRS) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2209() // Call dpiConn_getObjectType() with a PL/SQL indexed-by-binary-integer table // and validate the results from the call to dpiObjectType_getInfo() (no // error). //----------------------------------------------------------------------------- int dpiTest_2209(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "PKG_TESTNUMBERARRAYS.UDT_NUMBERLIST"; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyObjectTypeInfo(testCase, &typeInfo, params->mainUserName, params->mainUserNameLength, "UDT_NUMBERLIST", 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_DOUBLE, NULL, 0) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2210() // Call dpiConn_getObjectType() with a PL/SQL record type and validate the // results from the call to dpiObjectType_getInfo() (no error). //----------------------------------------------------------------------------- int dpiTest_2210(dpiTestCase *testCase, dpiTestParams *params) { const char *objStr = "PKG_TESTRECORDS.UDT_RECORD"; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objStr, strlen(objStr), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyObjectTypeInfo(testCase, &typeInfo, params->mainUserName, params->mainUserNameLength, "UDT_RECORD", 0, 0, 0, NULL, 7) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2200); dpiTestSuite_addCase(dpiTest_2200, "dpiConn_getObjectType() with invalid name"); dpiTestSuite_addCase(dpiTest_2201, "dpiConn_getObjectType() with valid name"); dpiTestSuite_addCase(dpiTest_2202, "dpiObjectType_release() called twice"); dpiTestSuite_addCase(dpiTest_2203, "call object type functions with NULL object type"); dpiTestSuite_addCase(dpiTest_2204, "dpiObjectType_getAttributes() with too small numAttributes"); dpiTestSuite_addCase(dpiTest_2205, "dpiObjectAttr_getInfo() and verify metadata"); dpiTestSuite_addCase(dpiTest_2206, "dpiObjectType_getInfo() of collection containing an object"); dpiTestSuite_addCase(dpiTest_2207, "dpiObjectType_getInfo() of collection containing scalar values"); dpiTestSuite_addCase(dpiTest_2208, "dpiObjectType_getInfo() of object type with attributes"); dpiTestSuite_addCase(dpiTest_2209, "dpiObjectType_getInfo() of indexed-by binary integer table"); dpiTestSuite_addCase(dpiTest_2210, "dpiObjectType_getInfo() of PL/SQL record type"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2300_objects.c000066400000000000000000003016461510466437300167630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2300_objects.c // Test suite for testing all the object related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" #define TYPE_NAME "PKG_TESTSTRINGARRAYS.UDT_STRINGLIST" #define SQL_TEXT "begin pkg_TestStringArrays.TestIndexBy(:1); end;" //----------------------------------------------------------------------------- // dpiTest__createNestedData() [INTERNAL] // Function to create nested data. //----------------------------------------------------------------------------- int dpiTest__createNestedData(dpiTestCase *testCase, dpiConn *conn, dpiObjectType *objType, dpiObjectType *ntType, dpiObjectType *ntOfNtType, dpiObject **outObj, uint32_t rowNum, dpiObjectAttr **attrs) { dpiObject *outerList, *innerList, *subObj; dpiData tempData, objData; char name[60]; int i, j; // create outer list object if (dpiObjectType_createObject(ntOfNtType, &outerList) < 0) return dpiTestCase_setFailedFromError(testCase); // populate outer list object with elements for (i = 0; i < 2; i++) { if (i == 1) { dpiData_setNull(&objData); innerList = NULL; } else { // create list of sub-objects if (dpiObjectType_createObject(ntType, &innerList) < 0) return dpiTestCase_setFailedFromError(testCase); for (j = 0; j < 2; j++) { // create sub-object if (dpiObjectType_createObject(objType, &subObj) < 0) return dpiTestCase_setFailedFromError(testCase); // set sub-object attribute for SubNumberValue dpiData_setInt64(&tempData, rowNum * 100 + i * 10 + j); if (dpiObject_setAttributeValue(subObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); // set sub-object attribute for SubStringValue snprintf(name, sizeof(name), "Member%d%d", i + 1, j + 1); dpiData_setBytes(&tempData, name, strlen(name)); if (dpiObject_setAttributeValue(subObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); // append element dpiData_setObject(&tempData, subObj); if (dpiObject_appendElement(innerList, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(subObj) < 0) return dpiTestCase_setFailedFromError(testCase); } dpiData_setObject(&objData, innerList); } // append element if (dpiObject_appendElement(outerList, DPI_NATIVE_TYPE_OBJECT, &objData) < 0) return dpiTestCase_setFailedFromError(testCase); if (innerList && dpiObject_release(innerList) < 0) return dpiTestCase_setFailedFromError(testCase); } *outObj = outerList; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__fetchRows() [INTERNAL] // Function to fetch rows from nested table. //----------------------------------------------------------------------------- int dpiTest__fetchRows(dpiTestCase *testCase, dpiConn *conn, dpiObjectType *objType, dpiObjectType *ntType, dpiObjectType *ntOfNtType, dpiObjectAttr **attrs) { const char *sql = "select IntCol, StringCol, NestedCol " "from TestNestedCollections order by IntCol"; dpiObject *outerNested, *innerNested, *subObj; uint32_t bufferRowIndex, rowNum, numCols; int32_t i, j, outerCount, innerCount; dpiNativeTypeNum nativeTypeNum; dpiData *fetchedData; dpiData tempData; dpiBytes *bytes; dpiStmt *stmt; char name[60]; int found; // prepare and execute statement if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numCols) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_defineValue(stmt, 1, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 0, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch all rows rowNum = 0; while (1) { // get next row from the result set if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) break; // validate value of IntCol if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &fetchedData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(fetchedData), rowNum + 1) < 0) return DPI_FAILURE; // validate value of StringCol if (dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &fetchedData) < 0) return dpiTestCase_setFailedFromError(testCase); snprintf(name, sizeof(name), "Team %d", rowNum + 1); bytes = dpiData_getBytes(fetchedData); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, name, strlen(name)) < 0) return DPI_FAILURE; // validate value of NestedCol if (dpiStmt_getQueryValue(stmt, 3, &nativeTypeNum, &fetchedData) < 0) return dpiTestCase_setFailedFromError(testCase); outerNested = dpiData_getObject(fetchedData); if (dpiObject_getSize(outerNested, &outerCount) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < outerCount; i++) { // check element of outer nested table if (dpiObject_getElementValueByIndex(outerNested, i, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (tempData.isNull) continue; // check elements of inner nested table innerNested = dpiData_getObject(&tempData); if (dpiObject_getSize(innerNested, &innerCount) < 0) return dpiTestCase_setFailedFromError(testCase); for (j = 0; j < innerCount; j++) { // get element of inner nested table if (dpiObject_getElementValueByIndex(innerNested, j, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); subObj = dpiData_getObject(&tempData); // check NumberValue of sub-object if (dpiObject_getAttributeValue(subObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), rowNum * 100 + i * 10 + j) < 0) return DPI_FAILURE; // check StringValue of sub-object if (dpiObject_getAttributeValue(subObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(&tempData); snprintf(name, sizeof(name), "Member%d%d", i + 1, j + 1); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, name, strlen(name)) < 0) return DPI_FAILURE; // cleanup if (dpiObject_release(subObj) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiObject_release(innerNested) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiObject_release(outerNested) < 0) return dpiTestCase_setFailedFromError(testCase); rowNum++; } // final cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__insertNtRows() [INTERNAL] // Function to insert rows into the nested table. //----------------------------------------------------------------------------- int dpiTest__insertNtRows(dpiTestCase *testCase, dpiConn *conn, dpiObjectType *objType, dpiObjectType *ntType, dpiObjectType *ntOfNtType, dpiObjectAttr **attrs, uint32_t numRows) { const char *insertSql = "insert into TestNestedCollections (IntCol, StringCol, NestedCol) " "values (:1, :2, :3)"; dpiData intData, strData, objData; dpiObject *nested; char label[60]; dpiStmt *stmt; uint32_t i; for (i = 0; i < numRows; i++) { snprintf(label, sizeof(label), "Team %d", i + 1); if (dpiTest__createNestedData(testCase, conn, objType, ntType, ntOfNtType, &nested, i, attrs) < 0) return DPI_FAILURE; dpiData_setInt64(&intData, i + 1); dpiData_setBytes(&strData, label, strlen(label)); dpiData_setObject(&objData, nested); if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt, 3, DPI_NATIVE_TYPE_OBJECT, &objData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(nested) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2300() // Call dpiObjectType_createObject(); call dpiObject_release() twice (error // DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2300(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_release(obj); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2301() // Call each of the dpiObject public functions with the obj parameter set to // NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2301(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiNativeTypeNum nativeTypeNum = DPI_NATIVE_TYPE_INT64; int32_t index, prevIndex, nextIndex, size; dpiConn *conn; dpiObject *obj; dpiData data; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiObject_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiData_setInt64(&data, 1); dpiObject_appendElement(NULL, nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_copy(NULL, &obj); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_deleteElementByIndex(NULL, 1); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getAttributeValue(NULL, NULL, nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getElementExistsByIndex(NULL, 1, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getElementValueByIndex(NULL, 1, nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getFirstIndex(NULL, &index, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getLastIndex(NULL, &index, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getNextIndex(NULL, 1, &nextIndex, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getPrevIndex(NULL, 1, &prevIndex, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_getSize(NULL, &size); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_setAttributeValue(NULL, NULL, nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_setElementValueByIndex(NULL, 1, nativeTypeNum, &data); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiObject_trim(NULL, 2); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2302() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_appendElement() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2302(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2303() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_deleteElementByIndex() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2303(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_deleteElementByIndex(obj, 1); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2304() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_getElementExistsByIndex() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2304(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getElementExistsByIndex(obj, 1, &exists); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2305() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_getElementValueByIndex() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2305(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getElementValueByIndex(obj, 1, DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2306() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_getFirstIndex() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2306(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; int32_t index; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getFirstIndex(obj, &index, &exists); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2307() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_getLastIndex() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2307(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; int32_t index; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getLastIndex(obj, &index, &exists); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2308() // call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_getNextIndex() (error DPI-1023) //----------------------------------------------------------------------------- int dpiTest_2308(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; int32_t nextIndex; dpiObject *obj; dpiConn *conn; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getNextIndex(obj, 1, &nextIndex, &exists); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2309() // Call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_getPrevIndex() (error DPI-1023). //----------------------------------------------------------------------------- int dpiTest_2309(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; int32_t prevIndex; dpiObject *obj; dpiConn *conn; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getPrevIndex(obj, 2, &prevIndex, &exists); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2310() // call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_setElementValueByIndex() (error DPI-1023) //----------------------------------------------------------------------------- int dpiTest_2310(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); dpiObject_setElementValueByIndex(obj, 1, DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2311() // call dpiObjectType_createObject() with an object type that is not a // collection; call dpiObject_trim() (error DPI-1023) //----------------------------------------------------------------------------- int dpiTest_2311(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_trim(obj, 2); if (dpiTestCase_expectError(testCase, "DPI-1023:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2312() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() with a value that does not match // the expected element type (error DPI-1014). //----------------------------------------------------------------------------- int dpiTest_2312(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECTARRAY"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); dpiObject_appendElement(obj, DPI_NATIVE_TYPE_INT64, &data); if (dpiTestCase_expectError(testCase, "DPI-1014:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2313() // call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() with a value that matches the // expected element type; verify that the size reported by dpiObject_getSize() // is now 1 (no error) //----------------------------------------------------------------------------- int dpiTest_2313(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_OBJECTARRAY"; dpiObjectType *objType, *objType2; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; int32_t size; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, size, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2314() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_deleteElementByIndex() with any // index value (error OCI-22160). //----------------------------------------------------------------------------- int dpiTest_2314(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_deleteElementByIndex(obj, 0); if (dpiTestCase_expectError(testCase, "OCI-22160:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2315() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() at least once; call // dpiObject_deleteElementByIndex() with a valid index and confirm that the // element has been deleted by calling dpiObject_getElementExistsByIndex() (no // error). //----------------------------------------------------------------------------- int dpiTest_2315(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType, *objType2; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_deleteElementByIndex(obj, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getElementExistsByIndex(obj, 0, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, exists, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2316() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() at least once; call // dpiObject_getElementExistsByIndex() with an index that is known to not exist // and verify the value returned is 0; call dpiObject_getElementExistsByIndex() // with an index that is known to exist and verify the value returned is 1 (no // error). //----------------------------------------------------------------------------- int dpiTest_2316(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType, *objType2; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getElementExistsByIndex(obj, 1, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, exists, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getElementExistsByIndex(obj, 0, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, exists, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2317() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() at least once; call // dpiObject_getElementValueByIndex() with a native type that is incompatible // with the element type (error DPI-1014). //----------------------------------------------------------------------------- int dpiTest_2317(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType, *objType2; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getElementValueByIndex(obj, 0, DPI_NATIVE_TYPE_INT64, &data); if (dpiTestCase_expectError(testCase, "DPI-1014:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2318() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() at least once; call // dpiObject_getElementValueByIndex() with an index that is known to not exist // (error DPI-1024). //----------------------------------------------------------------------------- int dpiTest_2318(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType, *objType2; dpiObject *obj, *obj2; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getElementValueByIndex(obj, 1, DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1024:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2319() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_setElementValue() with a native type that is // incompatible with the element type (error DPI-1014). //----------------------------------------------------------------------------- int dpiTest_2319(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType; dpiConn *conn; dpiObject *obj; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); dpiObject_setElementValueByIndex(obj, 0, DPI_NATIVE_TYPE_INT64, &data); if (dpiTestCase_expectError(testCase, "DPI-1014:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2320() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_trim() with any value for numToTrim (error // OCI-22167). //----------------------------------------------------------------------------- int dpiTest_2320(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_OBJECTARRAY"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_trim(obj, 1); if (dpiTestCase_expectError(testCase, "OCI-22167:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2321() // Call dpiObjectType_createObject() with an object type that is a // collection; append any number of elements to the collection; call // dpiObject_trim() with any value less than the number of elements appended // and verify that the size of the collection is the expected size (no error). //----------------------------------------------------------------------------- int dpiTest_2321(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_OBJECTARRAY"; dpiObjectType *objType, *subObjType; dpiObject *obj, *subObj1, *subObj2; dpiConn *conn; dpiData data; int32_t size; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(subObjType, &subObj1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(subObjType, &subObj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, subObj1); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, subObj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, size, 2) < 0) return DPI_FAILURE; if (dpiObject_trim(obj, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, size, 1) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(subObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(subObj1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(subObj2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2322() // Call dpiObject_getAttributeValue() with an attribute that does not belong // to the object type of the object (error DPI-1022). //----------------------------------------------------------------------------- int dpiTest_2322(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_SUBOBJECT", *objName2 = "UDT_OBJECT"; dpiObjectType *objType, *objType2; dpiObjectAttr *attributes[7]; dpiObjectTypeInfo typeInfo; dpiObject *obj; dpiConn *conn; uint32_t i; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, objName2, strlen(objName2), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType2, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType2, typeInfo.numAttributes, attributes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getAttributeValue(obj, attributes[0], DPI_NATIVE_TYPE_DOUBLE, &data); if (dpiTestCase_expectError(testCase, "DPI-1022:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < typeInfo.numAttributes; i++) { if (dpiObjectAttr_release(attributes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2323() // Call dpiObject_getAttributeValue() with a native type that does not // correspond to the attribute value's type (error). //----------------------------------------------------------------------------- int dpiTest_2323(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_SUBOBJECT"; dpiObjectAttr *attributes[2]; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; dpiData data; uint32_t i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, typeInfo.numAttributes, attributes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 5); if (dpiObject_setAttributeValue(obj, attributes[0], DPI_NATIVE_TYPE_INT64, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getAttributeValue(obj, attributes[0], DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1014:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < typeInfo.numAttributes; i++) { if (dpiObjectAttr_release(attributes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2324() // Call PL/SQL procedure which populates an object of a type that is not // a collection; call dpiObject_getAttributeValue() with a NULL value for the // attribute parameter (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2324(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_SUBOBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiObject_getAttributeValue(obj, NULL, DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2325() // Call dpiObject_setAttributeValue() with an attribute that does not belong // to the object type of the object (error DPI-1022). //----------------------------------------------------------------------------- int dpiTest_2325(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_SUBOBJECT", *objName2 = "UDT_OBJECT"; dpiObjectType *objType, *objType2; dpiObjectAttr *attributes[7]; dpiObjectTypeInfo typeInfo; dpiObject *obj; dpiConn *conn; dpiData data; uint32_t i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, objName2, strlen(objName2), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType2, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType2, typeInfo.numAttributes, attributes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&data, 12.25); dpiObject_setAttributeValue(obj, attributes[0], DPI_NATIVE_TYPE_DOUBLE, &data); if (dpiTestCase_expectError(testCase, "DPI-1022:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < typeInfo.numAttributes; i++) { if (dpiObjectAttr_release(attributes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2326() // Call dpiObject_setAttributeValue() with a native type that does not // correspond to the attribute value's type (error). //----------------------------------------------------------------------------- int dpiTest_2326(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_SUBOBJECT"; dpiObjectAttr *attributes[2]; dpiObjectTypeInfo typeInfo; dpiObjectType *objType; dpiConn *conn; dpiObject *obj; dpiData data; uint32_t i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getInfo(objType, &typeInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, typeInfo.numAttributes, attributes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setIntervalYM(&data, 1, 5); dpiObject_setAttributeValue(obj, attributes[0], DPI_NATIVE_TYPE_INTERVAL_YM, &data); if (dpiTestCase_expectError(testCase, "DPI-1014:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < typeInfo.numAttributes; i++) { if (dpiObjectAttr_release(attributes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2327() // Call dpiObject_setAttributeValue() with a NULL value for the attribute // parameter (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2327(dpiTestCase *testCase, dpiTestParams *params) { const char *objName = "UDT_SUBOBJECT"; dpiObjectType *objType; dpiObject *obj; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&data, 1); dpiObject_setAttributeValue(obj, NULL, DPI_NATIVE_TYPE_INT64, &data); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2328() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() at least once; call // dpiObject_getElementValueByIndex() with an index that is known to exist // and verify the value returned is the expected value (no error). //----------------------------------------------------------------------------- int dpiTest_2328(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiData outData, attrValue, getValue; dpiObjectType *objType, *objType2; double testDouble = 1234.567999; char *testStr = "Test String"; dpiObjectAttr *attrs[2]; dpiObject *obj, *obj2; uint32_t numAttr = 2; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType2, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&attrValue, testDouble); if (dpiObject_setAttributeValue(obj2, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&attrValue, testStr, strlen(testStr)); if (dpiObject_setAttributeValue(obj2, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getElementValueByIndex(obj, 0, DPI_NATIVE_TYPE_OBJECT, &outData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(outData.value.asObject, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, getValue.value.asDouble, testDouble) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(outData.value.asObject, attrs[1], DPI_NATIVE_TYPE_BYTES, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue.value.asBytes.ptr, getValue.value.asBytes.length, testStr, strlen(testStr)) < 0) return DPI_FAILURE; if (dpiObject_release(outData.value.asObject) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2329() // Call dpiObject_getFirstIndex() and dpiObject_getLastIndex() and verify the // values returned are the expected values (no error). //----------------------------------------------------------------------------- int dpiTest_2329(dpiTestCase *testCase, dpiTestParams *params) { const char *stringData[2] = { "First element", "Fourth element" }; uint32_t numQueryColumns; dpiObjectType *objType; int32_t elementIndex; dpiData *objectValue; dpiData elementValue; dpiVar *objectVar; dpiStmt *stmt; dpiConn *conn; int exists; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, TYPE_NAME, strlen(TYPE_NAME), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getFirstIndex(objectValue->value.asObject, &elementIndex, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); if (!exists) return dpiTestCase_setFailed(testCase, "No elements exist!"); if (dpiObject_getElementValueByIndex(objectValue->value.asObject, elementIndex, DPI_NATIVE_TYPE_BYTES, &elementValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, elementValue.value.asBytes.ptr, elementValue.value.asBytes.length, stringData[0], strlen(stringData[0])) < 0) return DPI_FAILURE; if (dpiObject_getLastIndex(objectValue->value.asObject, &elementIndex, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); if (!exists) return dpiTestCase_setFailed(testCase, "No elements exist!"); if (dpiObject_getElementValueByIndex(objectValue->value.asObject, elementIndex, DPI_NATIVE_TYPE_BYTES, &elementValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, elementValue.value.asBytes.ptr, elementValue.value.asBytes.length, stringData[1], strlen(stringData[1])) < 0) return DPI_FAILURE; if (dpiVar_release(objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2330() // Call dpiObject_getFirstIndex() followed by dpiObject_getNextIndex() // repeatedly to iterate through the collection and verify the indices // returned match the expected values (no error). //----------------------------------------------------------------------------- int dpiTest_2330(dpiTestCase *testCase, dpiTestParams *params) { int32_t indexes[4] = { -1048576, -576, 284, 8388608 }; uint32_t numQueryColumns, numElements = 4; int32_t elementIndex, nextElementIndex; dpiObjectType *objType; dpiData *objectValue; dpiVar *objectVar; dpiStmt *stmt; dpiConn *conn; int exists, i; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, TYPE_NAME, strlen(TYPE_NAME), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getFirstIndex(objectValue->value.asObject, &elementIndex, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); if (!exists) return dpiTestCase_setFailed(testCase, "No elements exist!"); for (i = 0; i < numElements; i++) { if (!exists) return dpiTestCase_setFailed(testCase, "Missing expected element!"); if (dpiTestCase_expectIntEqual(testCase, elementIndex, indexes[i]) < 0) return DPI_FAILURE; if (dpiObject_getNextIndex(objectValue->value.asObject, elementIndex, &nextElementIndex, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); elementIndex = nextElementIndex; } if (exists) return dpiTestCase_setFailed(testCase, "Unexpected element found!"); if (dpiVar_release(objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2331() // Call dpiObject_getLastIndex() followed by dpiObject_getPrevIndex() // repeatedly to iterate through the collection and verify the indices returned // match the expected values (no error). //----------------------------------------------------------------------------- int dpiTest_2331(dpiTestCase *testCase, dpiTestParams *params) { int32_t indexes[4] = { 8388608, 284, -576, -1048576 }; uint32_t numQueryColumns, numElements = 4; int32_t elementIndex, prevElementIndex; dpiObjectType *objType; dpiData *objectValue; dpiVar *objectVar; dpiStmt *stmt; dpiConn *conn; int exists, i; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, TYPE_NAME, strlen(TYPE_NAME), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, SQL_TEXT, strlen(SQL_TEXT), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getLastIndex(objectValue->value.asObject, &elementIndex, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numElements; i++) { if (!exists) return dpiTestCase_setFailed(testCase, "Missing expected element!"); if (dpiTestCase_expectIntEqual(testCase, elementIndex, indexes[i]) < 0) return DPI_FAILURE; if (dpiObject_getPrevIndex(objectValue->value.asObject, elementIndex, &prevElementIndex, &exists) < 0) return dpiTestCase_setFailedFromError(testCase); elementIndex = prevElementIndex; } if (exists) return dpiTestCase_setFailed(testCase, "Unexpected element found!"); if (dpiVar_release(objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2332() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_setElementValueByIndex() with a native type that // is compatible with the element type; verify that the element was set // properly by calling dpiObject_getElementValueByIndex() and verifying the // values match (no error). //----------------------------------------------------------------------------- int dpiTest_2332(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiData outData, attrValue, getValue; dpiObjectType *objType, *objType2; double testDouble = 1234.5679999; char *testStr = "Test String"; dpiObjectAttr *attrs[2]; dpiObject *obj, *obj2; uint32_t numAttr = 2; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType2, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&attrValue, testDouble); if (dpiObject_setAttributeValue(obj2, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&attrValue, testStr, strlen(testStr)); if (dpiObject_setAttributeValue(obj2, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); if (dpiObject_setElementValueByIndex(obj, 0, DPI_NATIVE_TYPE_OBJECT, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getElementValueByIndex(obj, 0, DPI_NATIVE_TYPE_OBJECT, &outData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(outData.value.asObject, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, getValue.value.asDouble, testDouble) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(outData.value.asObject, attrs[1], DPI_NATIVE_TYPE_BYTES, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue.value.asBytes.ptr, getValue.value.asBytes.length, testStr, strlen(testStr)) < 0) return DPI_FAILURE; if (dpiObject_release(outData.value.asObject) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2333() // Call dpiObject_copy() and verify that the copy is a true copy of the // original object; append or delete an element of one of the objects and // verify that only the one object has been changed (no error). //----------------------------------------------------------------------------- int dpiTest_2333(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; double testDouble = 1234.5679999; char *testStr = "Test String"; dpiData outData, attrValue, getValue; dpiObjectType *objType, *objType2; dpiObject *obj, *obj2, *copiedObj; dpiObjectAttr *attrs[2]; uint32_t numAttr = 2; dpiConn *conn; int32_t size; int i; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 2) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType2, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&attrValue, testDouble); if (dpiObject_setAttributeValue(obj2, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&attrValue, testStr, strlen(testStr)); if (dpiObject_setAttributeValue(obj2, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_copy(obj, &copiedObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getElementValueByIndex(copiedObj, 0, DPI_NATIVE_TYPE_OBJECT, &outData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(outData.value.asObject, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, getValue.value.asDouble, testDouble) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(outData.value.asObject, attrs[1], DPI_NATIVE_TYPE_BYTES, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue.value.asBytes.ptr, getValue.value.asBytes.length, testStr, strlen(testStr)) < 0) return DPI_FAILURE; if (dpiObject_release(outData.value.asObject) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); if (dpiObject_appendElement(copiedObj, DPI_NATIVE_TYPE_OBJECT, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, size, 1) < 0) return DPI_FAILURE; if (dpiObject_getSize(copiedObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, size, 2) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(copiedObj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2334() // Call PL/SQL procedure which populates an object of a type that is not a // collection; call dpiObject_copy() and verify that the copy is a true copy of // the original object; set one or more of the attributes of one of the objects // and verify that only the one object has been changed (no error). //----------------------------------------------------------------------------- int dpiTest_2334(dpiTestCase *testCase, dpiTestParams *params) { double testDouble1 = 1234.5679999, testDouble2 = 5678999.1234; const char *objName = "UDT_SUBOBJECT"; char *testStr = "Test String"; dpiData attrValue, getValue; dpiObject *obj, *copiedObj; dpiObjectType *objType; dpiObjectAttr *attrs[2]; uint32_t numAttr = 2; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&attrValue, testDouble1); if (dpiObject_setAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&attrValue, testStr, strlen(testStr)); if (dpiObject_setAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_copy(obj, &copiedObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(copiedObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, getValue.value.asDouble, testDouble1) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(copiedObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue.value.asBytes.ptr, getValue.value.asBytes.length, testStr, strlen(testStr)) < 0) return DPI_FAILURE; dpiData_setDouble(&attrValue, testDouble2); if (dpiObject_setAttributeValue(copiedObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(copiedObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, getValue.value.asDouble, testDouble2) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, getValue.value.asDouble, testDouble1) < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(copiedObj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2335() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_appendElement() with an object that does not // match the expected type (error DPI-1056). //----------------------------------------------------------------------------- int dpiTest_2335(dpiTestCase *testCase, dpiTestParams *params) { const char *collectionObjTypeName = "UDT_OBJECTARRAY"; dpiObjectType *collectionObjType, *elementObjType; const char *elementObjTypeName = "UDT_OBJECT"; dpiObject *collectionObj, *elementObj; dpiConn *conn; dpiData data; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, collectionObjTypeName, strlen(collectionObjTypeName), &collectionObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjTypeName, strlen(elementObjTypeName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(collectionObjType, &collectionObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(elementObjType, &elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, elementObj); dpiObject_appendElement(collectionObj, DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1056:") < 0) return DPI_FAILURE; if (dpiObjectType_release(collectionObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(collectionObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2336() // Call dpiObjectType_createObject() with an object type that is not a // collection; set the attribute of an object to an object of the wrong type // (error DPI-1056). //----------------------------------------------------------------------------- int dpiTest_2336(dpiTestCase *testCase, dpiTestParams *params) { const char *valueObjTypeName = "UDT_SUBOBJECT"; const char *objTypeName = "UDT_OBJECT"; dpiObjectType *objType, *valueObjType; dpiObject *obj, *valueObj; dpiObjectAttr *attrs[7]; uint32_t numAttrs = 7; dpiConn *conn; dpiData data; int i; // get object types and attributes if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objTypeName, strlen(objTypeName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, valueObjTypeName, strlen(valueObjTypeName), &valueObjType) < 0) return dpiTestCase_setFailedFromError(testCase); // create object and attempt to set attribute if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(valueObjType, &valueObj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&data, valueObj); dpiObject_setAttributeValue(obj, attrs[6], DPI_NATIVE_TYPE_OBJECT, &data); if (dpiTestCase_expectError(testCase, "DPI-1056:") < 0) return DPI_FAILURE; // cleanup if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(valueObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(valueObj) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2337() // Create a variable with one object type and attempt to set its value with // an object of another type (error DPI-1056). //----------------------------------------------------------------------------- int dpiTest_2337(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedObjTypeName = "UDT_SUBOBJECT"; const char *varObjTypeName = "UDT_OBJECT"; dpiObjectType *objType, *varObjType; dpiObject *obj; dpiConn *conn; dpiData *data; dpiVar *var; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, varObjTypeName, strlen(varObjTypeName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, expectedObjTypeName, strlen(expectedObjTypeName), &varObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, varObjType, &var, &data) < 0) return dpiTestCase_setFailedFromError(testCase); dpiVar_setFromObject(var, 0, obj); if (dpiTestCase_expectError(testCase, "DPI-1056:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(varObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2338() // Call dpiObjectType_createObject() with an object type that is a // collection; call dpiObject_setElementValueByIndex() with a native type that // is incompatible with the element type (error). //----------------------------------------------------------------------------- int dpiTest_2338(dpiTestCase *testCase, dpiTestParams *params) { const char *subObjName = "UDT_SUBOBJECT"; const char *objName = "UDT_NESTEDARRAY"; dpiObjectType *objType, *objType2; double testDouble = 1234.5679999; char *testStr = "Test String"; dpiObjectAttr *attrs[2]; dpiObject *obj, *obj2; uint32_t numAttr = 2; dpiData attrValue; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, subObjName, strlen(subObjName), &objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType2, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType2, &obj2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_OBJECT, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&attrValue, testDouble); if (dpiObject_setAttributeValue(obj2, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&attrValue, testStr, strlen(testStr)); if (dpiObject_setAttributeValue(obj2, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&attrValue, obj2); dpiObject_setElementValueByIndex(obj, 0, DPI_NATIVE_TYPE_INT64, &attrValue); if (dpiTestCase_expectError(testCase, "DPI-1014:") < 0) return DPI_FAILURE; if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj2) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2339() // Call dpiConn_getObjectType() with objName as NULL (error DPI-1046). call // dpiObjectType_createObject() with an object type that is NULL // (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2339(dpiTestCase *testCase, dpiTestParams *params) { dpiObjectType *objType = NULL; const char *objName = NULL; dpiObject *obj; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_getObjectType(conn, objName, 0, &objType); if (dpiTestCase_expectError(testCase, "DPI-1046:") < 0) return DPI_FAILURE; dpiObjectType_createObject(objType, &obj); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2340() // Test inserts, fetches, deletes works as expected with nested collections. //----------------------------------------------------------------------------- int dpiTest_2340(dpiTestCase *testCase, dpiTestParams *params) { dpiObjectType *objType, *ntType, *ntOfNtType; uint32_t numRows = 100, numAttr = 2; dpiObjectAttr *attrs[2]; dpiConn *conn; int i; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 2) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types if (dpiConn_getObjectType(conn, "UDT_SUBOBJECT", strlen("UDT_SUBOBJECT"), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, "UDT_NESTTAB", strlen("UDT_NESTTAB"), &ntType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, "UDT_NESTTABOFNESTTAB", strlen("UDT_NESTTABOFNESTTAB"), &ntOfNtType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttr, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // insert rows into nested table if (dpiTest__insertNtRows(testCase, conn, objType, ntType, ntOfNtType, attrs, numRows) < 0) return DPI_FAILURE; // fetch rows from the nested table if (dpiTest__fetchRows(testCase, conn, objType, ntType, ntOfNtType, attrs) < 0) return DPI_FAILURE; // cleanup for (i = 0; i < numAttr; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(ntType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(ntOfNtType) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2300); dpiTestSuite_addCase(dpiTest_2300, "dpiObjectType_createObject() with dpiObject_release() twice"); dpiTestSuite_addCase(dpiTest_2301, "call all object functions with NULL object"); dpiTestSuite_addCase(dpiTest_2302, "dpiObject_appendElement() with non-collection object"); dpiTestSuite_addCase(dpiTest_2303, "dpiObject_deleteElementByIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2304, "dpiObject_getElementExistsByIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2305, "dpiObject_getElementValueByIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2306, "dpiObject_getFirstIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2307, "dpiObject_getLastIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2308, "dpiObject_getNextIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2309, "dpiObject_getPrevIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2310, "dpiObject_setElementValueByIndex() with non-collection object"); dpiTestSuite_addCase(dpiTest_2311, "dpiObject_trim() with non-collection object"); dpiTestSuite_addCase(dpiTest_2312, "dpiObject_appendElement() with invalid element type"); dpiTestSuite_addCase(dpiTest_2313, "dpiObject_appendElement() with valid element type"); dpiTestSuite_addCase(dpiTest_2314, "dpiObject_deleteElementByIndex() with invalid index"); dpiTestSuite_addCase(dpiTest_2315, "dpiObject_deleteElementByIndex() with valid index"); dpiTestSuite_addCase(dpiTest_2316, "dpiObject_getElementExistsByIndex() with valid/invalid indices"); dpiTestSuite_addCase(dpiTest_2317, "dpiObject_getElementValueByIndex() with invalid element type"); dpiTestSuite_addCase(dpiTest_2318, "dpiObject_getElementValueByIndex() with invalid index"); dpiTestSuite_addCase(dpiTest_2319, "dpiObject_setElementValueByIndex() with invalid element type"); dpiTestSuite_addCase(dpiTest_2320, "dpiObject_trim() on empty collection"); dpiTestSuite_addCase(dpiTest_2321, "dpiObject_trim() with valid number of elements"); dpiTestSuite_addCase(dpiTest_2322, "dpiObject_getAttributeValue() with invalid attribute"); dpiTestSuite_addCase(dpiTest_2323, "dpiObject_getAttributeValue() with invalid native type"); dpiTestSuite_addCase(dpiTest_2324, "dpiObject_getAttributeValue() with NULL attribute"); dpiTestSuite_addCase(dpiTest_2325, "dpiObject_setAttributeValue() with invalid attribute"); dpiTestSuite_addCase(dpiTest_2326, "dpiObject_setAttributeValue() with invalid native type"); dpiTestSuite_addCase(dpiTest_2327, "dpiObject_appendElement() with NULL attribute"); dpiTestSuite_addCase(dpiTest_2328, "call dpiObject_getElementValueByIndex() and verify the value"); dpiTestSuite_addCase(dpiTest_2329, "call getFirstIndex and getLastIndex and verify the values"); dpiTestSuite_addCase(dpiTest_2330, "call getNextIndex repeatedly and verify Indexes are as expected"); dpiTestSuite_addCase(dpiTest_2331, "call getPrevIndex repeatedly and verify Indexes are as expected"); dpiTestSuite_addCase(dpiTest_2332, "setElement at specific index and verify it is set properly"); dpiTestSuite_addCase(dpiTest_2333, "copy collection object and verify copies are independent"); dpiTestSuite_addCase(dpiTest_2334, "copy object with attributes and verify copies are independent"); dpiTestSuite_addCase(dpiTest_2335, "append object of wrong type to a collection"); dpiTestSuite_addCase(dpiTest_2336, "set object attribute value of wrong type on an object"); dpiTestSuite_addCase(dpiTest_2337, "set object variable value with wrong type"); dpiTestSuite_addCase(dpiTest_2338, "call dpiObject_setElementValueByIndex() with wrong type"); dpiTestSuite_addCase(dpiTest_2339, "call dpiObjectType_createObject() with object type as NULL"); dpiTestSuite_addCase(dpiTest_2340, "test inserts/fetches works with nested collections"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2400_enq_options.c000066400000000000000000000131541510466437300176630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2400_enq_options.c // Test suite for testing all the Enqueue Options related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_2400() // Call dpiConn_newEnqOptions(); call dpiEnqOptions_release() twice (error // DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2400(dpiTestCase *testCase, dpiTestParams *params) { dpiEnqOptions *enqOptions; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); dpiEnqOptions_release(enqOptions); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2401() // Call each of the dpiEnqOptions public functions with the options parameter // set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2401(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiVisibility visibility; uint32_t valueLength; const char *value; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiEnqOptions_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiEnqOptions_getTransformation(NULL, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiEnqOptions_getVisibility(NULL, &visibility); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiEnqOptions_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiEnqOptions_setDeliveryMode(NULL, DPI_MODE_MSG_PERSISTENT); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiEnqOptions_setTransformation(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiEnqOptions_setVisibility(NULL, DPI_VISIBILITY_IMMEDIATE); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2402() // Call dpiConn_newEnqOptions(), call dpiEnqOptions_setVisibility(), // call dpiEnqOptions_getVisibility() and verify that the value returned // matches the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2402(dpiTestCase *testCase, dpiTestParams *params) { dpiVisibility visModes[] = {DPI_VISIBILITY_ON_COMMIT, DPI_VISIBILITY_IMMEDIATE, -1}, getValue; dpiEnqOptions *enqOptions; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; visModes[i] != -1; i++) { if (dpiEnqOptions_setVisibility(enqOptions, visModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_getVisibility(enqOptions, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getValue, visModes[i]) < 0) return DPI_FAILURE; } if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2400); dpiTestSuite_addCase(dpiTest_2400, "call dpiEnqOptions_release() twice"); dpiTestSuite_addCase(dpiTest_2401, "call all dpiEnqOptions functions with options param as NULL"); dpiTestSuite_addCase(dpiTest_2402, "verify visibility is set as expected"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2500_deq_options.c000066400000000000000000000435701510466437300176570ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2500_deq_options.c // Test suite for testing all the Dequeue Options related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_2500() // Call dpiConn_newDeqOptions(); call dpiDeqOptions_release() twice (error // DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2500(dpiTestCase *testCase, dpiTestParams *params) { dpiDeqOptions *deqOptions; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); dpiDeqOptions_release(deqOptions); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2501() // Call each of the dpiDeqOptions public functions with the options parameter // set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2501(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiDeqNavigation navigation; uint32_t valueLength, time; dpiVisibility visibility; const char *value; dpiDeqMode mode; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiDeqOptions_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getCondition(NULL, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getConsumerName(NULL, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getCorrelation(NULL, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getMode(NULL, &mode); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getMsgId(NULL, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getNavigation(NULL, &navigation); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getTransformation(NULL, &value, &valueLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getVisibility(NULL, &visibility); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_getWait(NULL, &time); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setCondition(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setConsumerName(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setCorrelation(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setDeliveryMode(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setMode(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setMsgId(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setNavigation(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setTransformation(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setVisibility(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiDeqOptions_setWait(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2502() // Call dpiConn_newDeqOptions(); call dpiDeqOptions_setNavigation(); call // dpiDeqOptions_getNavigation() and verify that the value returned matches the // value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2502(dpiTestCase *testCase, dpiTestParams *params) { dpiDeqNavigation setValue = DPI_DEQ_NAV_FIRST_MSG, getValue; dpiDeqOptions *deqOptions; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getNavigation(deqOptions, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, getValue, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2503() // call dpiConn_newDeqOptions(); call dpiDeqOptions_setWait(); call // dpiDeqOptions_getWait() and verify that the value returned matches // the value that was set (no error) //----------------------------------------------------------------------------- int dpiTest_2503(dpiTestCase *testCase, dpiTestParams *params) { uint32_t setValue = 4, getValue; dpiDeqOptions *deqOptions; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getWait(deqOptions, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, getValue, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2504() // Call dpiConn_newDeqOptions(); call dpiDeqOptions_setMode(); call // dpiDeqOptions_getMode() and verify that the value returned matches the value // that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2504(dpiTestCase *testCase, dpiTestParams *params) { dpiDeqMode setValue = DPI_MODE_DEQ_BROWSE, getValue; dpiDeqOptions *deqOptions; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setMode(deqOptions, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getMode(deqOptions, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, getValue, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2505() // Call dpiConn_newDeqOptions(); call dpiDeqOptions_setCorrelation(); call // dpiDeqOptions_getCorrelation() and verify that the value returned matches // the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2505(dpiTestCase *testCase, dpiTestParams *params) { const char *setValue = "_", *getValue; dpiDeqOptions *deqOptions; uint32_t getValueLength; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setCorrelation(deqOptions, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getCorrelation(deqOptions, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2506() // Call dpiConn_newDeqOptions(), call dpiDeqOptions_setVisibility(), // call dpiDeqOptions_getVisibility() and verify that the value returned // matches the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2506(dpiTestCase *testCase, dpiTestParams *params) { dpiVisibility visModes[] = {DPI_VISIBILITY_ON_COMMIT, DPI_VISIBILITY_IMMEDIATE, -1}, getValue; dpiDeqOptions *deqOptions; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; visModes[i] != -1; i++) { if (dpiDeqOptions_setVisibility(deqOptions, visModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getVisibility(deqOptions, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getValue, visModes[i]) < 0) return DPI_FAILURE; } if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2507() // Call dpiConn_newDeqOptions(), call dpiDeqOptions_setMsgId(), // call dpiDeqOptions_getMsgId() and verify that the value returned matches // the value that was set (no error) //----------------------------------------------------------------------------- int dpiTest_2507(dpiTestCase *testCase, dpiTestParams *params) { const char *setMsgId = "TEST_MSGID", *getMsgId; dpiDeqOptions *deqOptions; uint32_t getMsgIdLen; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getMsgId(deqOptions, &getMsgId, &getMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getMsgId, getMsgIdLen, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setMsgId(deqOptions, setMsgId, strlen(setMsgId)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getMsgId(deqOptions, &getMsgId, &getMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getMsgId, getMsgIdLen, setMsgId, strlen(setMsgId)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2508() // Call dpiConn_newDeqOptions(), call dpiDeqOptions_setCondition(), // call dpiDeqOptions_getCondition() and verify that the value returned // matches the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2508(dpiTestCase *testCase, dpiTestParams *params) { const char *setCond = "tab.priority between 2 and 4", *getCond; dpiDeqOptions *deqOptions; uint32_t getCondLen; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getCondition(deqOptions, &getCond, &getCondLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getCond, getCondLen, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setCondition(deqOptions, setCond, strlen(setCond)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getCondition(deqOptions, &getCond, &getCondLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getCond, getCondLen, setCond, strlen(setCond)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2509() // Call dpiConn_newDeqOptions(), call dpiDeqOptions_setConsumerName(), // call dpiDeqOptions_getConsumerName() and verify that the value returned // matches the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2509(dpiTestCase *testCase, dpiTestParams *params) { const char *setConsName = "TEST_CONSUMER!", *getConsName; dpiDeqOptions *deqOptions; uint32_t getConsNameLen; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getConsumerName(deqOptions, &getConsName, &getConsNameLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getConsName, getConsNameLen, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setConsumerName(deqOptions, setConsName, strlen(setConsName)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getConsumerName(deqOptions, &getConsName, &getConsNameLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getConsName, getConsNameLen, setConsName, strlen(setConsName)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2500); dpiTestSuite_addCase(dpiTest_2500, "call dpiDeqOptions_release() twice"); dpiTestSuite_addCase(dpiTest_2501, "call all dpiDeqOptions functions with options param as NULL"); dpiTestSuite_addCase(dpiTest_2502, "verify Navigation is set as expected"); dpiTestSuite_addCase(dpiTest_2503, "verify wait time is set as expected"); dpiTestSuite_addCase(dpiTest_2504, "verify mode is set as expected"); dpiTestSuite_addCase(dpiTest_2505, "verify correlation is set as expected"); dpiTestSuite_addCase(dpiTest_2506, "verify visibility mode is set as expected"); dpiTestSuite_addCase(dpiTest_2507, "verify message id is set as expected"); dpiTestSuite_addCase(dpiTest_2508, "verify condition is set as expected"); dpiTestSuite_addCase(dpiTest_2509, "verify consumer name is set as expected"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2600_msg_props.c000066400000000000000000000324561510466437300173460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2600_msg_props.c // Test suite for testing all the Message Properties related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_2600() // Call dpiConn_newMsgProps(); call dpiMsgProps_release() twice (error // DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2600(dpiTestCase *testCase, dpiTestParams *params) { dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); dpiMsgProps_release(msgProps); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2601() // Call each of the dpiMsgProps public functions with the props parameter set // to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2601(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiMsgProps_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getNumAttempts(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getCorrelation(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getDelay(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getDeliveryMode(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getEnqTime(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getExceptionQ(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getExpiration(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getOriginalMsgId(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getPriority(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_getState(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_setCorrelation(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_setDelay(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_setExceptionQ(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_setExpiration(NULL, 2); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_setOriginalMsgId(NULL, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiMsgProps_setPriority(NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2602() // Call dpiConn_newMsgProps(); call dpiMsgProps_setCorrelation(); call // dpiMsgProps_getCorrelation() and verify that the value returned matches // the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2602(dpiTestCase *testCase, dpiTestParams *params) { const char *setValue = "_", *getValue; uint32_t getValueLength; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setCorrelation(msgProps, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getCorrelation(msgProps, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2603() // Call dpiConn_newMsgProps(); call dpiMsgProps_setDelay(); call // dpiMsgProps_getDelay() and verify that the value returned matches the // value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2603(dpiTestCase *testCase, dpiTestParams *params) { int32_t setValue = 5, getValue; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setDelay(msgProps, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getDelay(msgProps, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, getValue, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2604() // Call dpiConn_newMsgProps(); call dpiMsgProps_setExpiration(); call // dpiMsgProps_getExpiration() and verify that the value returned matches the // value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2604(dpiTestCase *testCase, dpiTestParams *params) { int32_t setValue = 8, getValue; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setExpiration(msgProps, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getExpiration(msgProps, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, getValue, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2605() // Call dpiConn_newMsgProps(); call dpiMsgProps_setPriority(); call // dpiMsgProps_getPriority() and verify that the value returned matches the // value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2605(dpiTestCase *testCase, dpiTestParams *params) { int32_t setValue = 2, getValue; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setPriority(msgProps, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getPriority(msgProps, &getValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, getValue, setValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2606() // Call dpiConn_newMsgProps(); call dpiMsgProps_setOriginalMsgId(); call // dpiMsgProps_getOriginalMsgId() and verify that the value returned matches // the value that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2606(dpiTestCase *testCase, dpiTestParams *params) { const char *setValue = "id1", *getValue; uint32_t getValueLength; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setOriginalMsgId(msgProps, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getOriginalMsgId(msgProps, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2607() // call dpiConn_newMsgProps(); call dpiMsgProps_setExceptionQ(); call // dpiMsgProps_getExceptionQ() and verify that the value returned matches // the value that was set (no error) //----------------------------------------------------------------------------- int dpiTest_2607(dpiTestCase *testCase, dpiTestParams *params) { const char *setValue = "excq", *getValue; uint32_t getValueLength; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setExceptionQ(msgProps, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getExceptionQ(msgProps, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, setValue, strlen(setValue)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2600); dpiTestSuite_addCase(dpiTest_2600, "call dpiMsgProps_release() twice"); dpiTestSuite_addCase(dpiTest_2601, "call all dpiMsgProps public functions with props param as NULL"); dpiTestSuite_addCase(dpiTest_2602, "verify correlation is set as expected"); dpiTestSuite_addCase(dpiTest_2603, "verify delay is set as expected"); dpiTestSuite_addCase(dpiTest_2604, "verify expiration is set as expected"); dpiTestSuite_addCase(dpiTest_2605, "verify priority is set as expected"); dpiTestSuite_addCase(dpiTest_2606, "verify msgId is set as expected"); dpiTestSuite_addCase(dpiTest_2607, "verify exceptionQ is set as expected"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2700_aq.c000066400000000000000000001126471510466437300157400ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2700_aq.c // Test suite for testing all the Advanced Queuing related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" #define QUEUE_NAME "BOOK_QUEUE" #define QUEUE_OBJECT_TYPE "UDT_BOOK" #define MAX_ATTEMPTS 10 #define NUM_BOOKS 1 #define NUM_ATTRS 3 struct bookType { char *title; char *authors; double price; }; struct bookType books[NUM_BOOKS] = { { "Oracle Call Interface Programmers Guide", "Oracle", 10.34 } }; //----------------------------------------------------------------------------- // dpiTest__enqObj() [INTERNAL] // Sets attribute values and enqueues the object. //----------------------------------------------------------------------------- int dpiTest__enqObj(dpiTestCase *testCase, dpiObject *bookObj, dpiObjectAttr **attrs, dpiEnqOptions *enqOptions, dpiMsgProps *msgProps, const char **msgId, uint32_t *msgIdLength, dpiConn *conn) { dpiData attrValue; int i; for (i = 0; i < NUM_BOOKS; i++) { dpiData_setBytes(&attrValue, books[i].title, strlen(books[i].title)); if (dpiObject_setAttributeValue(bookObj, attrs[0], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&attrValue, books[i].authors, strlen(books[i].authors)); if (dpiObject_setAttributeValue(bookObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setDouble(&attrValue, books[i].price); if (dpiObject_setAttributeValue(bookObj, attrs[2], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_enqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), enqOptions, msgProps, bookObj, &msgId[i], &msgIdLength[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2700() // Call dpiConn_enqObject(); call dpiConn_deqObject() and verify that the // object that was enqueued matches the object that was dequeued // (separate objects should be used for this test) (no error). //----------------------------------------------------------------------------- int dpiTest_2700(dpiTestCase *testCase, dpiTestParams *params) { uint32_t i, enqMsgIdLength[NUM_BOOKS], deqMsgIdLen; const char *enqMsgId[NUM_BOOKS], *deqMsgId; dpiObjectAttr *attrs[NUM_ATTRS]; dpiObject *enqBook, *deqBook; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiMsgProps *msgProps; dpiData attrValue; dpiConn *conn; // initialization if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); // enqueue objects if (dpiTest__enqObj(testCase, enqBook, attrs, enqOptions, msgProps, enqMsgId, enqMsgIdLength, conn) < 0) return DPI_FAILURE; // dequeue objects if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_BOOKS; i++) { if (dpiConn_deqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, deqBook, &deqMsgId, &deqMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (!deqMsgId) { return dpiTestCase_setFailedFromError(testCase); } if (dpiObject_getAttributeValue(deqBook, attrs[0], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, attrValue.value.asBytes.ptr, attrValue.value.asBytes.length, books[i].title, strlen(books[i].title)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(deqBook, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, attrValue.value.asBytes.ptr, attrValue.value.asBytes.length, books[i].authors, strlen(books[i].authors)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getAttributeValue(deqBook, attrs[2], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, attrValue.value.asDouble, books[i].price) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return DPI_FAILURE; } if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2701() // Call dpiConn_deqObject() on a queue and verify that a call to // dpiMsgProps_getNumAttempts() returns a positive value (no error). //----------------------------------------------------------------------------- int dpiTest_2701(dpiTestCase *testCase, dpiTestParams *params) { uint32_t i, enqMsgIdLength[NUM_BOOKS], deqMsgIdLen; const char *enqMsgId[NUM_BOOKS], *deqMsgId; dpiObjectAttr *attrs[NUM_ATTRS]; dpiObject *enqBook, *deqBook; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiMsgProps *msgProps; int32_t numAttempts; dpiConn *conn; // initialization if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); // enqueue objects if (dpiTest__enqObj(testCase, enqBook, attrs, enqOptions, msgProps, enqMsgId, enqMsgIdLength, conn) < 0) return DPI_FAILURE; // dequeue objects if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_BOOKS; i++) { if (dpiConn_deqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, deqBook, &deqMsgId, &deqMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getNumAttempts(msgProps, &numAttempts) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numAttempts, 0) < 0) return DPI_FAILURE; } // cleanup if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return DPI_FAILURE; } if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2702() // Call dpiConn_deqObject() on a queue and verify that a call to // dpiMsgProps_getEnqTime() returns a consistent value (no error). //----------------------------------------------------------------------------- int dpiTest_2702(dpiTestCase *testCase, dpiTestParams *params) { uint32_t i, enqMsgIdLength[NUM_BOOKS], deqMsgIdLen; const char *enqMsgId[NUM_BOOKS], *deqMsgId; dpiObjectAttr *attrs[NUM_ATTRS]; dpiObject *enqBook, *deqBook; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiTimestamp timestamp; dpiObjectType *objType; dpiMsgProps *msgProps; dpiConn *conn; // initialization if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); // enqueue objects if (dpiTest__enqObj(testCase, enqBook, attrs, enqOptions, msgProps, enqMsgId, enqMsgIdLength, conn) < 0) return DPI_FAILURE; // dequeue objects if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_BOOKS; i++) { if (dpiConn_deqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, deqBook, &deqMsgId, &deqMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getEnqTime(msgProps, ×tamp) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return DPI_FAILURE; } if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2703() // Call dpiConn_deqObject() on an empty queue and verify that the message id // returned is NULL (no error). //----------------------------------------------------------------------------- int dpiTest_2703(dpiTestCase *testCase, dpiTestParams *params) { dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiMsgProps *msgProps; uint32_t msgIdLength; dpiObject *enqBook; const char *msgId; dpiConn *conn; int i; // initialization if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); // dequeue until queue is empty or max attempts has been reached for (i = 0; i < MAX_ATTEMPTS; i++) { if (dpiConn_deqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, enqBook, &msgId, &msgIdLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (!msgId) break; } // at this point we should have a NULL message id if (msgId) return dpiTestCase_setFailed(testCase, "expecting NULL message for empty queue"); // cleanup if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2704() // Call dpiConn_enqObject() and dpiConn_deqObject() on any queue and verify // that the message id returned is correct (no error). //----------------------------------------------------------------------------- int dpiTest_2704(dpiTestCase *testCase, dpiTestParams *params) { uint32_t i, enqMsgIdLen[NUM_BOOKS], deqMsgIdLen; const char *engMsgId[NUM_BOOKS], *deqMsgId; dpiObjectAttr *attrs[NUM_ATTRS]; dpiObject *enqBook, *deqBook; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiMsgProps *msgProps; dpiConn *conn; // initialization if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); // enqueue objects if (dpiTest__enqObj(testCase, enqBook, attrs, enqOptions, msgProps, engMsgId, enqMsgIdLen, conn) < 0) return DPI_FAILURE; // dequeue objects if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_BOOKS; i++) { if (dpiConn_deqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, deqBook, &deqMsgId, &deqMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, deqMsgId, deqMsgIdLen, engMsgId[i], enqMsgIdLen[i]) < 0) return DPI_FAILURE; } // cleanup if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return DPI_FAILURE; } if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2705() // Set each of the properties that can be set on dequeue options and verify // that they are set correctly (no error). //----------------------------------------------------------------------------- int dpiTest_2705(dpiTestCase *testCase, dpiTestParams *params) { const char *condition = "TEST_CONDITION", *consumerName = "TEST_CONSUMER", *correlation = "TEST_CORRELATION", *msgId = "TEST_MSGID"; uint32_t waitModes[] = {DPI_DEQ_WAIT_NO_WAIT, DPI_DEQ_WAIT_FOREVER, 9, -1}; int deqModes[] = {DPI_MODE_DEQ_BROWSE, DPI_MODE_DEQ_LOCKED, DPI_MODE_DEQ_REMOVE, DPI_MODE_DEQ_REMOVE_NO_DATA, 55, -1}; int navModes[] = {DPI_DEQ_NAV_NEXT_TRANSACTION, DPI_DEQ_NAV_FIRST_MSG, DPI_DEQ_NAV_NEXT_MSG, 20, -1}; int visModes[] = {DPI_VISIBILITY_IMMEDIATE, DPI_VISIBILITY_ON_COMMIT, 99, -1}; uint32_t getValueInt, getValueLength; dpiDeqNavigation expNavMode; dpiDeqOptions *deqOptions; dpiVisibility expVisMode; dpiDeqMode expDeqMode; const char *getValue; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; waitModes[i] != -1; i++) { if (dpiDeqOptions_setWait(deqOptions, waitModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getWait(deqOptions, &getValueInt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getValueInt, waitModes[i]) < 0) return DPI_FAILURE; } if (dpiDeqOptions_setCondition(deqOptions, condition, strlen(condition)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getCondition(deqOptions, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, condition, strlen(condition)) < 0) return DPI_FAILURE; if (dpiDeqOptions_setConsumerName(deqOptions, consumerName, strlen(consumerName)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getConsumerName(deqOptions, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, consumerName, strlen(consumerName)) < 0) return DPI_FAILURE; if (dpiDeqOptions_setCorrelation(deqOptions, correlation, strlen(correlation)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getCorrelation(deqOptions, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, correlation, strlen(correlation)) < 0) return DPI_FAILURE; for (i = 0; deqModes[i] != -1; i++) { if (dpiDeqOptions_setMode(deqOptions, deqModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getMode(deqOptions, &expDeqMode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, expDeqMode, deqModes[i]) < 0) return DPI_FAILURE; } if (dpiDeqOptions_setMsgId(deqOptions, msgId, strlen(msgId)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getMsgId(deqOptions, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, msgId, strlen(msgId)) < 0) return DPI_FAILURE; for (i = 0; navModes[i] != -1; i++) { if (dpiDeqOptions_setNavigation(deqOptions, navModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getNavigation(deqOptions, &expNavMode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, expNavMode, navModes[i]) < 0) return DPI_FAILURE; } for (i = 0; visModes[i] != -1; i++) { if (dpiDeqOptions_setVisibility(deqOptions, visModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_getVisibility(deqOptions, &expVisMode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, expVisMode, visModes[i]) < 0) return DPI_FAILURE; } if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2706() // Set each of the properties that can be set on enqueue options and verify // that they are set correctly (no error). //----------------------------------------------------------------------------- int dpiTest_2706(dpiTestCase *testCase, dpiTestParams *params) { int visModes[] = {DPI_VISIBILITY_IMMEDIATE, DPI_VISIBILITY_ON_COMMIT, 99, -1}; dpiEnqOptions *enqOptions; dpiVisibility expVisMode; dpiConn *conn; int i; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; visModes[i] != -1; i++) { if (dpiEnqOptions_setVisibility(enqOptions, visModes[i]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_getVisibility(enqOptions, &expVisMode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, expVisMode, visModes[i]) < 0) return DPI_FAILURE; } if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2707() // Set each of the properties that can be set on message properties and // verify that they are set correctly (no error). //----------------------------------------------------------------------------- int dpiTest_2707(dpiTestCase *testCase, dpiTestParams *params) { const char *correlation = "TEST_CORRELATION"; const char *exceptionq = "TEST_EXCEPTION"; const char *origMsgId = "TEST_ORGMSGID"; uint32_t getValueLength; dpiMsgProps *msgProps; const char *getValue; int32_t getValueInt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_setCorrelation(msgProps, correlation, strlen(correlation)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getCorrelation(msgProps, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, correlation, strlen(correlation)) < 0) return DPI_FAILURE; if (dpiMsgProps_setDelay(msgProps, 10) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getDelay(msgProps, &getValueInt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getValueInt, 10) < 0) return DPI_FAILURE; if (dpiMsgProps_setExceptionQ(msgProps, exceptionq, strlen(exceptionq)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getExceptionQ(msgProps, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, exceptionq, strlen(exceptionq)) < 0) return DPI_FAILURE; if (dpiMsgProps_setExpiration(msgProps, 30) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getExpiration(msgProps, &getValueInt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getValueInt, 30) < 0) return DPI_FAILURE; if (dpiMsgProps_setOriginalMsgId(msgProps, origMsgId, strlen(origMsgId)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getOriginalMsgId(msgProps, &getValue, &getValueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, getValue, getValueLength, origMsgId, strlen(origMsgId)) < 0) return DPI_FAILURE; if (dpiMsgProps_setPriority(msgProps, -4) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getPriority(msgProps, &getValueInt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getValueInt, -4) < 0) return DPI_FAILURE; if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2708() // Set delivery mode to DPI_MODE_MSG_PERSISTENT and verify // dpiMsgProps_getDeliveryMode() returns the expected value (no error). //----------------------------------------------------------------------------- int dpiTest_2708(dpiTestCase *testCase, dpiTestParams *params) { uint32_t enqMsgIdLength[NUM_BOOKS], deqMsgIdLen, i; const char *enqMsgId[NUM_BOOKS], *deqMsgId; dpiMessageDeliveryMode getMsgDelMode; dpiObjectAttr *attrs[NUM_ATTRS]; dpiObject *enqBook, *deqBook; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiMsgProps *msgProps; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newEnqOptions(conn, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newDeqOptions(conn, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_setDeliveryMode(enqOptions, DPI_MODE_MSG_PERSISTENT) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__enqObj(testCase, enqBook, attrs, enqOptions, msgProps, enqMsgId, enqMsgIdLength, conn) < 0) return DPI_FAILURE; if (dpiDeqOptions_setDeliveryMode(deqOptions, DPI_MODE_MSG_PERSISTENT) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_deqObject(conn, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, deqBook, &deqMsgId, &deqMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (!deqMsgId) return dpiTestCase_setFailed(testCase, "no message dequeued!"); if (dpiMsgProps_getDeliveryMode(msgProps, &getMsgDelMode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getMsgDelMode, DPI_MODE_MSG_PERSISTENT) < 0) return DPI_FAILURE; for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2709() // Set delivery mode to DPI_MODE_MSG_BUFFERED and verify // dpiMsgProps_getDeliveryMode() returns the expected value (no error). //----------------------------------------------------------------------------- int dpiTest_2709(dpiTestCase *testCase, dpiTestParams *params) { uint32_t enqMsgIdLength[NUM_BOOKS], deqMsgIdLen, i; const char *enqMsgId[NUM_BOOKS], *deqMsgId; dpiMessageDeliveryMode getMsgDelMode; dpiObjectAttr *attrs[NUM_ATTRS]; dpiObject *enqBook, *deqBook; dpiEnqOptions *enqOptions; dpiDeqOptions *deqOptions; dpiConn *conn1, *conn2; dpiObjectType *objType; dpiMsgProps *msgProps; if (dpiTestCase_getConnection(testCase, &conn1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn2) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn1, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newEnqOptions(conn1, &enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn1, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_setVisibility(enqOptions, DPI_VISIBILITY_IMMEDIATE) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_setDeliveryMode(enqOptions, DPI_MODE_MSG_BUFFERED) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__enqObj(testCase, enqBook, attrs, enqOptions, msgProps, enqMsgId, enqMsgIdLength, conn1) < 0) return DPI_FAILURE; if (dpiMsgProps_release(msgProps) < 0) return DPI_FAILURE; if (dpiObjectType_createObject(objType, &deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn2, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newDeqOptions(conn2, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setVisibility(deqOptions, DPI_VISIBILITY_IMMEDIATE) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setDeliveryMode(deqOptions, DPI_MODE_MSG_BUFFERED) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_deqObject(conn2, QUEUE_NAME, strlen(QUEUE_NAME), deqOptions, msgProps, deqBook, &deqMsgId, &deqMsgIdLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (!deqMsgId) return dpiTestCase_setFailed(testCase, "no message dequeued!"); if (dpiMsgProps_getDeliveryMode(msgProps, &getMsgDelMode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, getMsgDelMode, DPI_MODE_MSG_BUFFERED) < 0) return DPI_FAILURE; for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(enqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(deqBook) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiEnqOptions_release(enqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_release(deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn1) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2700); dpiTestSuite_addCase(dpiTest_2700, "dpiConn_enqObject() and dpiConn_deqObject() object attributes"); dpiTestSuite_addCase(dpiTest_2701, "dpiMsgProps_getNumAttempts() after successful dequeue"); dpiTestSuite_addCase(dpiTest_2702, "dpiMsgProps_getEnqTime() after successful dequeue"); dpiTestSuite_addCase(dpiTest_2703, "dpiConn_deqObject() on empty queue"); dpiTestSuite_addCase(dpiTest_2704, "dpiConn_enqObject() and dpiConn_deqObject() message ids"); dpiTestSuite_addCase(dpiTest_2705, "verify properties of dequeue options"); dpiTestSuite_addCase(dpiTest_2706, "verify properties of enque options"); dpiTestSuite_addCase(dpiTest_2707, "verify properties of message options"); dpiTestSuite_addCase(dpiTest_2708, "set delivery mode to DPI_MODE_MSG_PERSISTENT and verify"); dpiTestSuite_addCase(dpiTest_2709, "set delivery mode to DPI_MODE_MSG_BUFFERED and verify"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2800_lobs.c000066400000000000000000001375761510466437300163070ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2800_lobs.c // Test suite for testing all the LOB related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" #define DEFAULT_CHARS "abcdef" #define MAX_CHARS 200 //----------------------------------------------------------------------------- // dpiTest__populateAndGetLobFromTable() [INTERNAL] // Function to insert LOB and select LOB from corresponding LOB tables. //----------------------------------------------------------------------------- int dpiTest__populateAndGetLobFromTable(dpiTestCase *testCase, dpiConn *conn, dpiOracleTypeNum oracleTypeNum, const char *value, uint32_t valueLength, dpiLob **lob) { dpiOracleTypeNum varOracleTypeNum, lobOracleTypeNum; dpiNativeTypeNum nativeTypeNum; dpiData *varData, *tempData; uint32_t bufferRowIndex; const char *lobType; char sql[100]; dpiStmt *stmt; dpiVar *var; int found; // verify type of LOB switch (oracleTypeNum) { case DPI_ORACLE_TYPE_CLOB: lobType = "CLOB"; varOracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; break; case DPI_ORACLE_TYPE_NCLOB: varOracleTypeNum = DPI_ORACLE_TYPE_NVARCHAR; lobType = "NCLOB"; break; case DPI_ORACLE_TYPE_BLOB: varOracleTypeNum = DPI_ORACLE_TYPE_RAW; lobType = "BLOB"; break; default: return dpiTestCase_setFailed(testCase, "invalid LOB type"); } // use default values if none supplied if (!value) { value = DEFAULT_CHARS; valueLength = strlen(value); } // truncate table sprintf(sql, "truncate table Test%ss", lobType); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row into the database sprintf(sql, "insert into Test%ss values (1, :1)", lobType); if (dpiConn_newVar(conn, varOracleTypeNum, DPI_NATIVE_TYPE_BYTES, 1, valueLength, 1, 0, NULL, &var, &varData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(var, 0, value, valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(var) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // perform query sprintf(sql, "select * from Test%ss for update", lobType); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "no rows found"); if (dpiStmt_getQueryValue(stmt, 2, &nativeTypeNum, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); *lob = tempData->value.asLOB; if (dpiLob_addRef(*lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_getType(*lob, &lobOracleTypeNum) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, lobOracleTypeNum, oracleTypeNum) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyLobWithGivenSize() [INTERNAL] // Function to fetch LOB and check their sizes. //----------------------------------------------------------------------------- int dpiTest__verifyLobWithGivenSize(dpiTestCase *testCase, dpiConn *conn, uint32_t lobSize, dpiOracleTypeNum oracleTypeNum) { const char alphaNum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; uint64_t bufferSize, numBytes, i; char *readBuffer, *writeBuffer; dpiLob *lob; // write random set of bytes to a buffer and populate LOB from that buffer writeBuffer = malloc(lobSize); if (!writeBuffer) return dpiTestCase_setFailed(testCase, "Out of memory!"); for (i = 0; i < lobSize; i++) writeBuffer[i] = alphaNum[rand() % (sizeof(alphaNum) - 1)]; if (dpiTest__populateAndGetLobFromTable(testCase, conn, oracleTypeNum, writeBuffer, lobSize, &lob) < 0) return DPI_FAILURE; // read the data from that LOB and verify it matches what was written if (dpiLob_getBufferSize(lob, lobSize, &bufferSize) < 0) return dpiTestCase_setFailedFromError(testCase); readBuffer = malloc(bufferSize); if (!readBuffer) return dpiTestCase_setFailed(testCase, "Out of memory!"); numBytes = bufferSize; if (dpiLob_readBytes(lob, 1, lobSize, readBuffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, readBuffer, numBytes, writeBuffer, lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); free(readBuffer); free(writeBuffer); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2800() // Call dpiConn_newTempLob() for lobType values of DPI_ORACLE_TYPE_CLOB, // DPI_ORACLE_TYPE_BLOB and DPI_ORACLE_TYPE_NCLOB (no error). //----------------------------------------------------------------------------- int dpiTest_2800(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_BLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_NCLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2801() // Call dpiConn_newTempLob() for an invalid lob type value (error DPI-1021). //----------------------------------------------------------------------------- int dpiTest_2801(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_VARCHAR, &lob); return dpiTestCase_expectError(testCase, "DPI-1021"); } //----------------------------------------------------------------------------- // dpiTest_2802() // Call dpiConn_newTempLob() for a valid lob type; call dpiLob_release() // twice (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_2802(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); dpiLob_release(lob); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_2803() // Call dpiConn_newTempLob() for a valid lob type; call dpiLob_close(); call // each of the public LOB functions except dpilob_addRef() and dpiLob_release() // (error DPI-1040). //----------------------------------------------------------------------------- int dpiTest_2803(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1040:"; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_close(lob) < 0) return dpiTestCase_setFailedFromError(testCase); dpiLob_copy(lob, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_getBufferSize(lob, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_getChunkSize(lob, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_getDirectoryAndFileName(lob, NULL, NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_getFileExists(lob, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_getIsResourceOpen(lob, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_getSize(lob, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_openResource(lob); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_closeResource(lob); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_readBytes(lob, 0, 0, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_setDirectoryAndFileName(lob, NULL, 0, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_setFromBytes(lob, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_trim(lob, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiLob_writeBytes(lob, 0, NULL, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2804() // Call dpiConn_newTempLob() for a valid lob type; call // dpiLob_closeResource() (error). //----------------------------------------------------------------------------- int dpiTest_2804(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); dpiLob_closeResource(lob); if (dpiTestCase_expectError(testCase, "ORA-22289:") < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2805() // Call dpiConn_newTempLob() for a valid lob type; call dpiLob_openResource() // (no error). //----------------------------------------------------------------------------- int dpiTest_2805(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_openResource(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2806() // Prepare and execute a select for update statment that returns a LOB and // fetch one of the LOBs; call dpiLob_closeResource() (error). //----------------------------------------------------------------------------- int dpiTest_2806(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_closeResource(lob); if (dpiTestCase_expectError(testCase, "ORA-22289:") < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2807() // Prepare and execute a select for update statment that returns a LOB and // fetch one of the LOBs; call dpiLob_openResource(); call dpiLob_writeBytes() // with any value; call dpiConn_commit() (error). //----------------------------------------------------------------------------- int dpiTest_2807(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_openResource(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_writeBytes(lob, 1, "test", strlen("test")) < 0) return dpiTestCase_setFailedFromError(testCase); dpiConn_commit(conn); if (dpiTestCase_expectError(testCase, "ORA-22297:") < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2808() // Prepare and execute a select for update statment that returns a LOB and // fetch one of the LOBs; call dpiLob_openResource(); call dpiLob_writeBytes() // with any value; call dpiLob_closeResource(); call dpiConn_commit() (no // error). //----------------------------------------------------------------------------- int dpiTest_2808(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_openResource(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_writeBytes(lob, 1, "test", strlen("test")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_closeResource(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2809() // Fetch a CLOB from the database; call dpiLob_getBufferSize() and verify // that the size in bytes returned is a multiple of the maxBytesPerCharacter // value in the connection encoding information structure (no error). //----------------------------------------------------------------------------- int dpiTest_2809(dpiTestCase *testCase, dpiTestParams *params) { uint64_t lobSize, sizeInBytes; dpiEncodingInfo info; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_getSize(lob, &lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_getBufferSize(lob, lobSize, &sizeInBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(conn, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, sizeInBytes, lobSize * info.maxBytesPerCharacter) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2810() // Fetch a NCLOB from the database; call dpiLob_getBufferSize() and verify // that the size in bytes returned is a multiple of the nmaxBytesPerCharacter // value in the connection encoding information structure (no error). //----------------------------------------------------------------------------- int dpiTest_2810(dpiTestCase *testCase, dpiTestParams *params) { uint64_t lobSize, sizeInBytes; dpiEncodingInfo info; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_NCLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_getSize(lob, &lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_getBufferSize(lob, lobSize, &sizeInBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getEncodingInfo(conn, &info) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, sizeInBytes, lobSize * info.nmaxBytesPerCharacter) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2811() // Fetch a BLOB from the database; call dpiLob_getBufferSize() and verify // that the size in bytes returned is identical to the sizeInChars value that // was passed (no error). //----------------------------------------------------------------------------- int dpiTest_2811(dpiTestCase *testCase, dpiTestParams *params) { uint64_t lobSize, sizeInBytes; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_BLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_getSize(lob, &lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_getBufferSize(lob, lobSize, &sizeInBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, sizeInBytes, lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2812() // Fetch a LOB from the database; call dpiLob_getChunkSize() and verify that // the value returned matches the expected value (no error). //----------------------------------------------------------------------------- int dpiTest_2812(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; uint32_t size; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_getChunkSize(lob, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, (16384 - size) & 0xfffffe00, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2813() // Fetch a CLOB, NCLOB or BLOB from the database; call the function // dpiLob_getDirectoryAndFileName() (error). //----------------------------------------------------------------------------- int dpiTest_2813(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; uint32_t directoryAliasLength, fileNameLength; const char *directoryAlias, *fileName; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_getDirectoryAndFileName(lob, &directoryAlias, &directoryAliasLength, &fileName, &fileNameLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_NCLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_getDirectoryAndFileName(lob, &directoryAlias, &directoryAliasLength, &fileName, &fileNameLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_BLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_getDirectoryAndFileName(lob, &directoryAlias, &directoryAliasLength, &fileName, &fileNameLength); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2814() // Fetch a CLOB, NCLOB or BLOB from the database; call the function // dpiLob_getFileExists() (error). //----------------------------------------------------------------------------- int dpiTest_2814(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiConn *conn; dpiLob *lob; int exists; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_getFileExists(lob, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_NCLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_getFileExists(lob, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_BLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_getFileExists(lob, &exists); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2815() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_getIsResourceOpen() and verify that the // value returned is 0; call dpiLob_openResource(); call // dpiLob_getIsResourceOpen() a second time and verify that the value returned // is now 1 (no error). //----------------------------------------------------------------------------- int dpiTest_2815(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; int isOpen; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_getIsResourceOpen(lob, &isOpen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isOpen, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_openResource(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_getIsResourceOpen(lob, &isOpen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isOpen, 1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_closeResource(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2816() // Fetch a LOB from the database; call dpiLob_getSize() and verify that the // value returned matches expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2816(dpiTestCase *testCase, dpiTestParams *params) { uint64_t lobSize; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_getSize(lob, &lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, lobSize, 6) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2817() // Fetch a CLOB, NCLOB or BLOB from the database; call // dpiLob_setDirectoryAndFileName() (error). //----------------------------------------------------------------------------- int dpiTest_2817(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "OCI-22275:"; const char *dirName = "X", *fileName = "garbage.txt"; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_setDirectoryAndFileName(lob, dirName, strlen(dirName), fileName, strlen(fileName)); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_NCLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_setDirectoryAndFileName(lob, dirName, strlen(dirName), fileName, strlen(fileName)); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_BLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_setDirectoryAndFileName(lob, dirName, strlen(dirName), fileName, strlen(fileName)); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2818() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_trim() with a value greater than the // current length of the LOB (error). //----------------------------------------------------------------------------- int dpiTest_2818(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; dpiLob_trim(lob, 30); if (dpiTestCase_expectError(testCase, "ORA-22926:") < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2819() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_trim() with a value smaller than the // current length of the LOB and verify that the new size matches the size // that was set (no error). //----------------------------------------------------------------------------- int dpiTest_2819(dpiTestCase *testCase, dpiTestParams *params) { uint64_t lobSize; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_trim(lob, 3) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_getSize(lob, &lobSize) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, lobSize, 3) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2820() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_writeBytes() with any value; call // dpiLob_copy() and verify that the values in the LOBs are identical; call // dpiLob_writeBytes() on one of the LOBs and verify that the values in the // other LOB is unchanged (no error). //----------------------------------------------------------------------------- int dpiTest_2820(dpiTestCase *testCase, dpiTestParams *params) { char buffer[MAX_CHARS]; dpiLob *lob, *copyLob; uint64_t numBytes; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_writeBytes(lob, 1, "copying", strlen("copying")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_copy(lob, ©Lob) < 0) return dpiTestCase_setFailedFromError(testCase); numBytes = MAX_CHARS; if (dpiLob_readBytes(copyLob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "copying", strlen("copying")) < 0) return DPI_FAILURE; if (dpiLob_writeBytes(copyLob, 1, "Testing", strlen("Testing")) < 0) return dpiTestCase_setFailedFromError(testCase); numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "copying", strlen("copying")) < 0) return DPI_FAILURE; if (dpiLob_release(copyLob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2821() // Fetch a CLOB from the database; call dpiLob_readBytes() at a number of // offsets (beginning, end, somewhere in the middle) and verify that the // data returned matches expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2821(dpiTestCase *testCase, dpiTestParams *params) { char buffer[MAX_CHARS]; uint64_t numBytes; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "abcdef", strlen("abcdef")) < 0) return DPI_FAILURE; numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 3, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "cdef", strlen("cdef")) < 0) return DPI_FAILURE; numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 8, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "", 0) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2822() // Fetch a NCLOB from the database; call dpiLob_readBytes() at a number of // offsets (beginning, end, somewhere in the middle) and verify that the data // returned matches expectations (no error). //----------------------------------------------------------------------------- int dpiTest_2822(dpiTestCase *testCase, dpiTestParams *params) { char buffer[MAX_CHARS]; uint64_t numBytes; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_NCLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "abcdef", strlen("abcdef")) < 0) return DPI_FAILURE; numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 4, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "def", strlen("def")) < 0) return DPI_FAILURE; numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 8, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "", 0) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2823() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_setFromBytes() with a value that is // smaller than the original size of the LOB and verify that the new value // of the LOB is correct (no error) //----------------------------------------------------------------------------- int dpiTest_2823(dpiTestCase *testCase, dpiTestParams *params) { const char *value = "Test"; char buffer[MAX_CHARS]; uint64_t numBytes; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_setFromBytes(lob, value, strlen(value)) < 0) return dpiTestCase_setFailedFromError(testCase); numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, value, strlen(value)) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2824() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_setFromBytes() with a value that is // larger than the original size of the LOB and verify that the new value of // the LOB is correct (no error). //----------------------------------------------------------------------------- int dpiTest_2824(dpiTestCase *testCase, dpiTestParams *params) { const char *value = "a much longer LOB value than previously"; char buffer[MAX_CHARS]; uint64_t numBytes; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_setFromBytes(lob, value, strlen(value)) < 0) return dpiTestCase_setFailedFromError(testCase); numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, value, strlen(value)) < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2825() // Prepare and execute a select for update statement that returns a LOB and // fetch one of the LOBs; call dpiLob_writeBytes() for a number of offsets // (beginning, middle and end of the LOB) and after commiting the transaction // perform a second fetch and verify that the LOB contents match what was // written (no error). //----------------------------------------------------------------------------- int dpiTest_2825(dpiTestCase *testCase, dpiTestParams *params) { char buffer[MAX_CHARS]; uint64_t numBytes; dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateAndGetLobFromTable(testCase, conn, DPI_ORACLE_TYPE_CLOB, NULL, 0, &lob) < 0) return DPI_FAILURE; if (dpiLob_writeBytes(lob, 1, "lob", strlen("lob")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_writeBytes(lob, 4, "test", strlen("test")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_writeBytes(lob, 8, "ing", strlen("ing")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); numBytes = MAX_CHARS; if (dpiLob_readBytes(lob, 1, MAX_CHARS, buffer, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, buffer, numBytes, "lobtesting", strlen("lobtesting")) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2826() // Fetch LOBs (CLOB, NCLOB, BLOB) from the database using a variable with // native type DPI_NATIVE_TYPE_BYTES; verify that the value returned matches // the expected value for each of the below combinations (no error): // LOB of 64K - 1 bytes // LOB of 64K bytes // LOB of 64K + 1 bytes // LOB of 512K bytes // LOB of 512K + 1 bytes // LOB of 1024K bytes // LOB of 1024K + 1 bytes //----------------------------------------------------------------------------- int dpiTest_2826(dpiTestCase *testCase, dpiTestParams *params) { const uint32_t sizes[7] = { 65535, 65536, 65537, 524288, 524289, 1048576, 1048577 }; const dpiOracleTypeNum oracleTypeNums[3] = { DPI_ORACLE_TYPE_CLOB, DPI_ORACLE_TYPE_NCLOB, DPI_ORACLE_TYPE_BLOB }; dpiConn *conn; int i, j; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; for (i = 0; i < 3; i++) { for (j = 0; j < 7; j++) { if (dpiTest__verifyLobWithGivenSize(testCase, conn, sizes[j], oracleTypeNums[i]) < 0) return DPI_FAILURE; } } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2827() // Verify dpiLob_setFromBytes() allows value parameter to be NULL when the // valueLength parameter has the value zero. //----------------------------------------------------------------------------- int dpiTest_2827(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_setFromBytes(lob, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2828() // Verify dpiLob_setFromBytes() does not allow value parameter to be NULL // when the valueLength parameter has a non-zero value. //----------------------------------------------------------------------------- int dpiTest_2828(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn; dpiLob *lob; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newTempLob(conn, DPI_ORACLE_TYPE_CLOB, &lob) < 0) return dpiTestCase_setFailedFromError(testCase); dpiLob_setFromBytes(lob, NULL, 1); if (dpiTestCase_expectError(testCase, "DPI-1053:") < 0) return DPI_FAILURE; if (dpiLob_release(lob) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2800); dpiTestSuite_addCase(dpiTest_2800, "create all types of LOBs"); dpiTestSuite_addCase(dpiTest_2801, "create invalid LOB type"); dpiTestSuite_addCase(dpiTest_2802, "call dpiLob_release() twice"); dpiTestSuite_addCase(dpiTest_2803, "call all LOB public functions after closing the lob"); dpiTestSuite_addCase(dpiTest_2804, "call dpiLob_closeResource on unopened lob"); dpiTestSuite_addCase(dpiTest_2805, "call dpiLob_openResource and verify"); dpiTestSuite_addCase(dpiTest_2806, "fetch a lob and call dpiLob_closeResource"); dpiTestSuite_addCase(dpiTest_2807, "verify commit on a unclosed lob returns error"); dpiTestSuite_addCase(dpiTest_2808, "verify commit on a closed lob"); dpiTestSuite_addCase(dpiTest_2809, "verify getBufferSize on Clob returns the expected value"); dpiTestSuite_addCase(dpiTest_2810, "verify getBufferSize on Nclob returns the expected value"); dpiTestSuite_addCase(dpiTest_2811, "verify getBufferSize on Blob returns the expected value"); dpiTestSuite_addCase(dpiTest_2812, "verify getChunkSize returns the expected value"); dpiTestSuite_addCase(dpiTest_2813, "verify getDirectoryAndFileName func with CLOB, NCLOB, BLOB"); dpiTestSuite_addCase(dpiTest_2814, "verify getFileExists func with CLOB, NCLOB, BLOB"); dpiTestSuite_addCase(dpiTest_2815, "verify dpiLob_getIsResourceOpen works as expected"); dpiTestSuite_addCase(dpiTest_2816, "verify dpiLob_getSize works as expected"); dpiTestSuite_addCase(dpiTest_2817, "verify setDirectoryAndFileName func with CLOB, NCLOB, BLOB"); dpiTestSuite_addCase(dpiTest_2818, "verify trim function with bigger value than existing length"); dpiTestSuite_addCase(dpiTest_2819, "verify trim function with smaller value than existing length"); dpiTestSuite_addCase(dpiTest_2820, "verify dpiLob_copy works as expected "); dpiTestSuite_addCase(dpiTest_2821, "verify readBytes on Clob with diff offsets works as expected"); dpiTestSuite_addCase(dpiTest_2822, "verify readBytes on Nclob with diff offsets works as expected"); dpiTestSuite_addCase(dpiTest_2823, "verify setFromBytes with small value than existing and verify"); dpiTestSuite_addCase(dpiTest_2824, "verify setFromBytes with big value than existing and verify"); dpiTestSuite_addCase(dpiTest_2825, "verify writeBytes on Clob with diff offsets works as expected"); dpiTestSuite_addCase(dpiTest_2826, "verify CLOB, NCLOB, BLOB values with different buffer sizes"); dpiTestSuite_addCase(dpiTest_2827, "dpiLob_setFromBytes() with value NULL and valueLength zero"); dpiTestSuite_addCase(dpiTest_2828, "dpiLob_setFromBytes() with value not NULL and valueLength " "non-zero"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_2900_implicit_results.c000066400000000000000000000144331510466437300207260ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_2900_implicit_results.c // Test suite for testing all the Implicit Results related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" #define SQL_NOIMP_RES "begin null; end;" #define SQL_IMP_RES "declare " \ " c1 sys_refcursor; " \ " c2 sys_refcursor; " \ "begin " \ " " \ " open c1 for " \ " select NumberCol " \ " from TestNumbers " \ " where IntCol between 3 and 4; " \ " " \ " dbms_sql.return_result(c1); " \ " " \ " open c2 for " \ " select NumberCol " \ " from TestNumbers " \ " where IntCol between 7 and 8; " \ " " \ " dbms_sql.return_result(c2); " \ "end;" //----------------------------------------------------------------------------- // dpiTest_2900() // Prepare and execute statement that does not produce implicit results; // call dpiStmt_getImplicitResult() and confirm that NULL is returned (no // error). //----------------------------------------------------------------------------- int dpiTest_2900(dpiTestCase *testCase, dpiTestParams *params) { dpiStmt *stmt, *impResult; uint32_t numQueryColumns; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, SQL_NOIMP_RES, strlen(SQL_NOIMP_RES), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getImplicitResult(stmt, &impResult) < 0) return dpiTestCase_setFailedFromError(testCase); if (impResult) return dpiTestCase_setFailed(testCase, "expected NULL implicit result for query"); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_2901() // Prepare and execute statements that return a varying number of implicit // results and call dpiStmt_getImplicitResult() as many times as are needed // to verify that the expected number of implicit results is returned; // perform fetches from the implicit results and confirm results are // as expected (no error). //----------------------------------------------------------------------------- int dpiTest_2901(dpiTestCase *testCase, dpiTestParams *params) { uint32_t numQueryColumns, bufferRowIndex; double result[4] = {3.75, 5, 8.75, 10}; dpiNativeTypeNum nativeTypeNum; dpiStmt *stmt, *impResult; dpiData *doubleValue; dpiConn *conn; int found, i; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, SQL_IMP_RES, strlen(SQL_IMP_RES), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); i = 0; while (1) { if (dpiStmt_getImplicitResult(stmt, &impResult) < 0) return dpiTestCase_setFailedFromError(testCase); if (!impResult) break; while (1) { if (dpiStmt_fetch(impResult, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) break; if (dpiStmt_getQueryValue(impResult, 1, &nativeTypeNum, &doubleValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, doubleValue->value.asDouble, result[i++]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_release(impResult) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(2900); dpiTestSuite_addCase(dpiTest_2900, "dpiStmt_getImplicitResult() without implicit results"); dpiTestSuite_addCase(dpiTest_2901, "dpiStmt_getImplicitResult() returns expected results"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3000_scroll_cursors.c000066400000000000000000000420641510466437300204020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3000_scroll_cursors.c // Test suite for testing all the Scrollable Cursors related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__populateTable() [INTERNAL] // Populate table with a known set of data. //----------------------------------------------------------------------------- static int dpiTest__populateTable(dpiTestCase *testCase, dpiConn *conn) { const char *truncateSql = "truncate table TestTempTable"; const char *populateSql = "begin " " for i in 1..30 loop " " insert into TestTempTable values (i, 'Test Data ' || i); " " end loop; " "end;"; dpiStmt *stmt; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // populate table with known data if (dpiConn_prepareStmt(conn, 0, populateSql, strlen(populateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifyFetchedRow() [INTERNAL] // Verify that the row fetched from the cursor is the expected row. //----------------------------------------------------------------------------- static int dpiTest__verifyFetchedRow(dpiTestCase *testCase, dpiStmt *stmt, uint64_t expectedValue) { dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; int64_t fetchedValue; dpiData *data; int found; if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (nativeTypeNum == DPI_NATIVE_TYPE_INT64) { fetchedValue = data->value.asInt64; } else { fetchedValue = data->value.asDouble; } return dpiTestCase_expectUintEqual(testCase, fetchedValue, expectedValue); } //----------------------------------------------------------------------------- // dpiTest_3000() // Prepare and execute a non scrollable query; call dpiStmt_scroll() with the // mode parameter set to any value except DPI_MODE_FETCH_NEXT (error // ORA-24391). //----------------------------------------------------------------------------- int dpiTest_3000(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select intcol from TestOrgIndex"; const char *expectedError = "ORA-24391:"; uint32_t numQueryColumns; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_scroll(stmt, DPI_MODE_FETCH_FIRST, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_scroll(stmt, DPI_MODE_FETCH_PRIOR, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_scroll(stmt, DPI_MODE_FETCH_ABSOLUTE, 3, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, 2, 3); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3001() // Prepare and execute scrollable query which returns no rows; call // dpiStmt_scroll() with mode set to DPI_MODE_FETCH_LAST; call dpiStmt_fetch() // and verify that no rows are available; call dpiStmt_scroll() with mode set // to DPI_MODE_FETCH_FIRST; call dpiStmt_fetch() and verify that no rows are // available (no error). //----------------------------------------------------------------------------- int dpiTest_3001(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select IntCol from TestOrgIndex where 1 = 0"; uint32_t bufferRowIndex; dpiStmt *stmt; dpiConn *conn; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_LAST, 0, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (found) return dpiTestCase_setFailed(testCase, "last row should not be found!"); if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_FIRST, 0, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (found) return dpiTestCase_setFailed(testCase, "first row should not be found!"); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3002() // Prepare and execute scrollable query which returns no rows; call // dpiStmt_scroll() with mode set to DPI_MODE_FETCH_ABSOLUTE and offset set to // 1 (error DPI-1027). //----------------------------------------------------------------------------- int dpiTest_3002(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select IntCol from TestOrgIndex where 1 = 0"; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_scroll(stmt, DPI_MODE_FETCH_ABSOLUTE, 1, 0); if (dpiTestCase_expectError(testCase, "DPI-1027:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3003() // Prepare and execute scrollable query; call dpiStmt_scroll() with mode set // to DPI_MODE_FETCH_RELATIVE and offset set to a negative value (error // DPI-1027). //----------------------------------------------------------------------------- int dpiTest_3003(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select intcol from TestOrgIndex"; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, -1, 0); if (dpiTestCase_expectError(testCase, "DPI-1027:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3004() // Prepare and execute scrollable query; call dpiStmt_scroll() with mode set // to DPI_MODE_FETCH_LAST; then call dpiStmt_scroll() with mode set to // DPI_MODE_FETCH_RELATIVE and offset set to a positive value (error DPI-1027). //----------------------------------------------------------------------------- int dpiTest_3004(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select intcol from TestOrgIndex"; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_LAST, 0, 0) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, 2, 0); if (dpiTestCase_expectError(testCase, "DPI-1027:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3005() // prepare and execute scrollable query which returns some rows; call // dpiStmt_scroll() with mode set to DPI_MODE_FETCH_RELATIVE and offset set // to values that exceed the array size (internal fetch required) and that // do not exceed the array size (satisfied by internal buffers) (no error) //----------------------------------------------------------------------------- int dpiTest_3005(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select IntCol from TestTempTable where IntCol < 21 " "order by IntCol"; uint32_t numQueryColumns; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 5) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, 4, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 5) < 0) return DPI_FAILURE; if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, 10, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 15) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3006() // prepare and execute scrollable query; call dpiStmt_scroll() with each // possible mode from the enumeration dpiFetchMode, verifying that both // fetches satisfied by the internal buffers and fetches not satisified by // internal buffers provide the correct results (no error) //----------------------------------------------------------------------------- int dpiTest_3006(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select IntCol from TestTempTable where IntCol < 22 " "order by IntCol"; uint32_t numQueryColumns; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__populateTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_setFetchArraySize(stmt, 5) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_ABSOLUTE, 2, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 2) < 0) return DPI_FAILURE; if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_ABSOLUTE, 15, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 15) < 0) return DPI_FAILURE; if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, 1, 4) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 20) < 0) return DPI_FAILURE; if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_FIRST, 0, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 1) < 0) return DPI_FAILURE; if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_RELATIVE, 10, 10) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 21) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3007() // Prepare and execute scrollable query; scroll to the first row and then // attempt to scroll to the previous row (error DPI-1027). //----------------------------------------------------------------------------- int dpiTest_3007(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select 1 from dual union all select 2 from dual union all select 3 from dual union all select 4 from dual union all select 5 from dual"; uint32_t numQueryColumns; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 1, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, &numQueryColumns) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_scroll(stmt, DPI_MODE_FETCH_FIRST, 0, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyFetchedRow(testCase, stmt, 1) < 0) return DPI_FAILURE; dpiStmt_scroll(stmt, DPI_MODE_FETCH_PRIOR, 0, 0); if (dpiTestCase_expectError(testCase, "DPI-1027:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3000); dpiTestSuite_addCase(dpiTest_3000, "verify non scrollable query with different fetch modes"); dpiTestSuite_addCase(dpiTest_3001, "dpiStmt_scroll() with modes first and last with no rows"); dpiTestSuite_addCase(dpiTest_3002, "dpiStmt_scroll() with absolute mode with no rows"); dpiTestSuite_addCase(dpiTest_3003, "dpiStmt_scroll() with relative mode, negative offset"); dpiTestSuite_addCase(dpiTest_3004, "dpiStmt_scroll() with last mode and then relative mode"); dpiTestSuite_addCase(dpiTest_3005, "dpiStmt_scroll() with relative mode, various offsets"); dpiTestSuite_addCase(dpiTest_3006, "dpiStmt_scroll() with all possible modes"); dpiTestSuite_addCase(dpiTest_3007, "dpiStmt_scroll() with previous mode at first row"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3100_subscriptions.c000066400000000000000000000100341510466437300202240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3100_subscriptions.c // Test suite for testing all the Subscriptions related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_3100() // Call dpiConn_subscribe() with protocol DPI_SUBSCR_PROTO_CALLBACK but // with the callback attribute left NULL (error). //----------------------------------------------------------------------------- int dpiTest_3100(dpiTestCase *testCase, dpiTestParams *params) { dpiCommonCreateParams commonParams; dpiSubscrCreateParams subParams; dpiContext *context; dpiSubscr *subscr; dpiConn *conn; dpiTestSuite_getContext(&context); if (dpiContext_initCommonCreateParams(context, &commonParams) < 0) return dpiTestCase_setFailedFromError(testCase); commonParams.createMode = DPI_MODE_CREATE_EVENTS; if (dpiConn_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, &commonParams, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiContext_initSubscrCreateParams(context, &subParams) < 0) return dpiTestCase_setFailedFromError(testCase); subParams.protocol = DPI_SUBSCR_PROTO_CALLBACK; dpiConn_subscribe(conn, &subParams, &subscr); if (dpiTestCase_expectError(testCase, "ORA-24904:") < 0) return DPI_FAILURE; dpiConn_release(conn); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3101() // Call each of the dpiSubscr public functions with the subscr parameter set // to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_3101(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiSubscr_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSubscr_prepareStmt(NULL, NULL, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSubscr_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3100); dpiTestSuite_addCase(dpiTest_3100, "dpiConn_subscribe() without callback"); dpiTestSuite_addCase(dpiTest_3101, "call all dpiSubscr public functions with subscr param as NULL"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3200_batch_errors.c000066400000000000000000000213111510466437300177730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3200_batch_errors.c // Test suite for testing all the Batch Errors related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" #define NUM_ROWS 3 #define NUM_ERR 2 //----------------------------------------------------------------------------- // dpiTest__prepareInsertWithErrors() // Prepare insert statement for execution with known errors. //----------------------------------------------------------------------------- int dpiTest__prepareInsertWithErrors(dpiTestCase *testCase, dpiConn *conn, dpiStmt **stmt) { const char *stringValues[NUM_ROWS] = { "TEST 1", "TEST 2", "TEST 3" }; const char *sql = "insert into TestTempTable values (:1, :2)"; int64_t intValues[NUM_ROWS] = { 3, 3, 71113434343434 }; dpiData *intColValue, *stringColValue; dpiVar *intColVar, *stringColVar; int i; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, NUM_ROWS, 0, 0, 0, NULL, &intColVar, &intColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(*stmt, 1, intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, NUM_ROWS, 30, 0, 0, NULL, &stringColVar, &stringColValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(*stmt, 2, stringColVar) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < NUM_ROWS; i++) { dpiData_setInt64(&intColValue[i], intValues[i]); if (dpiVar_setFromBytes(stringColVar, i, stringValues[i], strlen(stringValues[i])) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(intColVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(stringColVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__truncateTable() // Truncate test table. //----------------------------------------------------------------------------- int dpiTest__truncateTable(dpiTestCase *testCase, dpiConn *conn) { const char *sql = "truncate table TestTempTable"; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3200() // Prepare array of data to insert that will result in errors (such as // ORA-00001: unique constraint violations and ORA-01438: value larger than // specified precision allowed for this column); call dpiStmt_executeMany() // with mode set to DPI_MODE_EXEC_DEFAULT and confirm that the error returned // matches the first error in the array of data that was prepared. //----------------------------------------------------------------------------- int dpiTest_3200(dpiTestCase *testCase, dpiTestParams *params) { dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiTest__prepareInsertWithErrors(testCase, conn, &stmt) < 0) return DPI_FAILURE; dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, NUM_ROWS); if (dpiTestCase_expectError(testCase, "ORA-00001:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3201() // Prepare array of data to insert that will result in errors. Call // dpiStmt_executeMany() with mode set to DPI_MODE_EXEC_BATCH_ERRORS; call // dpiStmt_getBatchErrorCount() and confirm the count returned matches the // number of errors expected; call dpiStmt_getBatchErrors() and confirm that // the errors and row offsets returned match expectations (no error). //----------------------------------------------------------------------------- int dpiTest_3201(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo[NUM_ERR]; uint32_t count; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiTest__prepareInsertWithErrors(testCase, conn, &stmt) < 0) return DPI_FAILURE; if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_BATCH_ERRORS, NUM_ROWS) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getBatchErrorCount(stmt, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, NUM_ERR) < 0) return DPI_FAILURE; if (dpiStmt_getBatchErrors(stmt, NUM_ERR, errorInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectErrorInfo(testCase, &errorInfo[0], "ORA-01438:") < 0) return DPI_FAILURE; if (dpiTestCase_expectErrorInfo(testCase, &errorInfo[1], "ORA-00001:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3202() // Prepare array of data to insert that will result in errors. Call // dpiStmt_executeMany() with mode set to DPI_MODE_EXEC_BATCH_ERRORS; call // dpiStmt_getBatchErrors() with a value for numErrors that is less than the // number of errors expected (error DPI-1018). //----------------------------------------------------------------------------- int dpiTest_3202(dpiTestCase *testCase, dpiTestParams *params) { dpiErrorInfo errorInfo; dpiStmt *stmt; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiTest__prepareInsertWithErrors(testCase, conn, &stmt) < 0) return DPI_FAILURE; if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_BATCH_ERRORS, NUM_ROWS) < 0) return dpiTestCase_setFailedFromError(testCase); dpiStmt_getBatchErrors(stmt, 1, &errorInfo); if (dpiTestCase_expectError(testCase, "DPI-1018:") < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3200); dpiTestSuite_addCase(dpiTest_3200, "dpiStmt_executeMany() with batch errors"); dpiTestSuite_addCase(dpiTest_3201, "dpiStmt_getBatchErrors() returns expected results"); dpiTestSuite_addCase(dpiTest_3202, "dpiStmt_getBatchErrors() with numErrors less than required"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3300_dml_returning.c000066400000000000000000000624641510466437300202060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3300_dml_returning.c // Test suite for testing all the possible combinations of DML Returning // statements. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__prepareTable() [INTERNAL] // Prepare table for test. This truncates the table and then optionally // populates it with a number of rows. //----------------------------------------------------------------------------- int dpiTest__prepareTable(dpiTestCase *testCase, dpiConn *conn, uint32_t numRows) { const char *truncateSql = "truncate table TestTempTable"; const char *insertSql = "begin " " for i in 1..:count loop " " insert into TestTempTable " " values (i, 'String value ' || i); " " end loop; " "end;"; dpiData tempData; dpiStmt *stmt; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // populate table with some rows, if applicable if (numRows > 0) { if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, numRows); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3300() // Test call to dpiStmt_execute() of a DML returning statement that returns a // single row. //----------------------------------------------------------------------------- int dpiTest_3300(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable " "values (:intIn, :strIn) " "returning IntCol + 4, substr(StringCol, 1, 4) " "into :intOut, :strOut"; dpiData *intData, *strData, tempData; const char *expectedString = "Test"; uint32_t numReturnedRows; dpiVar *intVar, *strVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, 0) < 0) return DPI_FAILURE; // prepare statement to insert row with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // perform binds dpiData_setInt64(&tempData, 1); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&tempData, "Test data", strlen("Test data")); if (dpiStmt_bindValueByPos(stmt, 2, DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 4, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and check return values if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getReturnedData(intVar, 0, &numReturnedRows, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, intData->value.asUint64, 5) < 0) return DPI_FAILURE; if (dpiVar_getReturnedData(strVar, 0, &numReturnedRows, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, strData->value.asBytes.ptr, strData->value.asBytes.length, expectedString, strlen(expectedString)) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3301() // Test call to dpiStmt_execute() of a DML returning statement that returns // no rows. //----------------------------------------------------------------------------- int dpiTest_3301(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "update TestTempTable set StringCol = 'X' " "returning IntCol, StringCol into :intVar, :strVar"; dpiData *intData, *strData; uint32_t numReturnedRows; dpiVar *intVar, *strVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, 0) < 0) return DPI_FAILURE; // prepare statement to update row with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // perform binds if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and check return values if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getReturnedData(intVar, 0, &numReturnedRows, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 0) < 0) return DPI_FAILURE; if (dpiVar_getReturnedData(strVar, 0, &numReturnedRows, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 0) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3302() // Test call to dpiStmt_execute() of a DML returning statement that returns // multiple rows. //----------------------------------------------------------------------------- int dpiTest_3302(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "update TestTempTable set " " IntCol = IntCol + 15, " " StringCol = 'The final value of string ' || to_char(IntCol) " "returning IntCol, StringCol into :intVar, :strVar"; uint32_t numRows = 10, numReturnedRows; dpiData *intData, *strData; dpiVar *intVar, *strVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, numRows) < 0) return DPI_FAILURE; // prepare statement to update row with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // perform binds if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and check return values if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getReturnedData(intVar, 0, &numReturnedRows, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, numRows) < 0) return DPI_FAILURE; if (dpiVar_getReturnedData(strVar, 0, &numReturnedRows, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, numRows) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3303() // Test inserting multiple rows with DML returning of one row for each row // inserted. //----------------------------------------------------------------------------- int dpiTest_3303(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable " "values (:intVal, :strVal) " "returning IntCol + 3, substr(StringCol, 11) " "into :intVar, :strVar"; uint32_t numCols = 4, numRows = 10, i, numReturnedRows; dpiData *colData[4]; dpiVar *colVar[4]; char buffer[30]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, 0) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &colVar[0], &colData[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[1], &colData[1]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &colVar[2], &colData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[3], &colData[3]) < 0) return dpiTestCase_setFailedFromError(testCase); // populate some dummy data for (i = 0; i < numRows; i++) { dpiData_setInt64(&colData[0][i], i + 1); sprintf(buffer, "Test data %d", i + 1); if (dpiVar_setFromBytes(colVar[1], i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } // prepare and bind statement to insert rows with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numCols; i++) { if (dpiStmt_bindByPos(stmt, i + 1, colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // execute and check return values if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numRows; i++) { if (dpiVar_getReturnedData(colVar[2], i, &numReturnedRows, &colData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, colData[2]->value.asUint64, i + 4) < 0) return DPI_FAILURE; if (dpiVar_getReturnedData(colVar[3], i, &numReturnedRows, &colData[3]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 1) < 0) return DPI_FAILURE; sprintf(buffer, "%d", i + 1); if (dpiTestCase_expectStringEqual(testCase, colData[3]->value.asBytes.ptr, colData[3]->value.asBytes.length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; } // cleanup for (i = 0; i < numCols; i++) { if (dpiVar_release(colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3304() // Test updating of multiple rows with DML returning of no rows for each // iteration. //----------------------------------------------------------------------------- int dpiTest_3304(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "update TestTempTable set StringCol = 'X' " "where IntCol = :intVal " "returning IntCol, StringCol into :intVar, :strVar"; uint32_t numCols = 3, numRows = 10, i, numReturnedRows; dpiData *colData[3]; dpiVar *colVar[3]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, numRows) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &colVar[0], &colData[0]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &colVar[1], &colData[1]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 0, 0, NULL, &colVar[2], &colData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare and bind statement to update rows with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numRows; i++) dpiData_setInt64(&colData[0][i], i + 100); for (i = 0; i < numCols; i++) { if (dpiStmt_bindByPos(stmt, i + 1, colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // execute and check return values if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numRows; i++) { if (dpiVar_getReturnedData(colVar[1], i, &numReturnedRows, &colData[1]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 0) < 0) return DPI_FAILURE; if (dpiVar_getReturnedData(colVar[2], i, &numReturnedRows, &colData[2]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 0) < 0) return DPI_FAILURE; } // cleanup for (i = 0; i < numCols; i++) { if (dpiVar_release(colVar[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3305() // Test deleting of multiple rows with DML returning of multiple differing // number of rows for each iteration. //----------------------------------------------------------------------------- int dpiTest_3305(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "delete from TestTempTable " "where IntCol <= :intVal returning IntCol into :intVar"; uint32_t numRows = 3, i, numReturnedRows, intValues[3] = { 3, 8, 10 }; dpiData *intValData, *intVarData; dpiVar *intVal, *intVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, 10) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVal, &intValData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare and bind statement to delete rows with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numRows; i++) dpiData_setInt64(&intValData[i], intValues[i]); if (dpiStmt_bindByPos(stmt, 1, intVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); // check first iteration if (dpiVar_getReturnedData(intVar, 0, &numReturnedRows, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 3) < 0) return DPI_FAILURE; for (i = 0; i < 3; i++) { if (dpiTestCase_expectUintEqual(testCase, intVarData[i].value.asUint64, i + 1) < 0) return DPI_FAILURE; } // check second iteration if (dpiVar_getReturnedData(intVar, 1, &numReturnedRows, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 5) < 0) return DPI_FAILURE; for (i = 0; i < 5; i++) { if (dpiTestCase_expectUintEqual(testCase, intVarData[i].value.asUint64, i + 4) < 0) return DPI_FAILURE; } // check third iteration if (dpiVar_getReturnedData(intVar, 2, &numReturnedRows, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 2) < 0) return DPI_FAILURE; for (i = 0; i < 2; i++) { if (dpiTestCase_expectUintEqual(testCase, intVarData[i].value.asUint64, i + 9) < 0) return DPI_FAILURE; } // cleanup if (dpiVar_release(intVal) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3306() // Test deleting multiple rows with DML returning and then attempting to // delete the same rows which should result in no rows being returned. //----------------------------------------------------------------------------- int dpiTest_3306(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "delete from TestTempTable " "where IntCol <= :intVal returning IntCol into :intVar"; dpiData *intVarData, tempData; uint32_t numReturnedRows; dpiVar *intVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare table for use if (dpiTest__prepareTable(testCase, conn, 10) < 0) return DPI_FAILURE; // prepare statement to perform delete with DML returning if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // perform binds dpiData_setInt64(&tempData, 4); if (dpiStmt_bindValueByPos(stmt, 1, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &intVar, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and check return values if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getReturnedData(intVar, 0, &numReturnedRows, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 4) < 0) return DPI_FAILURE; // execute statement a second time and check return values if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getReturnedData(intVar, 0, &numReturnedRows, &intVarData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numReturnedRows, 0) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3300); dpiTestSuite_addCase(dpiTest_3300, "verify execute() of statement returning single row"); dpiTestSuite_addCase(dpiTest_3301, "verify execute() of statement returning no rows"); dpiTestSuite_addCase(dpiTest_3302, "verify execute() of statement returning multiple rows"); dpiTestSuite_addCase(dpiTest_3303, "verify executeMany() returning one row per iteration"); dpiTestSuite_addCase(dpiTest_3304, "verify executeMany() returning no rows per iteration"); dpiTestSuite_addCase(dpiTest_3305, "verify executeMany() returning multiple rows per iteration"); dpiTestSuite_addCase(dpiTest_3306, "verify execute() of statement returning multiple, then no rows"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3400_soda_db.c000066400000000000000000000375261510466437300167320ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3400_soda_db.c // Test suite for testing SODA Database (dpiSodaDb) functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__getCollections() // Iterate over the collections found in the database and verify that the // names found match the expected names. //----------------------------------------------------------------------------- int dpiTest__getCollections(dpiTestCase *testCase, dpiSodaDb *db, const char *startName, uint32_t startNameLength, const char **expectedNames, uint32_t expectedNamesLength) { dpiSodaCollCursor *cursor; uint32_t pos, nameLength; dpiSodaColl *coll; const char *name; // create cursor if (dpiSodaDb_getCollections(db, startName, startNameLength, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiTestCase_setFailedFromError(testCase); // iterate over all collections for (pos = 0; pos < expectedNamesLength; pos++) { if (dpiSodaCollCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (!coll) return dpiTestCase_setFailed(testCase, "too few collections found in the database"); if (dpiSodaColl_getName(coll, &name, &nameLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, name, nameLength, expectedNames[pos], strlen(expectedNames[pos])) < 0) return DPI_FAILURE; if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); } // no further collections should be found if (dpiSodaCollCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (coll) return dpiTestCase_setFailed(testCase, "too many collections found in the database"); if (dpiSodaCollCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3400() // Call dpiSodaDb_release() twice and confirm correct error is returned. //----------------------------------------------------------------------------- int dpiTest_3400(dpiTestCase *testCase, dpiTestParams *params) { dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaDb_release(db); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3401() // Verify dpiSodaDb_addRef() works as expected. //----------------------------------------------------------------------------- int dpiTest_3401(dpiTestCase *testCase, dpiTestParams *params) { dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_addRef(db) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaDb_release(db); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3402() // Call all public functions with invalid handle. //----------------------------------------------------------------------------- int dpiTest_3402(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaDb_createCollection(db, NULL, 0, NULL, 0, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDb_createDocument(db, NULL, 0, NULL, 0, NULL, 0, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDb_getCollections(db, NULL, 0, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDb_openCollection(db, NULL, 0, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDb_release(db); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3403() // Create a collection and then attempt to create the collection a second // time. It should open the existing collection without error. //----------------------------------------------------------------------------- int dpiTest_3403(dpiTestCase *testCase, dpiTestParams *params) { const char *name = "ODPIC_COLL_2503", *tempName; uint32_t tempNameLength; dpiSodaColl *coll; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, name, strlen(name), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_getName(coll, &tempName, &tempNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, tempName, tempNameLength, name, strlen(name)) < 0) return DPI_FAILURE; if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); // create SODA collection again if (dpiSodaDb_createCollection(db, name, strlen(name), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_getName(coll, &tempName, &tempNameLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, tempName, tempNameLength, name, strlen(name)) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3404() // Create a bunch of collections and then test various calls to // dpiSodaDb_getCollections() and verify that the correct number of names is // returned. //----------------------------------------------------------------------------- int dpiTest_3404(dpiTestCase *testCase, dpiTestParams *params) { const char *allNames[] = { "ODPIC_COLL_2504_A", "ODPIC_COLL_2504_B", "ODPIC_COLL_2504_C", "ODPIC_COLL_2504_D", "ODPIC_COLL_2504_E", NULL }; dpiSodaColl *coll; const char *name; dpiSodaDb *db; uint32_t i; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // remove all existing collections, if any if (dpiTestCase_dropAllSodaColls(testCase, db) < 0) return DPI_FAILURE; // create the collections in the array for (i = 0; ; i++) { name = allNames[i]; if (!name) break; if (dpiSodaDb_createCollection(db, name, strlen(name), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); } // test iterating over all collections if (dpiTest__getCollections(testCase, db, NULL, 0, allNames, 5) < 0) return DPI_FAILURE; // test iterating over collections from a starting point if (dpiTest__getCollections(testCase, db, allNames[1], strlen(allNames[1]), &allNames[1], 4) < 0) return DPI_FAILURE; if (dpiTest__getCollections(testCase, db, allNames[3], strlen(allNames[3]), &allNames[3], 2) < 0) return DPI_FAILURE; if (dpiTest__getCollections(testCase, db, allNames[4], strlen(allNames[4]), &allNames[4], 1) < 0) return DPI_FAILURE; // test iterating over no collections if (dpiTest__getCollections(testCase, db, "X", 1, allNames, 0) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3405() // Call dpiConn_getSodaDb() twice with the same connection and with different // connections. //----------------------------------------------------------------------------- int dpiTest_3405(dpiTestCase *testCase, dpiTestParams *params) { dpiConn *conn1, *conn2; dpiSodaDb *db1, *db2; // create initial SODA database object (checks client/server versions) if (dpiTestCase_getSodaDb(testCase, &db1) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db1) < 0) return dpiTestCase_setFailedFromError(testCase); // create connections if (dpiTestCase_getConnection(testCase, &conn1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn2) < 0) return DPI_FAILURE; // create two SODA databases on the same connection if (dpiConn_getSodaDb(conn1, &db1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getSodaDb(conn1, &db2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db2) < 0) return dpiTestCase_setFailedFromError(testCase); // create two SODA databases but on different connections if (dpiConn_getSodaDb(conn2, &db1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getSodaDb(conn1, &db2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn1) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3406() // Create document and verify that the content, key and media type were all // saved properly. //----------------------------------------------------------------------------- int dpiTest_3406(dpiTestCase *testCase, dpiTestParams *params) { const char *content = "{\"test\":\"2506\"}", *temp, *encoding; const char *setMediaType = "text/plain", *key = "Key2506"; const char *defaultMediaType = "application/json"; uint32_t tempLength; dpiSodaDoc *doc; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // set content but leave other attributes NULL if (dpiSodaDb_createDocument(db, NULL, 0, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getContent(doc, &temp, &tempLength, &encoding) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, temp, tempLength, content, strlen(content)) < 0) return DPI_FAILURE; if (dpiSodaDoc_getKey(doc, &temp, &tempLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, temp, tempLength, NULL, 0) < 0) return DPI_FAILURE; if (dpiSodaDoc_getMediaType(doc, &temp, &tempLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, temp, tempLength, defaultMediaType, strlen(defaultMediaType)) < 0) return DPI_FAILURE; if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); // set key and media type but not content if (dpiSodaDb_createDocument(db, key, strlen(key), NULL, 0, setMediaType, strlen(setMediaType), DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getContent(doc, &temp, &tempLength, &encoding) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, temp, tempLength, NULL, 0) < 0) return DPI_FAILURE; if (dpiSodaDoc_getKey(doc, &temp, &tempLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, temp, tempLength, key, strlen(key)) < 0) return DPI_FAILURE; if (dpiSodaDoc_getMediaType(doc, &temp, &tempLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, temp, tempLength, setMediaType, strlen(setMediaType)) < 0) return DPI_FAILURE; if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3400); dpiTestSuite_addCase(dpiTest_3400, "dpiSodaDb_release() twice"); dpiTestSuite_addCase(dpiTest_3401, "dpiSodaDb_addRef() with valid parameters"); dpiTestSuite_addCase(dpiTest_3402, "call SODA database functions with NULL handle"); dpiTestSuite_addCase(dpiTest_3403, "dpiSodaDb_createCollection() with valid parameters"); dpiTestSuite_addCase(dpiTest_3404, "dpiSodaDb_getCollections() with valid parameters"); dpiTestSuite_addCase(dpiTest_3405, "dpiConn_getSodaDb() with valid parameters"); dpiTestSuite_addCase(dpiTest_3406, "dpiSodaDb_createDocument() with valid parameters"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3500_soda_coll.c000066400000000000000000001611361510466437300172720ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3500_soda_coll.c // Test suite for testing SODA Collection functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__verifyContent() // Fetch the content of the document and verify it matches the expected // content. //----------------------------------------------------------------------------- int dpiTest__verifyContent(dpiTestCase *testCase, dpiSodaColl *coll, dpiSodaOperOptions *options, const char *expectedContent) { const char *content, *encoding; uint32_t contentLength; dpiSodaDoc *doc; if (dpiSodaColl_findOne(coll, options, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getContent(doc, &content, &contentLength, &encoding) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, content, contentLength, expectedContent, strlen(expectedContent)) < 0) return DPI_FAILURE; if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__countDocuments() // Count the documents found in the collection using a document cursor and // iterating over the cursor. //----------------------------------------------------------------------------- int dpiTest__countDocuments(dpiTestCase *testCase, dpiSodaColl *coll, dpiSodaOperOptions *options, uint64_t expectedCount) { dpiSodaDocCursor *cursor; dpiSodaDoc *doc; uint64_t pos; // create cursor if (dpiSodaColl_find(coll, options, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiTestCase_setFailedFromError(testCase); // iterate over all documents and ensure count matches for (pos = 0; pos < expectedCount; pos++) { if (dpiSodaDocCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (!doc) return dpiTestCase_setFailed(testCase, "too few documents found in the database"); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); } // no further document should be found if (dpiSodaDocCursor_getNext(cursor, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (doc) return dpiTestCase_setFailed(testCase, "too many documents found in the database"); if (dpiSodaDocCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__insertDoc() // Create a document and insert it into the collection. //----------------------------------------------------------------------------- int dpiTest__insertDoc(dpiTestCase *testCase, dpiSodaDb *db, const char *content, dpiSodaColl *coll, dpiSodaDoc **insertedDoc) { dpiSodaDoc *doc; if (dpiSodaDb_createDocument(db, NULL, 0, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_insertOne(coll, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__saveDoc() // Create a document and save it into the collection. //----------------------------------------------------------------------------- int dpiTest__saveDoc(dpiTestCase *testCase, dpiSodaDb *db, const char *key, uint32_t keyLength, const char *content, dpiSodaColl *coll, dpiSodaDoc **savedDoc) { dpiSodaDoc *doc; if (dpiSodaDb_createDocument(db, key, keyLength, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_save(coll, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, savedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__insertManyDocs() // Create a set of documents and insert it into the collection using // dpiSodaColl_insertMany(). Verifies the content if required. //----------------------------------------------------------------------------- int dpiTest__insertManyDocs(dpiTestCase *testCase, dpiSodaDb *db, dpiSodaColl *coll, uint32_t numDocs, const char **content, dpiSodaDoc **insertedDocs) { uint64_t origDocCount, docCount; dpiSodaOperOptions options; dpiContext *context; dpiSodaDoc **docs; uint32_t i; // get original document count if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &origDocCount) < 0) return dpiTestCase_setFailedFromError(testCase); // create documents for each of the contents provided docs = malloc(numDocs * sizeof(dpiSodaDoc*)); if (!docs) return dpiTestCase_setFailed(testCase, "Out of memory!"); for (i = 0; i < numDocs; i++) { if (dpiSodaDb_createDocument(db, NULL, 0, content[i], strlen(content[i]), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &docs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // perform bulk insert if (dpiSodaColl_insertMany(coll, numDocs, docs, DPI_SODA_FLAGS_ATOMIC_COMMIT, insertedDocs) < 0) return dpiTestCase_setFailedFromError(testCase); // clean up created documents for (i = 0; i < numDocs; i++) dpiSodaDoc_release(docs[i]); free(docs); // get document count and verify it matches expectations if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &docCount) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, docCount, origDocCount + numDocs) < 0) return DPI_FAILURE; // if result documents are returned, verify that the contents stored match // what was inserted if (insertedDocs) { // initialize operation options dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); // verify content for each result document returned for (i = 0; i < numDocs; i++) { if (dpiSodaDoc_getKey(insertedDocs[i], &options.key, &options.keyLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifyContent(testCase, coll, &options, content[i]) < 0) return DPI_FAILURE; } } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3500() // Call all public collection functions with NULL handle and verify that the // correct error is returned in each case. //----------------------------------------------------------------------------- int dpiTest_3500(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiSodaColl_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_createIndex(NULL, NULL, 0, DPI_SODA_FLAGS_DEFAULT); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_drop(NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_dropIndex(NULL, NULL, 0, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_find(NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_findOne(NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_getDataGuide(NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_getDocCount(NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_getMetadata(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_getName(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_insertOne(NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_insertMany(NULL, 0, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_remove(NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_replaceOne(NULL, NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_truncate(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaColl_save(NULL, NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3501() // Verify dpiSodaColl_addRef() works as expected. //----------------------------------------------------------------------------- int dpiTest_3501(dpiTestCase *testCase, dpiTestParams *params) { const char *collName = "ODPIC_COLL_2601"; dpiSodaColl *coll; dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_addRef(coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; dpiSodaColl_release(coll); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3502() // Create a document, replace it and verify that it was replaced properly. //----------------------------------------------------------------------------- int dpiTest_3502(dpiTestCase *testCase, dpiTestParams *params) { const char *replaceContent = "{\"test\":\"2602 replaced\"}"; const char *content = "{\"test\":\"2602 original\"}"; const char *collName = "ODPIC_COLL_2602"; dpiSodaDoc *doc, *insertedDoc, *replacedDoc; dpiSodaOperOptions options; dpiContext *context; dpiSodaColl *coll; dpiSodaDb *db; int replaced; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // insert new SODA document if (dpiTest__insertDoc(testCase, db, content, coll, &insertedDoc) < 0) return DPI_FAILURE; // initialize options to find document by key dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getKey(insertedDoc, &options.key, &options.keyLength) < 0) return dpiTestCase_setFailedFromError(testCase); // verify document was stored properly if (dpiTest__verifyContent(testCase, coll, &options, content) < 0) return DPI_FAILURE; // replace document with new content if (dpiSodaDb_createDocument(db, NULL, 0, replaceContent, strlen(replaceContent), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_replaceOne(coll, &options, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, &replaced, &replacedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, replaced, 1) < 0) return DPI_FAILURE; // verify document was replaced properly if (dpiTest__verifyContent(testCase, coll, &options, replaceContent) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDoc_release(insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(replacedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3503() // Create a document, remove it and verify that it was removed properly. //----------------------------------------------------------------------------- int dpiTest_3503(dpiTestCase *testCase, dpiTestParams *params) { const char *content = "{\"test\":\"2603 content\"}"; const char *collName = "ODPIC_COLL_2603"; dpiSodaOperOptions options; dpiSodaDoc *insertedDoc; dpiContext *context; dpiSodaColl *coll; uint64_t numDocs; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // insert new SODA document if (dpiTest__insertDoc(testCase, db, content, coll, &insertedDoc) < 0) return DPI_FAILURE; // initialize options to find document by key dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getKey(insertedDoc, &options.key, &options.keyLength) < 0) return dpiTestCase_setFailedFromError(testCase); // remove document if (dpiSodaColl_remove(coll, &options, DPI_SODA_FLAGS_ATOMIC_COMMIT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 1) < 0) return DPI_FAILURE; // attempt to remove document a second time if (dpiSodaColl_remove(coll, &options, DPI_SODA_FLAGS_ATOMIC_COMMIT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 0) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDoc_release(insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3504() // Create a collection and drop it, then attempt to drop it a second time. // It should not fail but it should indicate that the drop wasn't needed. //----------------------------------------------------------------------------- int dpiTest_3504(dpiTestCase *testCase, dpiTestParams *params) { const char *name = "ODPIC_COLL_2604"; dpiSodaColl *coll; int isDropped; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, name, strlen(name), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // drop collection for the first time if (dpiSodaColl_drop(coll, DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isDropped, 1) < 0) return DPI_FAILURE; // drop collection for the second time if (dpiSodaColl_drop(coll, DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isDropped, 0) < 0) return DPI_FAILURE; // cleanup if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3505() // Create an index and drop it, then attempt to drop it a second time. // It should not fail but it should indicate that the drop wasn't needed. //----------------------------------------------------------------------------- int dpiTest_3505(dpiTestCase *testCase, dpiTestParams *params) { const char *indexSpec = "{'name': 'ODPIC_COLL_2605_IX_1'}"; const char *indexName = "ODPIC_COLL_2605_IX_1"; const char *collName = "ODPIC_COLL_2605"; dpiSodaColl *coll; dpiSodaDb *db; int isDropped; // get SODA database and drop all existing collections if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiTestCase_dropAllSodaColls(testCase, db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // create index if (dpiSodaColl_createIndex(coll, indexSpec, strlen(indexSpec), DPI_SODA_FLAGS_DEFAULT) < 0) return dpiTestCase_setFailedFromError(testCase); // drop index for the first time if (dpiSodaColl_dropIndex(coll, indexName, strlen(indexName), DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isDropped, 1) < 0) return DPI_FAILURE; // drop index for the second time if (dpiSodaColl_dropIndex(coll, indexName, strlen(indexName), DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isDropped, 0) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3506() // Create a collection and populate it with a number of documents, then // perform counts to verify the the right number of documents is being // returned. //----------------------------------------------------------------------------- int dpiTest_3506(dpiTestCase *testCase, dpiTestParams *params) { const char *content = "{\"test\" : \"2606 content\"}"; const char *collName = "ODPIC_COLL_2606"; dpiSodaOperOptions options; dpiSodaDoc *insertedDoc; dpiContext *context; dpiSodaColl *coll; uint64_t numDocs; dpiSodaDb *db; // get SODA database and drop all existing collections if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiTestCase_dropAllSodaColls(testCase, db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // count of empty collection should be zero if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 0) < 0) return DPI_FAILURE; // insert documents and retain key of one of them for later count if (dpiTest__insertDoc(testCase, db, content, coll, &insertedDoc) < 0) return DPI_FAILURE; if (dpiTest__insertDoc(testCase, db, content, coll, NULL) < 0) return DPI_FAILURE; // count should now be 2 if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 2) < 0) return DPI_FAILURE; // perform count with key specified in options dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getKey(insertedDoc, &options.key, &options.keyLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_getDocCount(coll, &options, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 1) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDoc_release(insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3507() // Create a collection, get the name of the collection and verify it is the // same. //----------------------------------------------------------------------------- int dpiTest_3507(dpiTestCase *testCase, dpiTestParams *params) { const char *collName = "ODPIC_COLL_2607"; uint32_t valueLength; const char *value; dpiSodaColl *coll; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // get the name of the collection and verify if (dpiSodaColl_getName(coll, &value, &valueLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, value, valueLength, collName, strlen(collName)) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3508() // Create a collection and get metadata of it. Try to create collection with // existing name and matching metadata and verify it is working. Also create // collection with existing name and non matching metadata and verify it does // not work. //----------------------------------------------------------------------------- int dpiTest_3508(dpiTestCase *testCase, dpiTestParams *params) { const char *collName1 = "ODPIC_COLL_2608_A"; const char *collName2 = "ODPIC_COLL_2608_B"; dpiSodaColl *coll1, *coll2; uint32_t metadataLength; const char *metadata; dpiSodaDb *db; // get SODA database and drop all existing collections if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiTestCase_dropAllSodaColls(testCase, db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName1, strlen(collName1), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll1) < 0) return dpiTestCase_setFailedFromError(testCase); // get metadata of collection and attempt to create with the same value if (dpiSodaColl_getMetadata(coll1, &metadata, &metadataLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDb_createCollection(db, collName1, strlen(collName1), metadata, metadataLength, DPI_SODA_FLAGS_DEFAULT, &coll2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_release(coll2) < 0) return dpiTestCase_setFailedFromError(testCase); // create SODA collection with different name if (dpiSodaDb_createCollection(db, collName2, strlen(collName2), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll2) < 0) return dpiTestCase_setFailedFromError(testCase); // now attempt to create the second SODA collection using the metadata of // the first one; this should fail dpiSodaDb_createCollection(db, collName2, strlen(collName2), metadata, metadataLength, DPI_SODA_FLAGS_DEFAULT, &coll2); if (dpiTestCase_expectError(testCase, "ORA-40669:") < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll1) < 0) return DPI_FAILURE; if (dpiTestCase_cleanupSodaColl(testCase, coll2) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3509() // Insert set of documents into collection, call dpiSodaColl_find() without // specifying options and verify it finds all the documents in the collection. // call dpiSodaColl_find() by specifying options and verify documents that // match with options are only found. //----------------------------------------------------------------------------- int dpiTest_3509(dpiTestCase *testCase, dpiTestParams *params) { const char *content = "{\"test\":\"2609\"}"; const char *collName = "ODPIC_COLL_2609"; dpiSodaDoc **temp, *insertedDoc; dpiSodaOperOptions options; uint32_t i, numDocs = 5; dpiContext *context; dpiSodaColl *coll; dpiSodaDb *db; // get SODA database and drop all existing collections if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiTestCase_dropAllSodaColls(testCase, db) < 0) return DPI_FAILURE; // create SODA collection and verify that no documents exist in it if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__countDocuments(testCase, coll, NULL, 0) < 0) return DPI_FAILURE; // populate collection with some documents; retain only the first document // in order to perform a search by key for (i = 0; i < numDocs; i++) { temp = (i == 0) ? &insertedDoc : NULL; if (dpiTest__insertDoc(testCase, db, content, coll, temp) < 0) return DPI_FAILURE; } if (dpiTest__countDocuments(testCase, coll, NULL, numDocs) < 0) return DPI_FAILURE; // perform a search by key and verify only that document is returned dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getKey(insertedDoc, &options.key, &options.keyLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__countDocuments(testCase, coll, &options, 1) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDoc_release(insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3510() // Try to insert an invalid JSON value into a SODA collection and verify that // it throws an error. //----------------------------------------------------------------------------- int dpiTest_3510(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-02290:", "ORA-40479:", "ORA-40780:", NULL }; const char *content = "{\"test : 2610 content\"}"; const char *collName = "ODPIC_COLL_2610"; dpiSodaColl *coll; dpiSodaDoc *doc; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // insert new SODA document and verify it fails if (dpiSodaDb_createDocument(db, NULL, 0, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaColl_insertOne(coll, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, NULL); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3511() // Insert a set of documents into the collection. Verify that finding, // counting and removing documents works as expected when specifying a set of // keys. //----------------------------------------------------------------------------- int dpiTest_3511(dpiTestCase *testCase, dpiTestParams *params) { uint32_t i, keyLengths[3], numDocs = 5, numKeys = 3; const char *content = "{\"test\":\"2611\"}"; const char *collName = "ODPIC_COLL_2611"; dpiSodaDoc *doc, *retainedDocs[3]; dpiSodaOperOptions options; const char *keys[3]; dpiContext *context; dpiSodaColl *coll; uint64_t count; dpiSodaDb *db; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection and remove any documents that exist in it if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_remove(coll, NULL, DPI_SODA_FLAGS_ATOMIC_COMMIT, &count) < 0) return dpiTestCase_setFailedFromError(testCase); // populate collection with five documents; retain the keys of three of // these documents for further testing for (i = 0; i < numDocs; i++) { if (dpiTest__insertDoc(testCase, db, content, coll, &doc) < 0) return DPI_FAILURE; if (i % 2 == 0) { retainedDocs[i >> 1] = doc; if (dpiSodaDoc_getKey(doc, &keys[i >> 1], &keyLengths[i >> 1]) < 0) return dpiTestCase_setFailedFromError(testCase); } else if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); } // verify that all documents were inserted correctly if (dpiTest__countDocuments(testCase, coll, NULL, numDocs) < 0) return DPI_FAILURE; // populate SODA operation options structure with keys of retained // documents dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); options.numKeys = numKeys; options.keys = keys; options.keyLengths = keyLengths; // verify that iterating with keys works as expected if (dpiTest__countDocuments(testCase, coll, &options, numKeys) < 0) return DPI_FAILURE; // verify that counting with keys works as expected if (dpiSodaColl_getDocCount(coll, &options, DPI_SODA_FLAGS_DEFAULT, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, numKeys) < 0) return DPI_FAILURE; // remove documents and verify if (dpiSodaColl_remove(coll, &options, DPI_SODA_FLAGS_ATOMIC_COMMIT, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, numKeys) < 0) return DPI_FAILURE; // cleanup for (i = 0; i < numKeys; i++) { if (dpiSodaDoc_release(retainedDocs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3512() // Insert a set of documents into a collection. Specify values for skip and // limit in the options structure and verify dpiSodaColl_find() works as // expected. //----------------------------------------------------------------------------- int dpiTest_3512(dpiTestCase *testCase, dpiTestParams *params) { const char *content = "{\"test\":\"2611\"}"; const char *collName = "ODPIC_COLL_2611"; dpiSodaOperOptions options; uint32_t i, numDocs = 50; dpiContext *context; dpiSodaColl *coll; uint64_t count; dpiSodaDb *db; // get SODA database and drop all existing collections if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection and remove any documents that exist in it if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_remove(coll, NULL, DPI_SODA_FLAGS_ATOMIC_COMMIT, &count) < 0) return dpiTestCase_setFailedFromError(testCase); // populate collection with some documents and verify they were all // inserted for (i = 0; i < numDocs; i++) { if (dpiTest__insertDoc(testCase, db, content, coll, NULL) < 0) return DPI_FAILURE; } if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &count) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, count, numDocs) < 0) return DPI_FAILURE; // pass a variety of skip and limit values and verify iteration succeeds dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); options.skip = 15; if (dpiTest__countDocuments(testCase, coll, &options, numDocs - options.skip) < 0) return DPI_FAILURE; options.skip = numDocs; if (dpiTest__countDocuments(testCase, coll, &options, 0) < 0) return DPI_FAILURE; options.skip = 0; options.limit = 20; if (dpiTest__countDocuments(testCase, coll, &options, options.limit) < 0) return DPI_FAILURE; options.skip = 10; options.limit = 5; if (dpiTest__countDocuments(testCase, coll, &options, options.limit) < 0) return DPI_FAILURE; options.skip = 40; options.limit = 20; if (dpiTest__countDocuments(testCase, coll, &options, numDocs - options.skip) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3513() // Create documents with large number of bytes, replace them, remove them // and verify they are working as expected. //----------------------------------------------------------------------------- int dpiTest_3513(dpiTestCase *testCase, dpiTestParams *params) { uint64_t numBytes[5] = {100000, 200000, 400000, 800000, 1048576}; uint64_t numRemoved, numDocs = 5, i, j, lower = 49, upper = 90; const char *initStr = "{\"test\":\"", *termStr = "\"}"; const char *collName = "ODPIC_COLL_2613"; dpiSodaDoc *doc, *insertedDoc, *replacedDoc; uint64_t initStrLength = strlen(initStr); uint64_t termStrLength = strlen(termStr); char *content, *replaceContent; dpiSodaOperOptions options; dpiContext *context; dpiSodaColl *coll; dpiSodaDb *db; int replaced; // initialize content content = malloc(numBytes[numDocs - 1] + 1); replaceContent = malloc(numBytes[numDocs - 1] + 1); if (!content || !replaceContent) return dpiTestCase_setFailed(testCase, "Out of memory!"); strcpy(content, initStr); strcpy(replaceContent, initStr); // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // create documents of varying sizes with random content and ensure that // documents inserted or replaced have the content assigned to them (by // fetching the document after the operation has been completed) dpiTestSuite_getContext(&context); for (i = 0; i < numDocs; i++) { // create buffer with random data for (j = initStrLength; j < numBytes[i] - termStrLength; j++) { content[j] = (rand() % (upper - lower + 1)) + lower; replaceContent[j] = (rand() % (upper - lower + 1)) + lower; } strcpy(&content[numBytes[i] - termStrLength], termStr); strcpy(&replaceContent[numBytes[i] - termStrLength], termStr); // insert new SODA document if (dpiTest__insertDoc(testCase, db, content, coll, &insertedDoc) < 0) return DPI_FAILURE; // initialize options to find document by key if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getKey(insertedDoc, &options.key, &options.keyLength) < 0) return dpiTestCase_setFailedFromError(testCase); // verify document was stored properly if (dpiTest__verifyContent(testCase, coll, &options, content) < 0) return DPI_FAILURE; // replace document with new content if (dpiSodaDb_createDocument(db, NULL, 0, replaceContent, strlen(replaceContent), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_replaceOne(coll, &options, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, &replaced, &replacedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, replaced, 1) < 0) return DPI_FAILURE; // verify document was replaced properly if (dpiTest__verifyContent(testCase, coll, &options, replaceContent) < 0) return DPI_FAILURE; // remove document if (dpiSodaColl_remove(coll, &options, DPI_SODA_FLAGS_ATOMIC_COMMIT, &numRemoved) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numRemoved, 1) < 0) return DPI_FAILURE; // cleanup if (dpiSodaDoc_release(insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(replacedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup free(content); free(replaceContent); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3514() // Verify dpiSodaColl_insertMany() works as expected. Insert a set of docs // and perform counts to verify the right number of documents is being // returned. //----------------------------------------------------------------------------- int dpiTest_3514(dpiTestCase *testCase, dpiTestParams *params) { const char *contents[4] = { "{\"test1\":\"2614 content1\"}", "{\"test2\":\"2614 content2\"}", "{\"test3\":\"2614 content3\"}", "{\"test4\":\"2614 content4\"}" }; const char *collName = "ODPIC_COLL_2614"; dpiSodaDoc **insertedDocs; uint32_t numDocs = 4; uint64_t docCount; dpiSodaColl *coll; dpiSodaDb *db; // get SODA database (Oracle Client 18.5 required for bulk insert) if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 18, 5) < 0) return DPI_FAILURE; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // remove any documents that may already exist due to previous failures if (dpiSodaColl_remove(coll, NULL, DPI_SODA_FLAGS_ATOMIC_COMMIT, &docCount) < 0) return dpiTestCase_setFailedFromError(testCase); // insert documents and verify contents insertedDocs = malloc(numDocs * sizeof(dpiSodaDoc*)); if (!insertedDocs) return dpiTestCase_setFailed(testCase, "Out of memory!"); if (dpiTest__insertManyDocs(testCase, db, coll, numDocs, contents, insertedDocs) < 0) return DPI_FAILURE; free(insertedDocs); // insert documents a second time without verifying contents if (dpiTest__insertManyDocs(testCase, db, coll, numDocs, contents, NULL) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3515() // Try to insert invalid JSON values into a SODA collection using // dpiSodaColl_insertMany() and verify that it throws an error. //----------------------------------------------------------------------------- int dpiTest_3515(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedErrors[] = { "ORA-02290:", "ORA-40479:", "ORA-40780:", NULL }; const char *contents[5] = { "{\"test1\" : \"2615 content1\"}", "{\"test2\" : \"2615 content2\"}", "{\"test3\" : \"2615 content3\"}", "{\"test4 : 2615 content4\"}", "{\"test5\" : \"2615 content5\"}", }; const char *collName = "ODPIC_COLL_2615"; uint32_t i, numDocs = 5; dpiErrorInfo errorInfo; dpiSodaColl *coll; dpiSodaDoc **docs; dpiSodaDb *db; // get SODA database (Oracle Client 18.5 required for bulk insert) // get SODA database if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 18, 5) < 0) return DPI_FAILURE; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // insert SODA documents and verify it fails docs = malloc(numDocs * sizeof(dpiSodaDoc*)); if (!docs) return dpiTestCase_setFailed(testCase, "Out of memory!"); for (i = 0; i < numDocs; i++) { if (dpiSodaDb_createDocument(db, NULL, 0, contents[i], strlen(contents[i]), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &docs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } dpiSodaColl_insertMany(coll, numDocs, docs, DPI_SODA_FLAGS_ATOMIC_COMMIT, NULL); if (dpiTestCase_expectAnyError(testCase, expectedErrors) < 0) return DPI_FAILURE; // verify offset is accurate dpiTestSuite_getErrorInfo(&errorInfo); if (dpiTestCase_expectIntEqual(testCase, errorInfo.offset, 3) < 0) return DPI_FAILURE; // cleanup for (i = 0; i < numDocs; i++) { if (dpiSodaDoc_release(docs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } free(docs); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3516() // Insert a set of documents and perform a count to verify the right number // of documents exists. After that, call dpiSodaColl_truncate() and verify that // all documents have been removed. //----------------------------------------------------------------------------- int dpiTest_3516(dpiTestCase *testCase, dpiTestParams *params) { const char *contents[4] = { "{\"test1\":\"2616 content1\"}", "{\"test2\":\"2616 content2\"}", "{\"test3\":\"2616 content3\"}", "{\"test4\":\"2616 content4\"}" }; const char *collName = "ODPIC_COLL_2616"; uint64_t numDocs = 4; uint64_t docCount; dpiSodaColl *coll; dpiSodaDb *db; // Oracle Client 20.0 required for dpiSodaColl_truncate() if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 20, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // remove any documents that may already exist due to previous failures if (dpiSodaColl_remove(coll, NULL, DPI_SODA_FLAGS_ATOMIC_COMMIT, &docCount) < 0) return dpiTestCase_setFailedFromError(testCase); // insert documents if (dpiTest__insertManyDocs(testCase, db, coll, numDocs, contents, NULL) < 0) return DPI_FAILURE; // count should be 4 if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 4) < 0) return DPI_FAILURE; // truncate if (dpiSodaColl_truncate(coll) < 0) return dpiTestCase_setFailedFromError(testCase); // count should now be 0 if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 0) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3517() // Create a collection and use dpiSodaColl_save() to first create and then // update documents using client-assigned keys. Verify that the right number of // documents exists after each operation. //----------------------------------------------------------------------------- int dpiTest_3517(dpiTestCase *testCase, dpiTestParams *params) { const char *metadata = "{" "\"keyColumn\":" "{" "\"name\": \"ID\"," "\"sqlType\": \"NUMBER\"," "\"assignmentMethod\": \"CLIENT\"" "}" "}"; const char *collName = "ODPIC_COLL_2617", *key1 = "1", *key2 = "2"; const char *content = "{\"test\" : \"2617 content\"}"; dpiSodaColl *coll; uint64_t numDocs; dpiSodaDb *db; // Oracle Client 19.9 required for dpiSodaColl_save() if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 19, 9) < 0) return DPI_FAILURE; // get SODA database and drop all existing collections if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiTestCase_dropAllSodaColls(testCase, db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), metadata, strlen(metadata), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // save document if (dpiTest__saveDoc(testCase, db, key1, strlen(key1), content, coll, NULL) < 0) return DPI_FAILURE; // count should now be 1 if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 1) < 0) return DPI_FAILURE; // save document again if (dpiTest__saveDoc(testCase, db, key1, strlen(key1), content, coll, NULL) < 0) return DPI_FAILURE; // count should still be 1 if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 1) < 0) return DPI_FAILURE; // save another document with a different key if (dpiTest__saveDoc(testCase, db, key2, strlen(key2), content, coll, NULL) < 0) return DPI_FAILURE; // count should now be 2 if (dpiSodaColl_getDocCount(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &numDocs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numDocs, 2) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3518() // Verify fetchArraySize works as expected. Insert a set of docs and perform // counts to verify the right number of documents is being returned. //----------------------------------------------------------------------------- int dpiTest_3518(dpiTestCase *testCase, dpiTestParams *params) { const char *collName = "ODPIC_COLL_2618"; dpiSodaOperOptions options; uint32_t numDocs = 40, i; dpiContext *context; uint64_t docCount; dpiSodaColl *coll; char buffer[100]; dpiSodaDb *db; // get SODA database (Oracle Client 19.5 required for // dpiSodaOperOptions.fetchArraySize) if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 19, 5) < 0) return DPI_FAILURE; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // remove any documents that may already exist due to previous failures if (dpiSodaColl_remove(coll, NULL, DPI_SODA_FLAGS_ATOMIC_COMMIT, &docCount) < 0) return dpiTestCase_setFailedFromError(testCase); // populate collection with some documents for (i = 0; i < numDocs; i++) { sprintf(buffer, "{\"test1\":\"2618 content%d\"}", i+1); if (dpiTest__insertDoc(testCase, db, buffer, coll, NULL) < 0) return DPI_FAILURE; } // set fetchArraySize dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); options.fetchArraySize = numDocs - 10; if (dpiTest__countDocuments(testCase, coll, &options, numDocs) < 0) return DPI_FAILURE; options.fetchArraySize = numDocs + 10; if (dpiTest__countDocuments(testCase, coll, &options, numDocs) < 0) return DPI_FAILURE; options.fetchArraySize = numDocs; if (dpiTest__countDocuments(testCase, coll, &options, numDocs) < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3500); dpiTestSuite_addCase(dpiTest_3500, "call SODA collection functions with NULL handle"); dpiTestSuite_addCase(dpiTest_3501, "dpiSodaColl_addRef() with valid parameters"); dpiTestSuite_addCase(dpiTest_3502, "dpiSodaColl_replaceOne() with valid parameters"); dpiTestSuite_addCase(dpiTest_3503, "dpiSodaColl_remove() with valid parameters"); dpiTestSuite_addCase(dpiTest_3504, "dpiSodaColl_drop() with valid parameters"); dpiTestSuite_addCase(dpiTest_3505, "dpiSodaColl_dropIndex() with valid parameters"); dpiTestSuite_addCase(dpiTest_3506, "dpiSodaColl_getDocCount() with valid parameters"); dpiTestSuite_addCase(dpiTest_3507, "dpiSodaColl_getName() with valid parameters"); dpiTestSuite_addCase(dpiTest_3508, "dpiSodaColl_getMetadata() with valid parameters"); dpiTestSuite_addCase(dpiTest_3509, "dpiSodaColl_find() with valid parameters"); dpiTestSuite_addCase(dpiTest_3510, "dpiSodaColl_insertOne() with invalid JSON"); dpiTestSuite_addCase(dpiTest_3511, "verify find, getDocCount, remove with multiple keys"); dpiTestSuite_addCase(dpiTest_3512, "dpiSodaColl_find() with skip and limit"); dpiTestSuite_addCase(dpiTest_3513, "verify documents with large data"); dpiTestSuite_addCase(dpiTest_3514, "dpiSodaColl_insertMany() with valid parameters"); dpiTestSuite_addCase(dpiTest_3515, "dpiSodaColl_insertMany() with invalid JSON"); dpiTestSuite_addCase(dpiTest_3516, "dpiSodaColl_truncate() with valid parameters"); dpiTestSuite_addCase(dpiTest_3517, "dpiSodaColl_save() with valid parameters"); dpiTestSuite_addCase(dpiTest_3518, "fetch documents with different fetchArraySize options"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3600_soda_coll_cursor.c000066400000000000000000000075051510466437300206670ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3600_soda_coll_cursor.c // Tests suite for testing SODA Collection Cursor Functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_3600() // Call all public collection cursor functions with NULL handle and verify // that the correct error is returned in each case. //----------------------------------------------------------------------------- int dpiTest_3600(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiSodaCollCursor_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaCollCursor_getNext(NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaCollCursor_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3601() // Verify dpiSodaCollCursor_addRef() works as expected. //----------------------------------------------------------------------------- int dpiTest_3601(dpiTestCase *testCase, dpiTestParams *params) { dpiSodaCollCursor *cursor; dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_getCollections(db, NULL, 0, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaCollCursor_addRef(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaCollCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaCollCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaCollCursor_release(cursor); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3600); dpiTestSuite_addCase(dpiTest_3600, "call collection cursor functions with NULL handle"); dpiTestSuite_addCase(dpiTest_3601, "dpiSodaCollCursor_addRef() works with valid parameters"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3700_soda_doc.c000066400000000000000000000226671510466437300171150ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3700_soda_doc.c // Test suite for testing SODA Document Functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_3700() // Call all public document functions with a NULL handle and verify the // expected error is returned. //----------------------------------------------------------------------------- int dpiTest_3700(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiSodaDoc_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_getContent(NULL, NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_getCreatedOn(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_getKey(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_getLastModified(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_getMediaType(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_getVersion(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDoc_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3701() // Verify dpiSodaDoc_addRef() manages reference counts as expected. //----------------------------------------------------------------------------- int dpiTest_3701(dpiTestCase *testCase, dpiTestParams *params) { dpiSodaDoc *doc; dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_createDocument(db, NULL, 0, NULL, 0, NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_addRef(doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaDoc_release(doc); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3702() // Create a document and insert into a collection. Verify document public // functions are working as expected. Also replace the document and verify // version, lastmodified are changed and key, createdon are same as before. //----------------------------------------------------------------------------- int dpiTest_3702(dpiTestCase *testCase, dpiTestParams *params) { uint32_t createdOnLength1, lastModifiedLength1, keyLength1, versionLength1; uint32_t createdOnLength2, lastModifiedLength2, keyLength2, versionLength2; const char *content = "{\"test\":\"2802 original content\"}"; const char *replaceContent = "{\"test\":\"2802 replaced\"}"; const char *createdOn1, *lastModified1, *key1, *version1; const char *createdOn2, *lastModified2, *key2, *version2; dpiSodaDoc *doc, *insertedDoc, *replacedDoc; const char *collName = "ODPIC_COLL_2602"; dpiSodaOperOptions options; dpiContext *context; dpiSodaColl *coll; dpiSodaDb *db; int replaced; // get SODA database if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; // create SODA collection if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); // create a document and insert into collection if (dpiSodaDb_createDocument(db, NULL, 0, content, strlen(content), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_insertOne(coll, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, &insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); // retrieve attributes of inserted document if (dpiSodaDoc_getKey(insertedDoc, &key1, &keyLength1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getVersion(insertedDoc, &version1, &versionLength1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getCreatedOn(insertedDoc, &createdOn1, &createdOnLength1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getLastModified(insertedDoc, &lastModified1, &lastModifiedLength1) < 0) return dpiTestCase_setFailedFromError(testCase); // replace document with new content dpiTestSuite_getContext(&context); if (dpiContext_initSodaOperOptions(context, &options) < 0) return dpiTestCase_setFailedFromError(testCase); options.key = key1; options.keyLength = keyLength1; if (dpiSodaDb_createDocument(db, NULL, 0, replaceContent, strlen(replaceContent), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &doc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_replaceOne(coll, &options, doc, DPI_SODA_FLAGS_ATOMIC_COMMIT, &replaced, &replacedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(doc) < 0) return dpiTestCase_setFailedFromError(testCase); // retrieve attributes of replaced document if (dpiSodaDoc_getKey(replacedDoc, &key2, &keyLength2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getVersion(replacedDoc, &version2, &versionLength2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getCreatedOn(replacedDoc, &createdOn2, &createdOnLength2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_getLastModified(replacedDoc, &lastModified2, &lastModifiedLength2) < 0) return dpiTestCase_setFailedFromError(testCase); // compare results if (dpiTestCase_expectStringEqual(testCase, key2, keyLength2, key1, keyLength1) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, createdOn2, createdOnLength2, createdOn1, createdOnLength1) < 0) return DPI_FAILURE; if (versionLength2 == versionLength1 && strncmp(version2, version1, versionLength1) == 0) return dpiTestCase_setFailed(testCase, "created and replaced document versions are matching"); if (lastModifiedLength2 == lastModifiedLength1 && strncmp(lastModified2, lastModified1, lastModifiedLength1) == 0) return dpiTestCase_setFailed(testCase, "created and replaced document last modified are matching"); // cleanup if (dpiSodaDoc_release(insertedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDoc_release(replacedDoc) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3700); dpiTestSuite_addCase(dpiTest_3700, "verify public document functions with NULL"); dpiTestSuite_addCase(dpiTest_3701, "verify dpiSodaDoc_addRef() works as expected"); dpiTestSuite_addCase(dpiTest_3702, "verify doc functions are working as expected"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3800_soda_doc_cursor.c000066400000000000000000000117551510466437300205070ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2018, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3800_soda_doc_cursor.c // Test suite for testing SODA Document Cursor Functions. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__dropCollection() // Drops the collection and verifies that it was actually dropped. //----------------------------------------------------------------------------- int dpiTest__dropCollection(dpiTestCase *testCase, dpiSodaDb *db, const char *collName) { dpiSodaColl *coll; int isDropped; if (dpiSodaDb_openCollection(db, collName, strlen(collName), DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_drop(coll, DPI_SODA_FLAGS_DEFAULT, &isDropped) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, isDropped, 1) < 0) return DPI_FAILURE; if (dpiSodaColl_release(coll) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3800() // Call all public document cursor functions with NULL argument and verify. //----------------------------------------------------------------------------- int dpiTest_3800(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiSodaDocCursor_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDocCursor_getNext(NULL, DPI_SODA_FLAGS_DEFAULT, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiSodaDocCursor_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3801() // verify dpiSodaDocCursor_addRef() increments the reference count as // expected. //----------------------------------------------------------------------------- int dpiTest_3801(dpiTestCase *testCase, dpiTestParams *params) { const char *collName = "ODPIC_COLL_2901"; dpiSodaDocCursor *cursor; dpiSodaColl *coll; dpiSodaDb *db; if (dpiTestCase_getSodaDb(testCase, &db) < 0) return DPI_FAILURE; if (dpiSodaDb_createCollection(db, collName, strlen(collName), NULL, 0, DPI_SODA_FLAGS_DEFAULT, &coll) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaColl_find(coll, NULL, DPI_SODA_FLAGS_DEFAULT, &cursor) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDocCursor_addRef(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDocCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiSodaDocCursor_release(cursor) < 0) return dpiTestCase_setFailedFromError(testCase); dpiSodaDocCursor_release(cursor); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; // cleanup if (dpiTestCase_cleanupSodaColl(testCase, coll) < 0) return DPI_FAILURE; if (dpiSodaDb_release(db) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3800); dpiTestSuite_addCase(dpiTest_3800, "call all functions with NULL handle"); dpiTestSuite_addCase(dpiTest_3801, "dpiSodaDocCursor_addRef() with valid parameters"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_3900_sess_tags.c000066400000000000000000000357501510466437300173340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_3900_sess_tags.c // Test suite for testing session tagging. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_3900() // Verify that session tagging works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_3900(dpiTestCase *testCase, dpiTestParams *params) { dpiConnCreateParams connParams; dpiContext *context; dpiPool *pool; dpiConn *conn; char tag[20]; uint32_t i; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // acquire all of the possible connections from the pool and then // immediately return them with a different tag for each iteration dpiTestSuite_getContext(&context); if (dpiContext_initConnCreateParams(context, &connParams) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < DPI_TEST_POOL_MAX_SESSIONS; i++) { if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 1) < 0) return DPI_FAILURE; sprintf(tag, "SCHEMA=HR%d", i); if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_RETAG, tag, strlen(tag)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); } // now attempt to find each of those sessions again; each session should // have the requested tag for (i = 0; i < DPI_TEST_POOL_MAX_SESSIONS; i++) { sprintf(tag, "SCHEMA=HR%d", i); connParams.tag = tag; connParams.tagLength = strlen(tag); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 0) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, connParams.outTag, connParams.outTagLength, connParams.tag, connParams.tagLength) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); } // attempt to get a session with a non-existent tag without matchAnyTag // set; it should be a new session and not have any tag connParams.tag = "DOES_NOT_EXIST=1"; connParams.tagLength = strlen(connParams.tag); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 1) < 0) return DPI_FAILURE; if (dpiTestCase_expectStringEqual(testCase, connParams.outTag, connParams.outTagLength, NULL, 0) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // attempt to get a session with a non-existent tag with matchAnyTag set; // it should be an existing session connParams.matchAnyTag = 1; if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 0) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3901() // Specify tag name with invalid format and verify it throws an error // (ORA-24488). //----------------------------------------------------------------------------- int dpiTest_3901(dpiTestCase *testCase, dpiTestParams *params) { char *tag = "INVALID_TAG"; dpiConn *conn; dpiPool *pool; // versions less than 12.2 don't raise an error so skip them if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 1, 12, 2) < 0) return DPI_FAILURE; // create a pool if (dpiTestCase_getPool(testCase, &pool) < 0) return DPI_FAILURE; // acquire a connection from the pool if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); // attempt to tag the connection with an invalid tag dpiConn_close(conn, DPI_MODE_CONN_CLOSE_RETAG, tag, strlen(tag)); if (dpiTestCase_expectError(testCase, "ORA-24488:") < 0) return DPI_FAILURE; // cleanup if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_3902() // Demonstrate how to use a session callback written in PL/SQL. The callback // is invoked whenever the tag requested by the application does not match the // tag associated with the session in the pool. It should be used to set // session state, so that the application can count on known session state, // which allows the application to reduce the number of round trips to the // database. //----------------------------------------------------------------------------- int dpiTest_3902(dpiTestCase *testCase, dpiTestParams *params) { const char *querySql = "select count(*) from PLSQLSessionCallbacks"; const char *truncateSql = "truncate table PLSQLSessionCallbacks"; dpiPoolCreateParams poolParams; dpiConnCreateParams connParams; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiContext *context; dpiConn *conn; dpiPool *pool; dpiStmt *stmt; dpiData *data; int found; // only supported in 12.2 and higher if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 1, 12, 2) < 0) return DPI_FAILURE; // create a pool with a PL/SQL session callback specified dpiTestSuite_getContext(&context); if (dpiContext_initPoolCreateParams(context, &poolParams) < 0) return dpiTestCase_setFailedFromError(testCase); poolParams.minSessions = DPI_TEST_POOL_MIN_SESSIONS; poolParams.maxSessions = DPI_TEST_POOL_MAX_SESSIONS; poolParams.sessionIncrement = DPI_TEST_POOL_SESSION_INCREMENT; poolParams.plsqlFixupCallback = "pkg_SessionCallback.TheCallback"; poolParams.plsqlFixupCallbackLength = strlen(poolParams.plsqlFixupCallback); if (dpiPool_create(context, params->mainUserName, params->mainUserNameLength, params->mainPassword, params->mainPasswordLength, params->connectString, params->connectStringLength, NULL, &poolParams, &pool) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire a connection without specifying a tag; the callback will not be // invoked and no session state is changed if (dpiContext_initConnCreateParams(context, &connParams) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 1) < 0) return DPI_FAILURE; // truncate table logging calls to PL/SQL callback if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire a connection, specifying a tag; since the session returned has // no tag, the callback will be invoked; session state will be changed and // the tag is saved when the connection is closed connParams.tag = "NLS_DATE_FORMAT=SIMPLE"; connParams.tagLength = strlen(connParams.tag); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_RETAG, connParams.tag, connParams.tagLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire session, specifying the same tag; since a session exists in // the pool with this tag, it will be returned and the callback will // not be invoked but the connection will still have the session state // defined previously if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, connParams.outTag, connParams.outTagLength, connParams.tag, connParams.tagLength) < 0) return DPI_FAILURE; if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 0) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire session, specifying a different tag; since no session exists // in the pool with this tag, a new session will be returned and the // callback will be invoked; session state will be changed and the tag is // saved when the connection is closed connParams.tag = "NLS_DATE_FORMAT=FULL;TIME_ZONE=UTC"; connParams.tagLength = strlen(connParams.tag); if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 1) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_RETAG, connParams.tag, connParams.tagLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire session, specifying a different tag but also specifying that a // session with any tag can be acquired from the pool; a session with one // of the previously set tags will be returned and the callback will be // invoked; session state will be changed and the tag is saved when the // connection is closed connParams.tag = "NLS_DATE_FORMAT=FULL;TIME_ZONE=MST"; connParams.tagLength = strlen(connParams.tag); connParams.matchAnyTag = 1; if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, &connParams, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, connParams.outNewSession, 1) < 0) return DPI_FAILURE; if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_RETAG, connParams.tag, connParams.tagLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // acquire session and verify results from PL/SQL session logs if (dpiPool_acquireConnection(pool, NULL, 0, NULL, 0, NULL, &conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, querySql, strlen(querySql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, (uint32_t) data->value.asDouble, 3) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiConn_close(conn, DPI_MODE_CONN_CLOSE_DEFAULT, NULL, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiPool_release(pool) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(3900); dpiTestSuite_addCase(dpiTest_3900, "verify session tagging works as expected"); dpiTestSuite_addCase(dpiTest_3901, "specify invalid tag and verify"); dpiTestSuite_addCase(dpiTest_3902, "verify SessionCallbackPLSQL works as expected"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_4000_queue.c000066400000000000000000000671701510466437300164560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_4000_queue.c // Test suite for testing all the features of AQ queues. //----------------------------------------------------------------------------- #include "TestLib.h" #define RAW_QUEUE_NAME "RAW_QUEUE" #define NUM_MESSAGES 12 #define NUM_BATCH_ENQ 5 #define NUM_BATCH_DEQ 8 #define OBJ_QUEUE_NAME "BOOK_QUEUE" #define QUEUE_OBJECT_TYPE "UDT_BOOK" #define NUM_ATTRS 3 struct bookType { char *title; char *authors; double price; }; //----------------------------------------------------------------------------- // dpiTest__clearQueue() // Dequeue all messages from the queue to ensure that we are starting with // an empty queue. //----------------------------------------------------------------------------- int dpiTest__clearQueue(dpiTestCase *testCase, dpiConn *conn, const char *name, dpiObjectType *objType) { dpiDeqOptions *deqOptions; dpiMsgProps *props; dpiQueue *queue; // create queue if (dpiConn_newQueue(conn, name, strlen(name), objType, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); // get dequeue options from queue and specify that waiting should not be // done for messages if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); // perform dequeue until all messages have been dequeued while (1) { if (dpiQueue_deqOne(queue, &props) < 0) return dpiTestCase_setFailedFromError(testCase); if (!props) break; if (dpiMsgProps_release(props) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4000() // Call each of the dpiQueue public functions with the queue parameter set to // NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4000(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; dpiQueue_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_deqMany(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_deqOne(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_enqMany(NULL, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_enqOne(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_getDeqOptions(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_getEnqOptions(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiQueue_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4001() // Create a queue, then call dpiQueue_release() twice (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4001(dpiTestCase *testCase, dpiTestParams *params) { dpiQueue *queue; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); dpiQueue_release(queue); return dpiTestCase_expectError(testCase, "DPI-1002:"); } //----------------------------------------------------------------------------- // dpiTest_4002() // Create a queue and then call dpiQueue_enqMany() without setting any // payload (error DPI-1070), with the message properties parameter set to NULL // (error DPI-1046) and with the number of properties set to zero (no error). //----------------------------------------------------------------------------- int dpiTest_4002(dpiTestCase *testCase, dpiTestParams *params) { dpiMsgProps *enqProps[NUM_BATCH_ENQ]; dpiQueue *queue; dpiConn *conn; uint32_t i; // create queue if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); // create some message properties to enqueue but don't set any payloads for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiConn_newMsgProps(conn, &enqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // perform various tests dpiQueue_enqMany(queue, NUM_BATCH_ENQ, enqProps); if (dpiTestCase_expectError(testCase, "DPI-1070:") < 0) return DPI_FAILURE; dpiQueue_enqMany(queue, NUM_BATCH_ENQ, NULL); if (dpiTestCase_expectError(testCase, "DPI-1046:") < 0) return DPI_FAILURE; if (dpiQueue_enqMany(queue, 0, enqProps) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiMsgProps_release(enqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4003() // Create a queue and then call dpiQueue_deqMany() on an empty queue // (no error), number of properties set to 0 (error ORA-25327) and with the // different parameters set to NULL (error DPI-1046). //----------------------------------------------------------------------------- int dpiTest_4003(dpiTestCase *testCase, dpiTestParams *params) { dpiMsgProps *deqProps[NUM_BATCH_DEQ]; dpiDeqOptions *deqOptions; uint32_t numMessages; dpiQueue *queue; dpiConn *conn; // create queue; ensure it is cleared so that errors don't cascade if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__clearQueue(testCase, conn, RAW_QUEUE_NAME, NULL) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); // perform various tests numMessages = NUM_BATCH_DEQ; if (dpiQueue_deqMany(queue, &numMessages, deqProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, numMessages, 0) < 0) return DPI_FAILURE; dpiQueue_deqMany(queue, &numMessages, deqProps); if (dpiTestCase_expectError(testCase, "ORA-25327:") < 0) return DPI_FAILURE; dpiQueue_deqMany(queue, NULL, deqProps); if (dpiTestCase_expectError(testCase, "DPI-1046:") < 0) return DPI_FAILURE; dpiQueue_deqMany(queue, &numMessages, NULL); if (dpiTestCase_expectError(testCase, "DPI-1046:") < 0) return DPI_FAILURE; // cleanup if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4004() // Create a queue and then call dpiQueue_enqOne() without setting a payload // (error DPI-1070) and with the different parameters set to NULL (error // DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4004(dpiTestCase *testCase, dpiTestParams *params) { dpiMsgProps *msgProps; dpiQueue *queue; dpiConn *conn; // create queue if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); // perform various tests dpiQueue_enqOne(queue, msgProps); if (dpiTestCase_expectError(testCase, "DPI-1070:") < 0) return DPI_FAILURE; dpiQueue_enqOne(queue, NULL); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; // cleanup if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4005() // Create a queue and then call dpiQueue_deqOne() on an empty queue (no // error) and with the different parameters set to null (error DPI-1046). //----------------------------------------------------------------------------- int dpiTest_4005(dpiTestCase *testCase, dpiTestParams *params) { dpiDeqOptions *deqOptions; dpiMsgProps *props; dpiQueue *queue; dpiConn *conn; // create queue; ensure it is cleared so that errors don't cascade if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__clearQueue(testCase, conn, RAW_QUEUE_NAME, NULL) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); // perform various tests if (dpiQueue_deqOne(queue, &props) < 0) return dpiTestCase_setFailedFromError(testCase); if (props) return dpiTestCase_setFailed(testCase, "dequeue on empty queue should have NULL result"); dpiQueue_deqOne(queue, NULL); if (dpiTestCase_expectError(testCase, "DPI-1046:") < 0) return DPI_FAILURE; // cleanup if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4006() // Create a queue and then enqueue some messages in batches. Verify that the // messages can then be dequeued and match what was enqueued (no error). //----------------------------------------------------------------------------- int dpiTest_4006(dpiTestCase *testCase, dpiTestParams *params) { dpiMsgProps *enqProps[NUM_BATCH_ENQ], *deqProps[NUM_BATCH_DEQ]; uint32_t i, pos, numMessages, payloadLength; const char *payloads[NUM_MESSAGES] = { "The first message", "The second message", "The third message", "The fourth message", "The fifth message", "The sixth message", "The seventh message", "The eighth message", "The ninth message", "The tenth message", "The eleventh message", "The twelfth and final message" }; dpiDeqOptions *deqOptions; const char *payload; dpiQueue *queue; dpiConn *conn; // create queue; ensure it is cleared so that errors don't cascade if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__clearQueue(testCase, conn, RAW_QUEUE_NAME, NULL) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); // create some messages to be used for enqueuing for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiConn_newMsgProps(conn, &enqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // enqueue messages in batches for (i = 0, pos = 0; i < NUM_MESSAGES; i++) { if (dpiMsgProps_setPayloadBytes(enqProps[pos], payloads[i], strlen(payloads[i])) < 0) return dpiTestCase_setFailedFromError(testCase); if (++pos == NUM_BATCH_ENQ || i == NUM_MESSAGES - 1) { if (dpiQueue_enqMany(queue, pos, enqProps) < 0) return dpiTestCase_setFailedFromError(testCase); pos = 0; } } for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiMsgProps_release(enqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); // dequeue messages and verify they match what was enqueued pos = 0; while (1) { numMessages = NUM_BATCH_DEQ; if (dpiQueue_deqMany(queue, &numMessages, deqProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (numMessages == 0) break; for (i = 0; i < numMessages; i++, pos++) { if (dpiMsgProps_getPayload(deqProps[i], NULL, &payload, &payloadLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, payload, payloadLength, payloads[pos], strlen(payloads[pos])) < 0) return DPI_FAILURE; if (dpiMsgProps_release(deqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } } if (dpiTestCase_expectUintEqual(testCase, pos, NUM_MESSAGES) < 0) return DPI_FAILURE; // cleanup if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4007() // Create a queue and then enqueue some objects in batches. Verify that the // objects can then be dequeued and match what was enqueued (no error). //----------------------------------------------------------------------------- int dpiTest_4007(dpiTestCase *testCase, dpiTestParams *params) { dpiMsgProps *enqProps[NUM_BATCH_ENQ], *deqProps[NUM_BATCH_DEQ]; struct bookType books[NUM_MESSAGES] = { { "Oracle Call Interface Programmers Guide", "Oracle", 0 }, { "Oracle Call Interface Programmers Guide 1", "Oracle 1", 1.23 }, { "Oracle Call Interface Programmers Guide 2", "Oracle 2", 2.34 }, { "Oracle Call Interface Programmers Guide 3", "Oracle 3", 3.34 }, { "Oracle Call Interface Programmers Guide 4", "Oracle 4", 4.34 }, { "Oracle Call Interface Programmers Guide 5", "Oracle 5", 5.34 }, { "Oracle Call Interface Programmers Guide 6", "Oracle 6", 6.66 }, { "Oracle Call Interface Programmers Guide 7", "Oracle 7", 7.34 }, { "Oracle Call Interface Programmers Guide 8", "Oracle 8", 8.99 }, { "Oracle Call Interface Programmers Guide 9", "Oracle 9", 9.99 }, { "Oracle Call Interface Programmers Guide 10", "Oracle 10", 10.11 }, { "Selecting Employees", "Scott Tiger", 7.99 } }; dpiObjectAttr *attrs[NUM_ATTRS]; uint32_t i, pos, numMessages; dpiDeqOptions *deqOptions; dpiObjectType *objType; dpiObject *bookObj; dpiData attrValue; dpiQueue *queue; dpiConn *conn; // create queue; ensure it is cleared so that errors don't cascade if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_getObjectType(conn, QUEUE_OBJECT_TYPE, strlen(QUEUE_OBJECT_TYPE), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, NUM_ATTRS, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__clearQueue(testCase, conn, OBJ_QUEUE_NAME, objType) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, OBJ_QUEUE_NAME, strlen(OBJ_QUEUE_NAME), objType, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); // create some messages to be used for enqueuing for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiConn_newMsgProps(conn, &enqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } // enqueue messages in batches for (i = 0, pos = 0; i < NUM_MESSAGES; i++) { // create new object if (dpiObjectType_createObject(objType, &bookObj) < 0) return dpiTestCase_setFailedFromError(testCase); // set title dpiData_setBytes(&attrValue, books[i].title, strlen(books[i].title)); if (dpiObject_setAttributeValue(bookObj, attrs[0], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); // set authors dpiData_setBytes(&attrValue, books[i].authors, strlen(books[i].authors)); if (dpiObject_setAttributeValue(bookObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); // set price dpiData_setDouble(&attrValue, books[i].price); if (dpiObject_setAttributeValue(bookObj, attrs[2], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); // set payload if (dpiMsgProps_setPayloadObject(enqProps[pos], bookObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(bookObj) < 0) return dpiTestCase_setFailedFromError(testCase); // perform enqueue once the batch has been filled or there are no more // messages if (++pos == NUM_BATCH_ENQ || i == NUM_MESSAGES - 1) { if (dpiQueue_enqMany(queue, pos, enqProps) < 0) return dpiTestCase_setFailedFromError(testCase); pos = 0; } } // cleanup enqueue for (i = 0; i < NUM_BATCH_ENQ; i++) { if (dpiMsgProps_release(enqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); // dequeue messages and verify they match what was enqueued pos = 0; while (1) { numMessages = NUM_BATCH_DEQ; if (dpiQueue_deqMany(queue, &numMessages, deqProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (numMessages == 0) break; for (i = 0; i < numMessages; i++, pos++) { // get payload if (dpiMsgProps_getPayload(deqProps[i], &bookObj, NULL, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); // verify title matches if (dpiObject_getAttributeValue(bookObj, attrs[0], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, attrValue.value.asBytes.ptr, attrValue.value.asBytes.length, books[pos].title, strlen(books[pos].title)) < 0) return DPI_FAILURE; // verify authors match if (dpiObject_getAttributeValue(bookObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, attrValue.value.asBytes.ptr, attrValue.value.asBytes.length, books[pos].authors, strlen(books[pos].authors)) < 0) return DPI_FAILURE; // verify price matches if (dpiObject_getAttributeValue(bookObj, attrs[2], DPI_NATIVE_TYPE_DOUBLE, &attrValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, attrValue.value.asDouble, books[pos].price) < 0) return DPI_FAILURE; // cleanup if (dpiMsgProps_release(deqProps[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } } if (dpiTestCase_expectUintEqual(testCase, pos, NUM_MESSAGES) < 0) return DPI_FAILURE; // cleanup for (i = 0; i < NUM_ATTRS; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4008() // Create a queue and then enqueue some messages. Verify that the // message can then be dequeued using msgId(no error). //----------------------------------------------------------------------------- int dpiTest_4008(dpiTestCase *testCase, dpiTestParams *params) { const char *payloads[NUM_MESSAGES] = { "The first message", "The second message", "The third message", "The fourth message", "The fifth message", "The sixth message", "The seventh message", "The eighth message", "The ninth message", "The tenth message", "The eleventh message", "The twelfth and final message" }; dpiDeqOptions *deqOptions; uint32_t payloadLength; dpiMsgProps *msgProps; const char *payload; const char *msg; uint32_t msgLen; dpiQueue *queue; dpiConn *conn; uint32_t i; // connect to database if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__clearQueue(testCase, conn, RAW_QUEUE_NAME, NULL) < 0) return DPI_FAILURE; if (dpiConn_newQueue(conn, RAW_QUEUE_NAME, strlen(RAW_QUEUE_NAME), NULL, &queue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newMsgProps(conn, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); // enqueue messages for (i = 0; i < NUM_MESSAGES; i++) { if (dpiMsgProps_setPayloadBytes(msgProps, payloads[i], strlen(payloads[i])) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiQueue_enqOne(queue, msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiMsgProps_getMsgId(msgProps, &msg, &msgLen) < 0) return dpiTestCase_setFailedFromError(testCase); // get dequeue options from queue and set some options if (dpiQueue_getDeqOptions(queue, &deqOptions) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setNavigation(deqOptions, DPI_DEQ_NAV_FIRST_MSG) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setWait(deqOptions, DPI_DEQ_WAIT_NO_WAIT) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiDeqOptions_setMsgId(deqOptions, msg, msgLen) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiQueue_deqOne(queue, &msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_getPayload(msgProps, NULL, &payload, &payloadLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, payload, payloadLength, payloads[NUM_MESSAGES - 1], strlen(payloads[NUM_MESSAGES - 1])) < 0) return DPI_FAILURE; // cleanup if (dpiQueue_release(queue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiMsgProps_release(msgProps) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(4000); dpiTestSuite_addCase(dpiTest_4000, "call public functions with queue set to NULL"); dpiTestSuite_addCase(dpiTest_4001, "call dpiQueue_release() twice"); dpiTestSuite_addCase(dpiTest_4002, "call dpiQueue_enqMany() with various parameters"); dpiTestSuite_addCase(dpiTest_4003, "call dpiQueue_deqMany() with various parameters"); dpiTestSuite_addCase(dpiTest_4004, "call dpiQueue_enqOne() with various parameters"); dpiTestSuite_addCase(dpiTest_4005, "call dpiQueue_deqOne() with various parameters"); dpiTestSuite_addCase(dpiTest_4006, "bulk dequeue of raw data matches what was enqueued"); dpiTestSuite_addCase(dpiTest_4007, "bulk dequeue of objects matches what was enqueued"); dpiTestSuite_addCase(dpiTest_4008, "verify dequeue by message id"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_4100_binds.c000066400000000000000000003424461510466437300164340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2019, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_4100_binds.c // Test suite for all of the binding related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__bindLobIn() [INTERNAL] // Verify that binding LOBs IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest__bindLobIn(dpiTestCase *testCase, dpiOracleTypeNum oracleTypeNum, const char *lobType, const char *lobStr) { dpiData *returnValue, *lobValue; dpiVar *returnVar, *lobVar; char sql[100]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // generate SQL statement to execute sprintf(sql, "begin :1 := pkg_TestLobs.TestIn%s(:2); end;", lobType); // create variables and populate IN value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, oracleTypeNum, DPI_NATIVE_TYPE_LOB, 1, 0, 0, 0, NULL, &lobVar, &lobValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(lobVar, 0, lobStr, strlen(lobStr)) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, lobVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), strlen(lobStr)) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(lobVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__bindLobInOut() [INTERNAL] // Verify that binding LOBs IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest__bindLobInOut(dpiTestCase *testCase, dpiOracleTypeNum oracleTypeNum, const char *lobType, const char *lobInStr) { char expectedLobValue[200], actualLobValue[200], sql[100]; uint64_t numBytes; dpiData *lobValue; dpiVar *lobVar; dpiStmt *stmt; dpiConn *conn; dpiLob *lob; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // generate SQL statement to execute sprintf(sql, "begin pkg_TestLobs.TestInOut%s(:1); end;", lobType); // create variable and populate it if (dpiConn_newVar(conn, oracleTypeNum, DPI_NATIVE_TYPE_LOB, 1, 0, 0, 0, NULL, &lobVar, &lobValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(lobVar, 0, lobInStr, strlen(lobInStr)) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, lobVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(expectedLobValue, "%s (Modified)", lobInStr); lob = dpiData_getLOB(lobValue); numBytes = sizeof(actualLobValue); if (dpiLob_readBytes(lob, 1, numBytes, actualLobValue, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, actualLobValue, numBytes, expectedLobValue, strlen(expectedLobValue)) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(lobVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__bindLobOut() [INTERNAL] // Verify that binding LOBs OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest__bindLobOut(dpiTestCase *testCase, dpiOracleTypeNum oracleTypeNum, const char *lobType, const char *expectedLobValue) { char actualLobValue[200], sql[100]; uint64_t numBytes; dpiData *lobValue; dpiVar *lobVar; dpiStmt *stmt; dpiConn *conn; dpiLob *lob; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // generate SQL statement to execute sprintf(sql, "begin pkg_TestLobs.TestOut%s(:1); end;", lobType); // create variable if (dpiConn_newVar(conn, oracleTypeNum, DPI_NATIVE_TYPE_LOB, 1, 0, 0, 0, NULL, &lobVar, &lobValue) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, lobVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); lob = dpiData_getLOB(lobValue); numBytes = sizeof(actualLobValue); if (dpiLob_readBytes(lob, 1, numBytes, actualLobValue, &numBytes) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, actualLobValue, numBytes, expectedLobValue, strlen(expectedLobValue)) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(lobVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4100() // Verify that binding unicode (NVARCHAR2) arrays IN work as expected (no // error). //----------------------------------------------------------------------------- int dpiTest_4100(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestUnicodeArrays.TestInArrays(:2, :3); end;"; dpiData *returnValue, *startingLenValue, *arrayValue; dpiVar *returnVar, *startingLenVar, *arrayVar; uint32_t numElements = 278, i; char buffer[300]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &startingLenVar, &startingLenValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, numElements, 100, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(startingLenValue, 65); for (i = 0; i < numElements; i++) { sprintf(buffer, "\xe3\x81\x82 %u", i + 1); if (dpiVar_setFromBytes(arrayVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 1347) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4101() // Verify that binding unicode (NVARCHAR2) arrays IN/OUT work as expected (no // error). //----------------------------------------------------------------------------- int dpiTest_4101(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestUnicodeArrays.TestInOutArrays(:1, :2); end;"; const char *outValueFormat = "Converted element \xe3\x81\x82 # %u originally had length %u"; const char *inValueFormat = "\xe3\x81\x82 in value %u"; uint32_t numElements = 183, numElementsOut, i; dpiData *numElementsValue, *arrayValue; dpiVar *numElementsVar, *arrayVar; char buffer[300]; size_t strLength; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, numElements, 100, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); for (i = 0; i < numElements; i++) { sprintf(buffer, inValueFormat, i + 1); if (dpiVar_setFromBytes(arrayVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // perform execution and verify return values match expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { sprintf(buffer, inValueFormat, i + 1); strLength = strlen(buffer) - 2; sprintf(buffer, outValueFormat, i + 1, strLength); bytes = dpiData_getBytes(&arrayValue[i]); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4102() // Verify that binding unicode (NVARCHAR2) arrays OUT work as expected (no // error). //----------------------------------------------------------------------------- int dpiTest_4102(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestUnicodeArrays.TestOutArrays(:1, :2); end;"; const char *outValueFormat = "Test out element \xe3\x81\x82 # %u"; uint32_t numElements = 207, numElementsOut, i; dpiData *numElementsValue, *arrayValue; dpiVar *numElementsVar, *arrayVar; char buffer[300]; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, numElements, 100, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); if (dpiVar_setNumElementsInArray(arrayVar, 0) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // perform execution and verify return values match expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { sprintf(buffer, outValueFormat, i + 1); bytes = dpiData_getBytes(&arrayValue[i]); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4103() // Verify that binding NUMBER arrays IN work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4103(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestNumberArrays.TestInArrays(:2, :3); end;"; dpiData *returnValue, *startingValue, *arrayValue; dpiVar *returnVar, *startingVar, *arrayVar; uint32_t numElements = 295, i; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &startingVar, &startingValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numElements, 0, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(startingValue, 25); for (i = 0; i < numElements; i++) dpiData_setInt64(&arrayValue[i], i); if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, startingVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 43390) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(startingVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4104() // Verify that binding NUMBER arrays IN/OUT work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4104(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestNumberArrays.TestInOutArrays(:1, :2); end;"; uint32_t numElements = 179, i, numElementsOut; dpiData *numElementsValue, *arrayValue; dpiVar *numElementsVar, *arrayVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numElements, 0, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); for (i = 0; i < numElements; i++) dpiData_setInt64(&arrayValue[i], (i + 1) * 2); if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&arrayValue[i]), (i + 1) * 20) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4105() // Verify that binding NUMBER arrays IN/OUT work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4105(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestNumberArrays.TestOutArrays(:1, :2); end;"; uint32_t numElements = 243, i, numElementsOut; dpiData *numElementsValue, *arrayValue; dpiVar *numElementsVar, *arrayVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numElements, 0, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); if (dpiVar_setNumElementsInArray(arrayVar, 0) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&arrayValue[i]), (i + 1) * 100) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4106() // Verify that binding DATE arrays IN work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4106(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestDateArrays.TestInArrays(:2, :3, :4); end;"; dpiData *returnValue, *startingValue, *baseDateValue, *arrayValue; dpiVar *returnVar, *startingVar, *baseDateVar, *arrayVar; uint32_t numElements = 279, i; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &startingVar, &startingValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, 1, 0, 0, 0, NULL, &baseDateVar, &baseDateValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, numElements, 0, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(startingValue, 10); dpiData_setTimestamp(baseDateValue, 2020, 1, 1, 1, 2, 1, 0, 0, 0); for (i = 0; i < numElements; i++) dpiData_setTimestamp(&arrayValue[i], 2020, i % 12 + 1, 1, 1, 2, 1, 0, 0, 0); if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, startingVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, baseDateVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 4, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 46285) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(startingVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(baseDateVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4107() // Verify that binding DATE arrays IN/OUT work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4107(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestDateArrays.TestInOutArrays(:1, :2); end;"; dpiData *numElementsValue, *arrayValue, temp; uint32_t numElements = 185, i, numElementsOut; dpiVar *numElementsVar, *arrayVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, numElements, 0, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); for (i = 0; i < numElements; i++) dpiData_setTimestamp(&arrayValue[i], 2021, i % 12 + 1, 4, 1, 2, 1, 0, 0, 0); if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { dpiData_setTimestamp(&temp, 2021, i % 12 + 1, 11, 1, 2, 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&arrayValue[i]), dpiData_getTimestamp(&temp)) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4108() // Verify that binding DATE arrays OUT work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4108(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestDateArrays.TestOutArrays(:1, :2); end;"; dpiData *numElementsValue, *arrayValue, temp; uint32_t numElements = 14, i, numElementsOut; dpiVar *numElementsVar, *arrayVar; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_DATE, DPI_NATIVE_TYPE_TIMESTAMP, numElements, 0, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); if (dpiVar_setNumElementsInArray(arrayVar, 0) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { dpiData_setTimestamp(&temp, 2002, 12, i + 13, 0, 0, 0, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&arrayValue[i]), dpiData_getTimestamp(&temp)) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4109() // Verify that binding object arrays IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4109(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestObjectArrays.TestInObjArray(:2, :3); end;"; dpiData *returnValue, *startingLenValue, *arrayValue, tempData; dpiVar *returnVar, *startingLenVar, *arrayVar; const char *elementObjName = "UDT_SUBOBJECT"; const char *arrayObjName = "UDT_OBJECTARRAY"; dpiObjectType *arrayObjType, *elementObjType; dpiObject *arrayObj, *elementObj; uint32_t i, numElements = 10; dpiObjectAttr *attrs[2]; char buffer[300]; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, 2, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create objects if (dpiObjectType_createObject(arrayObjType, &arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(elementObjType, &elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &startingLenVar, &startingLenValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(startingLenValue, numElements); for (i = 0; i < numElements; i++) { dpiData_setDouble(&tempData, i + 1); if (dpiObject_setAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(buffer, "Test Data In %u", i + 1); dpiData_setBytes(&tempData, buffer, strlen(buffer)); if (dpiObject_setAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&tempData, elementObj); if (dpiObject_appendElement(arrayObj, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 206) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < 2; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4110() // Verify that binding object arrays IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4110(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestObjectArrays.TestInOutObjArray(:1, :2); end;"; const char *outValueFormat = "Test in/out element number %u"; const char *inValueFormat = "Test In/Out Data %u"; dpiData *numElementsValue, *arrayValue, tempData; const char *elementObjName = "UDT_SUBOBJECT"; const char *arrayObjName = "UDT_OBJECTARRAY"; dpiObjectType *arrayObjType, *elementObjType; dpiVar *numElementsVar, *arrayVar; dpiObject *arrayObj, *elementObj; uint32_t i, numElements = 8; dpiObjectAttr *attrs[2]; char buffer[300]; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, 2, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create objects if (dpiObjectType_createObject(arrayObjType, &arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(elementObjType, &elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); for (i = 0; i < numElements; i++) { dpiData_setDouble(&tempData, i); if (dpiObject_setAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(buffer, inValueFormat, i + 1); dpiData_setBytes(&tempData, buffer, strlen(buffer)); if (dpiObject_setAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&tempData, elementObj); if (dpiObject_appendElement(arrayObj, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; if (dpiObject_release(arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return values matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); arrayObj = dpiData_getObject(arrayValue); if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; for (i = 0; i < size; i++) { if (dpiObject_getElementValueByIndex(arrayObj, i, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); elementObj = dpiData_getObject(&tempData); if (dpiObject_getAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&tempData), i + 1) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(buffer, outValueFormat, i + 1); bytes = dpiData_getBytes(&tempData); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < 2; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4111() // Verify that binding object arrays OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4111(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestObjectArrays.TestOutObjArray(:1, :2); end;"; const char *outValueFormat = "Test out element number %u"; dpiData *numElementsValue, *arrayValue, tempData; const char *elementObjName = "UDT_SUBOBJECT"; const char *arrayObjName = "UDT_OBJECTARRAY"; dpiObjectType *arrayObjType, *elementObjType; dpiVar *numElementsVar, *arrayVar; dpiObject *arrayObj, *elementObj; uint32_t i, numElements = 7; dpiObjectAttr *attrs[2]; char buffer[300]; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, 2, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return values matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); arrayObj = dpiData_getObject(arrayValue); if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; for (i = 0; i < size; i++) { if (dpiObject_getElementValueByIndex(arrayObj, i, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); elementObj = dpiData_getObject(&tempData); if (dpiObject_getAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_DOUBLE, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, dpiData_getDouble(&tempData), i + 1) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(buffer, outValueFormat, i + 1); bytes = dpiData_getBytes(&tempData); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < 2; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4112() // Verify that binding Number Varray IN work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4112(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestNumberVarrays.TestInArrays(:2, :3); end;"; dpiData *returnValue, *startingLenValue, *arrayValue, tempData; dpiVar *returnVar, *startingLenVar, *arrayVar; const char *objName = "UDT_ARRAY"; uint32_t i, numElements = 9; dpiObjectType *objType; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create object if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &startingLenVar, &startingLenValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(startingLenValue, 10); for (i = 0; i < numElements; i++) { dpiData_setInt64(&tempData, i + 1); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 55) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4113() // Verify that binding Number Varray IN/OUT work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4113(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestNumberVarrays.TestInOutArrays(:1, :2); end;"; dpiData *numElementsValue, *arrayValue, tempData; dpiVar *numElementsVar,*arrayVar; const char *objName = "UDT_ARRAY"; uint32_t i, numElements = 6; dpiObjectType *objType; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create object if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); for (i = 0; i < numElements; i++) { dpiData_setInt64(&tempData, i); if (dpiObject_appendElement(obj, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_getSize(dpiData_getObject(arrayValue), &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; for (i = 0; i < size; i++) { if (dpiObject_getElementValueByIndex(dpiData_getObject(arrayValue), i, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 20) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4114() // Verify that binding Number Varray OUT work as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4114(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestNumberVarrays.TestOutArrays(:1, :2); end;"; dpiData *numElementsValue, *arrayValue, tempData; const char *objName = "UDT_ARRAY"; dpiVar *numElementsVar,*arrayVar; uint32_t i, numElements = 9; dpiObjectType *objType; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object type if (dpiConn_getObjectType(conn, objName, strlen(objName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return values matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); obj = dpiData_getObject(arrayValue); if (dpiObject_getSize(obj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; // compare results for (i = 0; i < size; i++) { if (dpiObject_getElementValueByIndex(obj, i, DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), (i + 1) * 200) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4115() // Verify that binding string (VARCHAR2) arrays IN work as expected (no // error). //----------------------------------------------------------------------------- int dpiTest_4115(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestStringArrays.TestInArrays(:2, :3); end;"; const char alphaNum[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; dpiData *returnValue, *startingLenValue, *arrayValue; dpiVar *returnVar, *startingLenVar, *arrayVar; uint32_t numElements = 2500, i, strSize = 100; char buffer[100]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &startingLenVar, &startingLenValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numElements, strSize, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(startingLenValue, 65); for (i = 0; i < strSize; i++) buffer[i] = alphaNum[rand() % (sizeof(alphaNum) - 1)]; for (i = 0; i < numElements; i++) { if (dpiVar_setFromBytes(arrayVar, i, buffer, strSize) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 3, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 250065) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(startingLenVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4116() // Verify that binding string (VARCHAR2) arrays IN/OUT work as expected (no // error). //----------------------------------------------------------------------------- int dpiTest_4116(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestStringArrays.TestInOutArrays(:1, :2); end;"; const char *outValueFormat = "Converted element # %u originally had length %u"; const char *inValueFormat = "IN String in value %u"; uint32_t numElements = 20000, numElementsOut, i; dpiData *numElementsValue, *arrayValue; dpiVar *numElementsVar, *arrayVar; char buffer[300]; size_t strLength; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numElements, 100, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); for (i = 0; i < numElements; i++) { sprintf(buffer, inValueFormat, i + 1); if (dpiVar_setFromBytes(arrayVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setNumElementsInArray(arrayVar, numElements) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // perform execution and verify return values match expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { sprintf(buffer, inValueFormat, i + 1); strLength = strlen(buffer); sprintf(buffer, outValueFormat, i + 1, strLength); bytes = dpiData_getBytes(&arrayValue[i]); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4117() // Verify that binding string (VARCHAR2) arrays OUT work as expected (no // error). //----------------------------------------------------------------------------- int dpiTest_4117(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestStringArrays.TestOutArrays(:1, :2); end;"; const char *outValueFormat = "Test out element # %u"; uint32_t numElements = 20007, numElementsOut, i; dpiData *numElementsValue, *arrayValue; dpiVar *numElementsVar, *arrayVar; char buffer[300]; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numElements, 100, 0, 1, NULL, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); if (dpiVar_setNumElementsInArray(arrayVar, 0) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and bind values if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // perform execution and verify return values match expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_getNumElementsInArray(arrayVar, &numElementsOut) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, numElementsOut, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { sprintf(buffer, outValueFormat, i + 1); bytes = dpiData_getBytes(&arrayValue[i]); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4118() // Verify that binding record IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4118(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedValue = "udt_Record(99, 'Test Record', " "to_date('2017-06-01', 'YYYY-MM-DD'), " "to_timestamp('2018-08-02 03:02:01', 'YYYY-MM-DD HH24:MI:SS')," " true, -2147483647, 2147483647)"; const char *sql = "begin :1 := pkg_TestRecords.GetStringRep(:2); end;"; const char *objectName = "PKG_TESTRECORDS.UDT_RECORD"; dpiData *stringRepValue, *objectValue, tempData; dpiVar *stringRepVar, *objectVar; uint32_t i, numAttrs = 7; dpiObjectAttr *attrs[7]; dpiObjectType *objType; dpiBytes *bytes; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object type and attributes if (dpiConn_getObjectType(conn, objectName, strlen(objectName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create object if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, 1, 200, 0, 0, NULL, &stringRepVar, &stringRepValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(&tempData, 99); if (dpiObject_setAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&tempData, "Test Record", strlen("Test Record")); if (dpiObject_setAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2017, 6, 1, 1, 2, 1, 1, 0, 0); if (dpiObject_setAttributeValue(obj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2018, 8, 2, 3, 2, 1, 1, 0, 0); if (dpiObject_setAttributeValue(obj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBool(&tempData, 1); if (dpiObject_setAttributeValue(obj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromObject(objectVar, 0, obj) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, -2147483647); if (dpiObject_setAttributeValue(obj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, 2147483647); if (dpiObject_setAttributeValue(obj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, stringRepVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(stringRepValue); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, expectedValue, strlen(expectedValue)) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(stringRepVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4119() // Verify that binding record IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4119(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestRecords.TestInOut(:1); end;"; const char *objectName = "PKG_TESTRECORDS.UDT_RECORD"; const char *expectedValue = "String in/out record"; dpiData *objectValue, tempData, tempData2; uint32_t i, numAttrs = 7; dpiObjectAttr *attrs[7]; dpiObjectType *objType; dpiVar *objectVar; dpiBytes *bytes; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object type and attribute if (dpiConn_getObjectType(conn, objectName, strlen(objectName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create object if (dpiObjectType_createObject(objType, &obj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(&tempData, 99); if (dpiObject_setAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&tempData, "Test Record", strlen("Test Record")); if (dpiObject_setAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2017, 6, 5, 0, 0, 0, 0, 0, 0); if (dpiObject_setAttributeValue(obj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2018, 8, 9, 3, 2, 1, 0, 0, 0); if (dpiObject_setAttributeValue(obj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBool(&tempData, 1); if (dpiObject_setAttributeValue(obj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, -214748); if (dpiObject_setAttributeValue(obj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, 214748); if (dpiObject_setAttributeValue(obj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromObject(objectVar, 0, obj) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); obj = dpiData_getObject(objectValue); if (dpiObject_getAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), 990) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(&tempData); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, expectedValue, strlen(expectedValue)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2017, 6, 9, 0, 0, 0, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2018, 8, 8, 3, 2, 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getBool(&tempData), 0) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), -2147480) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), 2147480) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(obj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4120() // Verify that binding record OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4120(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestRecords.TestOut(:1); end;"; const char *objectName = "PKG_TESTRECORDS.UDT_RECORD"; const char *expectedValue = "String in record"; dpiData *objectValue, tempData, tempData2; uint32_t i, numAttrs = 7; dpiObjectAttr *attrs[7]; dpiObjectType *objType; dpiVar *objectVar; dpiBytes *bytes; dpiObject *obj; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object type and attribute if (dpiConn_getObjectType(conn, objectName, strlen(objectName), &objType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(objType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, objType, &objectVar, &objectValue) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); obj = dpiData_getObject(objectValue); if (dpiObject_getAttributeValue(obj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), 25) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(&tempData); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, expectedValue, strlen(expectedValue)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2016, 2, 16, 0, 0, 0, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2016, 2, 16, 18, 23, 55, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getBool(&tempData), 1) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), -214748) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(obj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), 214748) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(objType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(objectVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4121() // Verify that binding Record array IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4121(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin :1 := pkg_TestRecords.TestInArrays(:2); end;"; const char *arrayObjName = "PKG_TESTRECORDS.UDT_RECORDARRAY"; const char *elementObjName = "PKG_TESTRECORDS.UDT_RECORD"; const char *inValueFormat = "Test Record In %u"; dpiObjectType *arrayObjType, *elementObjType; dpiData *returnValue, *arrayValue, tempData; uint32_t i, numAttrs = 7, numElements = 10; dpiObject *arrayObj, *elementObj; dpiVar *returnVar, *arrayVar; dpiObjectAttr *attrs[7]; char buffer[300]; dpiStmt *stmt; dpiConn *conn; // get connection if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create objects if (dpiObjectType_createObject(arrayObjType, &arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(elementObjType, &elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &returnVar, &returnValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values for (i = 0; i < numElements; i++) { dpiData_setInt64(&tempData, i + 1); if (dpiObject_setAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(buffer, inValueFormat, i + 1); dpiData_setBytes(&tempData, buffer, strlen(buffer)); if (dpiObject_setAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2017, 6, i + 1, 0, 0, 0, 0, 0, 0); if (dpiObject_setAttributeValue(elementObj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2018, 8, i + 1, 3, 2, 1, 0, 0, 0); if (dpiObject_setAttributeValue(elementObj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBool(&tempData, 1); if (dpiObject_setAttributeValue(elementObj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, i + -21478); if (dpiObject_setAttributeValue(elementObj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, i + 21478); if (dpiObject_setAttributeValue(elementObj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&tempData, elementObj); if (dpiObject_appendElement(arrayObj, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(returnValue), 55) < 0) return DPI_FAILURE; // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(returnVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4122() // Verify that binding Record array IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4122(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestRecords.TestInOutArrays(:1); end;"; const char *outValueFormat = "Converted in/out record # %u"; const char *arrayObjName = "PKG_TESTRECORDS.UDT_RECORDARRAY"; const char *elementObjName = "PKG_TESTRECORDS.UDT_RECORD"; const char *inValueFormat = "Test Record In %u"; dpiObjectType *arrayObjType, *elementObjType; uint32_t i, numAttrs = 7, numElements = 10; dpiData *arrayValue, tempData, tempData2; dpiObject *arrayObj, *elementObj; dpiObjectAttr *attrs[7]; dpiVar *arrayVar; char buffer[300]; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create objects if (dpiObjectType_createObject(arrayObjType, &arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_createObject(elementObjType, &elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values for (i = 0; i < numElements; i++) { dpiData_setInt64(&tempData, i); if (dpiObject_setAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); sprintf(buffer, inValueFormat, i); dpiData_setBytes(&tempData, buffer, strlen(buffer)); if (dpiObject_setAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2017, 6, i + 1, 0, 0, 0, 0, 0, 0); if (dpiObject_setAttributeValue(elementObj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData, 2018, 8, i + 1, 3, 2, 1, 0, 0, 0); if (dpiObject_setAttributeValue(elementObj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBool(&tempData, 1); if (dpiObject_setAttributeValue(elementObj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, i); if (dpiObject_setAttributeValue(elementObj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setInt64(&tempData, i); if (dpiObject_setAttributeValue(elementObj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setObject(&tempData, elementObj); if (dpiObject_appendElement(arrayObj, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_setFromObject(arrayVar, 0, arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(arrayObj) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); arrayObj = dpiData_getObject(arrayValue); if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; for (i = 0; i < numElements; i++) { if (dpiObject_getElementValueByIndex(arrayObj, i, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); elementObj = dpiData_getObject(&tempData); if (dpiObject_getAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 10) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(&tempData); sprintf(buffer, outValueFormat, i); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2017, 6, i * 2 + 1, 0, 0, 0, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2018, 8, i * 2 + 1, 3, 2, 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getBool(&tempData), i % 2) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 10) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 10) < 0) return DPI_FAILURE; if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4123() // Verify that binding Record array OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4123(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "begin pkg_TestRecords.TestOutArrays(:1, :2); end;"; const char *arrayObjName = "PKG_TESTRECORDS.UDT_RECORDARRAY"; dpiData *numElementsValue, *arrayValue, tempData, tempData2; const char *elementObjName = "PKG_TESTRECORDS.UDT_RECORD"; const char *outValueFormat = "Test OUT record # %u"; dpiObjectType *arrayObjType, *elementObjType; uint32_t i, numAttrs = 7, numElements = 10; dpiVar *numElementsVar, *arrayVar; dpiObject *arrayObj, *elementObj; dpiObjectAttr *attrs[7]; char buffer[300]; dpiBytes *bytes; dpiStmt *stmt; dpiConn *conn; int32_t size; // get connection if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 12, 1) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // get object types and attributes if (dpiConn_getObjectType(conn, arrayObjName, strlen(arrayObjName), &arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_getObjectType(conn, elementObjName, strlen(elementObjName), &elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_getAttributes(elementObjType, numAttrs, attrs) < 0) return dpiTestCase_setFailedFromError(testCase); // create variables if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, 1, 0, 0, 0, NULL, &numElementsVar, &numElementsValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_OBJECT, DPI_NATIVE_TYPE_OBJECT, 1, 0, 0, 0, arrayObjType, &arrayVar, &arrayValue) < 0) return dpiTestCase_setFailedFromError(testCase); // populate bind variables with values dpiData_setInt64(numElementsValue, numElements); // prepare statement and perform binds if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); // execute statement and verify return value matches expectations if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); arrayObj = dpiData_getObject(arrayValue); if (dpiObject_getSize(arrayObj, &size) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, size, numElements) < 0) return DPI_FAILURE; for (i = 0; i < size; i++) { if (dpiObject_getElementValueByIndex(arrayObj, i, DPI_NATIVE_TYPE_OBJECT, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); elementObj = dpiData_getObject(&tempData); if (dpiObject_getAttributeValue(elementObj, attrs[0], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 10) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[1], DPI_NATIVE_TYPE_BYTES, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); bytes = dpiData_getBytes(&tempData); sprintf(buffer, outValueFormat, i); if (dpiTestCase_expectStringEqual(testCase, bytes->ptr, bytes->length, buffer, strlen(buffer)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[2], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2016, 2, 16 + i, 0, 0, 0, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[3], DPI_NATIVE_TYPE_TIMESTAMP, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setTimestamp(&tempData2, 2016, 2, 16 + i, 18, 23, 55, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, dpiData_getTimestamp(&tempData), dpiData_getTimestamp(&tempData2)) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[4], DPI_NATIVE_TYPE_BOOLEAN, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, dpiData_getBool(&tempData), i%2) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[5], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 7) < 0) return DPI_FAILURE; if (dpiObject_getAttributeValue(elementObj, attrs[6], DPI_NATIVE_TYPE_INT64, &tempData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, dpiData_getInt64(&tempData), i * 5) < 0) return DPI_FAILURE; if (dpiObject_release(elementObj) < 0) return dpiTestCase_setFailedFromError(testCase); } // cleanup if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(arrayObjType) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiObjectType_release(elementObjType) < 0) return dpiTestCase_setFailedFromError(testCase); for (i = 0; i < numAttrs; i++) { if (dpiObjectAttr_release(attrs[i]) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiVar_release(numElementsVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(arrayVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4124() // Verify that binding CLOB IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4124(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobIn(testCase, DPI_ORACLE_TYPE_CLOB, "CLOB", "In CLOB value (string)"); } //----------------------------------------------------------------------------- // dpiTest_4125() // Verify that binding CLOB IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4125(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobInOut(testCase, DPI_ORACLE_TYPE_CLOB, "CLOB", "IN/OUT CLOB value (string)"); } //----------------------------------------------------------------------------- // dpiTest_4126() // Verify that binding CLOB OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4126(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobOut(testCase, DPI_ORACLE_TYPE_CLOB, "CLOB", "OUT CLOB"); } //----------------------------------------------------------------------------- // dpiTest_4127() // Verify that binding NCLOB IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4127(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobIn(testCase, DPI_ORACLE_TYPE_NCLOB, "NCLOB", "In NCLOB value (national string)"); } //----------------------------------------------------------------------------- // dpiTest_4128() // Verify that binding NCLOB IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4128(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobInOut(testCase, DPI_ORACLE_TYPE_NCLOB, "NCLOB", "IN/OUT NCLOB value (national string)"); } //----------------------------------------------------------------------------- // dpiTest_4129() // Verify that binding NCLOB OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4129(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobOut(testCase, DPI_ORACLE_TYPE_NCLOB, "NCLOB", "OUT NCLOB"); } //----------------------------------------------------------------------------- // dpiTest_4130() // Verify that binding BLOB IN works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4130(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobIn(testCase, DPI_ORACLE_TYPE_BLOB, "BLOB", "In BLOB value (raw)"); } //----------------------------------------------------------------------------- // dpiTest_4131() // Verify that binding BLOB IN/OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4131(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobInOut(testCase, DPI_ORACLE_TYPE_BLOB, "BLOB", "IN/OUT BLOB value (raw)"); } //----------------------------------------------------------------------------- // dpiTest_4132() // Verify that binding BLOB OUT works as expected (no error). //----------------------------------------------------------------------------- int dpiTest_4132(dpiTestCase *testCase, dpiTestParams *params) { return dpiTest__bindLobOut(testCase, DPI_ORACLE_TYPE_BLOB, "BLOB", "OUT BLOB"); } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(4100); dpiTestSuite_addCase(dpiTest_4100, "test PL/SQL bind of unicode array (IN)"); dpiTestSuite_addCase(dpiTest_4101, "test PL/SQL bind of unicode array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4102, "test PL/SQL bind of unicode array (OUT)"); dpiTestSuite_addCase(dpiTest_4103, "test PL/SQL bind of number array (IN)"); dpiTestSuite_addCase(dpiTest_4104, "test PL/SQL bind of number array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4105, "test PL/SQL bind of number array (OUT)"); dpiTestSuite_addCase(dpiTest_4106, "test PL/SQL bind of date array (IN)"); dpiTestSuite_addCase(dpiTest_4107, "test PL/SQL bind of date array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4108, "test PL/SQL bind of date array (OUT)"); dpiTestSuite_addCase(dpiTest_4109, "test PL/SQL bind of object array (IN)"); dpiTestSuite_addCase(dpiTest_4110, "test PL/SQL bind of object array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4111, "test PL/SQL bind of object array (OUT)"); dpiTestSuite_addCase(dpiTest_4112, "test PL/SQL bind of number varray (IN)"); dpiTestSuite_addCase(dpiTest_4113, "test PL/SQL bind of number varray (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4114, "test PL/SQL bind of number varray (OUT)"); dpiTestSuite_addCase(dpiTest_4115, "test PL/SQL bind of string array (IN)"); dpiTestSuite_addCase(dpiTest_4116, "test PL/SQL bind of string array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4117, "test PL/SQL bind of string array (OUT)"); dpiTestSuite_addCase(dpiTest_4118, "test PL/SQL bind of record (IN)"); dpiTestSuite_addCase(dpiTest_4119, "test PL/SQL bind of record (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4120, "test PL/SQL bind of record (OUT)"); dpiTestSuite_addCase(dpiTest_4121, "test PL/SQL bind of record array (IN)"); dpiTestSuite_addCase(dpiTest_4122, "test PL/SQL bind of record array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4123, "test PL/SQL bind of record array (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4124, "test PL/SQL bind of CLOBs (IN)"); dpiTestSuite_addCase(dpiTest_4125, "test PL/SQL bind of CLOBs (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4126, "test PL/SQL bind of CLOBs (OUT)"); dpiTestSuite_addCase(dpiTest_4127, "test PL/SQL bind of NCLOBs (IN)"); dpiTestSuite_addCase(dpiTest_4128, "test PL/SQL bind of NCLOBs (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4129, "test PL/SQL bind of NCLOBs (OUT)"); dpiTestSuite_addCase(dpiTest_4130, "test PL/SQL bind of BLOBs (IN)"); dpiTestSuite_addCase(dpiTest_4131, "test PL/SQL bind of BLOBs (IN/OUT)"); dpiTestSuite_addCase(dpiTest_4132, "test PL/SQL bind of BLOBs (OUT)"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_4200_rowids.c000066400000000000000000000646011510466437300166370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2017, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_4200_rowids.c // Test suite for testing all the rowid related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_4200() // Prepare and execute any query that selects rowid on a regular table. // Convert one of these rowids to string by calling dpiRowid_getStringValue() // and perform a second query specifically for the row matching that rowid. //----------------------------------------------------------------------------- int dpiTest_4200(dpiTestCase *testCase, dpiTestParams *params) { const char *sqlQuery1 = "select rowid from TestStrings where IntCol = 7"; const char *sqlQuery2 = "select IntCol from TestStrings where rowid = :1"; uint32_t bufferRowIndex, rowidAsStringLength; dpiData *queryValue, bindValue; dpiNativeTypeNum nativeTypeNum; const char *rowidAsString; dpiStmt *stmt1, *stmt2; dpiConn *conn; int found; // perform first query to get rowid if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sqlQuery1, strlen(sqlQuery1), NULL, 0, &stmt1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt1, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt1, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for first query!"); if (dpiStmt_getQueryValue(stmt1, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_getStringValue(queryValue->value.asRowid, &rowidAsString, &rowidAsStringLength) < 0) return dpiTestCase_setFailedFromError(testCase); // perform second query to get row using rowid if (dpiConn_prepareStmt(conn, 0, sqlQuery2, strlen(sqlQuery2), NULL, 0, &stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&bindValue, (char*) rowidAsString, rowidAsStringLength); if (dpiStmt_bindValueByPos(stmt2, 1, DPI_NATIVE_TYPE_BYTES, &bindValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt2, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt2, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for second query!"); if (dpiStmt_getQueryValue(stmt2, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, queryValue->value.asInt64, 7) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiStmt_release(stmt1) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4201() // Prepare and execute any query that selects rowid on an index organized // table. convert one of these rowids to string by calling // dpiRowid_getStringValue() and perform a second query specifically // for the row matching that rowid. //----------------------------------------------------------------------------- int dpiTest_4201(dpiTestCase *testCase, dpiTestParams *params) { const char *sqlQuery1 = "select rowid from TestOrgIndex where IntCol = 3"; const char *sqlQuery2 = "select IntCol from TestOrgIndex where rowid = :1"; uint32_t bufferRowIndex, rowidAsStringLength; dpiData *queryValue, bindValue; dpiNativeTypeNum nativeTypeNum; const char *rowidAsString; dpiStmt *stmt1, *stmt2; dpiConn *conn; int found; // perform first query to get rowid if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sqlQuery1, strlen(sqlQuery1), NULL, 0, &stmt1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt1, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt1, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for first query!"); if (dpiStmt_getQueryValue(stmt1, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_getStringValue(queryValue->value.asRowid, &rowidAsString, &rowidAsStringLength) < 0) return dpiTestCase_setFailedFromError(testCase); // perform second query to get row using rowid if (dpiConn_prepareStmt(conn, 0, sqlQuery2, strlen(sqlQuery2), NULL, 0, &stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); dpiData_setBytes(&bindValue, (char*) rowidAsString, rowidAsStringLength); if (dpiStmt_bindValueByPos(stmt2, 1, DPI_NATIVE_TYPE_BYTES, &bindValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt2, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt2, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for second query!"); if (dpiStmt_getQueryValue(stmt2, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, queryValue->value.asInt64, 3) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiStmt_release(stmt1) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4202() // Fetch any rowid; close statement that fetched that rowid; call // dpiRowid_release() twice (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4202(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select rowid from TestOrgIndex where IntCol = 6"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiData *rowidValue; dpiRowid *rowid; dpiStmt *stmt; dpiConn *conn; int found; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found!"); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &rowidValue) < 0) return dpiTestCase_setFailedFromError(testCase); rowid = rowidValue->value.asRowid; if (dpiRowid_addRef(rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_release(rowid) < 0) return dpiTestCase_setFailedFromError(testCase); dpiRowid_release(rowid); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4203() // Call dpiRowid_getStringValue() with a NULL rowid (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4203(dpiTestCase *testCase, dpiTestParams *params) { uint32_t rowidAsStringLength; const char *rowidAsString; dpiConn *conn; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiRowid_getStringValue(NULL, &rowidAsString, &rowidAsStringLength); if (dpiTestCase_expectError(testCase, "DPI-1002:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4204() // Prepare and execute any query which selects a rowid from a regular table. // Use one of these rowids to perform a second query specifically for the row // matching that rowid. //----------------------------------------------------------------------------- int dpiTest_4204(dpiTestCase *testCase, dpiTestParams *params) { const char *sqlQuery1 = "select rowid from TestStrings where IntCol = 9"; const char *sqlQuery2 = "select IntCol from TestStrings where rowid = :1"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiStmt *stmt1, *stmt2; dpiData *queryValue; dpiConn *conn; int found; // perform first query to get rowid if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sqlQuery1, strlen(sqlQuery1), NULL, 0, &stmt1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt1, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt1, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for first query!"); if (dpiStmt_getQueryValue(stmt1, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); // perform second query to get row using rowid if (dpiConn_prepareStmt(conn, 0, sqlQuery2, strlen(sqlQuery2), NULL, 0, &stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt2, 1, DPI_NATIVE_TYPE_ROWID, queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt2, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt2, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for second query!"); if (dpiStmt_getQueryValue(stmt2, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, queryValue->value.asInt64, 9) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiStmt_release(stmt1) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4205() // prepare and execute any query which selects rowid on an index organized // table. use one of these rowids to perform a second query specifically // for the row matching that rowid. //----------------------------------------------------------------------------- int dpiTest_4205(dpiTestCase *testCase, dpiTestParams *params) { const char *sqlQuery1 = "select rowid from TestOrgIndex where IntCol = 8"; const char *sqlQuery2 = "select IntCol from TestOrgIndex where rowid = :1"; dpiNativeTypeNum nativeTypeNum; uint32_t bufferRowIndex; dpiStmt *stmt1, *stmt2; dpiData *queryValue; dpiConn *conn; int found; // perform first query to get rowid if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sqlQuery1, strlen(sqlQuery1), NULL, 0, &stmt1) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt1, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt1, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for first query!"); if (dpiStmt_getQueryValue(stmt1, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); // perform second query to get row using rowid if (dpiConn_prepareStmt(conn, 0, sqlQuery2, strlen(sqlQuery2), NULL, 0, &stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindValueByPos(stmt2, 1, DPI_NATIVE_TYPE_ROWID, queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt2, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt2, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (!found) return dpiTestCase_setFailed(testCase, "row not found for second query!"); if (dpiStmt_getQueryValue(stmt2, 1, &nativeTypeNum, &queryValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectUintEqual(testCase, queryValue->value.asInt64, 8) < 0) return dpiTestCase_setFailedFromError(testCase); // cleanup if (dpiStmt_release(stmt1) < 0) dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt2) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4206() // Call dpiStmt_getLastRowid() before calling dpiStmt_execute() and verify // that it returns NULL (no error). //----------------------------------------------------------------------------- int dpiTest_4206(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select IntCol from TestOrgIndex"; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (rowid) return dpiTestCase_setFailed(testCase, "Non-NULL rowid returned."); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4207() // Call dpiStmt_getLastRowid() after calling dpiStmt_execute() on a non-DML // statement and verify it returns NULL (no error). //----------------------------------------------------------------------------- int dpiTest_4207(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "truncate table TestTempTable"; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (rowid) return dpiTestCase_setFailed(testCase, "Non-NULL rowid returned."); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4208() // Call dpiStmt_getLastRowid() after calling dpiStmt_execute() with a DML // statement that doesn't affect any rows and verify it returns NULL (no // error). //----------------------------------------------------------------------------- int dpiTest_4208(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "select IntCol from TestOrgIndex where rownum < 1"; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (rowid) return dpiTestCase_setFailed(testCase, "Non-NULL rowid returned."); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4209() // Call dpiStmt_getLastRowid() after calling dpiStmt_execute() with a DML // statement that affects one row and verify it returns a rowid (no error). //----------------------------------------------------------------------------- int dpiTest_4209(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable values (1, 'test1')"; uint32_t rowidAsStringLength; const char *rowidAsString; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_getStringValue(rowid, &rowidAsString, &rowidAsStringLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4210() // Call dpiStmt_getLastRowid() after calling dpiStmt_execute() with a DML // statement that affects multiple rows and verify it returns a rowid (no // error). //----------------------------------------------------------------------------- int dpiTest_4210(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable values (:1, :2)"; uint32_t rowidAsStringLength, numRows = 5, i; dpiData *intData, *strData; const char *rowidAsString; dpiVar *intVar, *strVar; char buffer[100]; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; // get connection if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // prepare and bind insert statement if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_NUMBER, DPI_NATIVE_TYPE_INT64, numRows, 0, 0, 0, NULL, &intVar, &intData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, numRows, 100, 1, 0, NULL, &strVar, &strData) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 2, strVar) < 0) return dpiTestCase_setFailedFromError(testCase); // populate some dummy data for (i = 0; i < numRows; i++) { dpiData_setInt64(&intData[i], i + 1); sprintf(buffer, "Dummy data %d", i + 1); if (dpiVar_setFromBytes(strVar, i, buffer, strlen(buffer)) < 0) return dpiTestCase_setFailedFromError(testCase); } if (dpiStmt_executeMany(stmt, DPI_MODE_EXEC_DEFAULT, numRows) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_getStringValue(rowid, &rowidAsString, &rowidAsStringLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(intVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(strVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4211() // Call dpiStmt_execute() with a DML statement that affects one row, verify // dpiStmt_getLastRowid() returns a rowid and call dpiRowid_addRef() to acquire // an independent reference, then release the statement and verify the rowid // can still be used (no error). //----------------------------------------------------------------------------- int dpiTest_4211(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert into TestTempTable values (1, 'test1')"; uint32_t rowidAsStringLength; const char *rowidAsString; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_addRef(rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_getStringValue(rowid, &rowidAsString, &rowidAsStringLength) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiRowid_release(rowid) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4212() // Call dpiStmt_getLastRowid() after calling dpiStmt_execute() with an INSERT // ALL statement that affects many rows and verify it returns NULL (no error). //----------------------------------------------------------------------------- int dpiTest_4212(dpiTestCase *testCase, dpiTestParams *params) { const char *sql = "insert all " "into TestTempTable(IntCol, StringCol) values (1, 'test1') " "into TestTempTable(IntCol, StringCol) values (2, 'test2') " "into TestTempTable(IntCol, StringCol) values (3, 'test3') " "select * from dual"; dpiRowid *rowid; dpiConn *conn; dpiStmt *stmt; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, 0, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getLastRowid(stmt, &rowid) < 0) return dpiTestCase_setFailedFromError(testCase); if (rowid) return dpiTestCase_setFailed(testCase, "Non-NULL rowid returned."); if (dpiStmt_release(stmt) < 0) dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(4200); dpiTestSuite_addCase(dpiTest_4200, "fetch rowid and refetch row via string rep (normal table)"); dpiTestSuite_addCase(dpiTest_4201, "fetch rowid and refetch row via string rep (index org table)"); dpiTestSuite_addCase(dpiTest_4202, "call dpiRowid_release() twice"); dpiTestSuite_addCase(dpiTest_4203, "verify dpiRowid_getStringValue() with NULL rowid"); dpiTestSuite_addCase(dpiTest_4204, "fetch rowid and refetch row (normal table)"); dpiTestSuite_addCase(dpiTest_4205, "fetch rowid and refetch row (index org table)"); dpiTestSuite_addCase(dpiTest_4206, "call dpiStmt_getLastRowid() before calling dpiStmt_execute"); dpiTestSuite_addCase(dpiTest_4207, "call dpiStmt_getLastRowid() after executing non-DML"); dpiTestSuite_addCase(dpiTest_4208, "call dpiStmt_getLastRowid() after executing DML (no rows)"); dpiTestSuite_addCase(dpiTest_4209, "call dpiStmt_getLastRowid() after executing DML (one row)"); dpiTestSuite_addCase(dpiTest_4210, "call dpiStmt_getLastRowid() after executing DML (many rows)"); dpiTestSuite_addCase(dpiTest_4211, "call dpiRowid_addRef() to verify independent reference"); dpiTestSuite_addCase(dpiTest_4212, "call dpiStmt_getLastRowid() after INSERT ALL statement"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_4300_json.c000066400000000000000000001414731510466437300163050ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2020, 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_4300_json.c // Test suite for all the JSON related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__truncateJsonTable() // Truncate the JSON table. //----------------------------------------------------------------------------- int dpiTest__truncateJsonTable(dpiTestCase *testCase, dpiConn *conn) { const char *sql = "truncate table TestJson"; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return 0; } //----------------------------------------------------------------------------- // dpiTest_4300() // Call each of the dpiJson public functions with the json parameter set to // NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4300(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; dpiJson_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiJson_getValue(NULL, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiJson_setValue(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiJson_setFromText(NULL, NULL, 0, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiJson_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4301() // Insert scalar JSON value into the table and then fetch it back again, // ensuring that it is identical. //----------------------------------------------------------------------------- int dpiTest_4301(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values(:1)"; const char *selectSql = "select jsoncol from TestJson"; dpiNativeTypeNum nativeTypeNum; dpiJsonNode inNode, *topNode; int64_t valueToPass = 99; dpiDataBuffer inNodeData; dpiData *data, *outValue; uint32_t bufferRowIndex; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // setup node inNode.value = &inNodeData; inNode.oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNode.nativeTypeNum = DPI_NATIVE_TYPE_INT64; inNodeData.asInt64 = valueToPass; // create variable and populate it with the node if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNode) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, topNode->value->asDouble, valueToPass) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4302() // Bind JSON values into the database by building a JSON node tree and // verify. //----------------------------------------------------------------------------- int dpiTest_4302(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values(:1)"; const char *selectSql = "select jsoncol from TestJson"; uint32_t bufferRowIndex, fieldNameLengths[2]; dpiJsonNode inNodes[11], *topNode; dpiNativeTypeNum nativeTypeNum; dpiDataBuffer inNodeData[11]; dpiData *data, *outValue; dpiJsonArray *arrayVal; dpiJsonObject *jsonObj; char *fieldNames[2]; dpiData arrData; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found, i; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); // set value for each of the nodes for (i = 0; i < 11; i++) inNodes[i].value = &inNodeData[i]; inNodes[0].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[0].nativeTypeNum = DPI_NATIVE_TYPE_INT64; inNodeData[0].asInt64 = -99; inNodes[1].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[1].nativeTypeNum = DPI_NATIVE_TYPE_UINT64; inNodeData[1].asUint64 = 9223372036854775809UL; inNodes[2].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[2].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData[2].asDouble = 1.23456; inNodes[3].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[3].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData[3].asDouble = 9397.111114444; inNodes[4].oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; inNodes[4].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[4].asBytes.ptr = "Test String"; inNodeData[4].asBytes.length = strlen(inNodeData[4].asBytes.ptr); inNodes[5].oracleTypeNum = DPI_ORACLE_TYPE_VARCHAR; inNodes[5].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[5].asBytes.ptr = "Test String2"; inNodeData[5].asBytes.length = strlen(inNodeData[5].asBytes.ptr); inNodes[6].oracleTypeNum = DPI_ORACLE_TYPE_RAW; inNodes[6].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[6].asBytes.ptr = "A Raw"; inNodeData[6].asBytes.length = strlen(inNodeData[6].asBytes.ptr); inNodes[7].oracleTypeNum = DPI_ORACLE_TYPE_DATE; inNodes[7].nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; inNodeData[7].asTimestamp.year = 2020; inNodeData[7].asTimestamp.month = 10; inNodeData[7].asTimestamp.day = 15; inNodeData[7].asTimestamp.hour = 13; inNodeData[7].asTimestamp.minute = 54; inNodeData[7].asTimestamp.second = 12; inNodes[8].oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP; inNodes[8].nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; inNodeData[8].asTimestamp.year = 2020; inNodeData[8].asTimestamp.month = 10; inNodeData[8].asTimestamp.day = 15; inNodeData[8].asTimestamp.hour = 13; inNodeData[8].asTimestamp.minute = 58; inNodeData[8].asTimestamp.second = 59; // JSON object fieldNames[0] = "Fred"; fieldNameLengths[0] = strlen(fieldNames[0]); fieldNames[1] = "George"; fieldNameLengths[1] = strlen(fieldNames[1]); inNodes[9].oracleTypeNum = DPI_ORACLE_TYPE_JSON_OBJECT; inNodes[9].nativeTypeNum = DPI_NATIVE_TYPE_JSON_OBJECT; inNodeData[9].asJsonObject.numFields = 2; inNodeData[9].asJsonObject.fieldNames = fieldNames; inNodeData[9].asJsonObject.fieldNameLengths = fieldNameLengths; inNodeData[9].asJsonObject.fields = &inNodes[0]; inNodeData[9].asJsonObject.fieldValues = &inNodeData[0]; inNodes[10].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[10].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[10].asJsonArray.numElements = 10; inNodeData[10].asJsonArray.elements = &inNodes[0]; inNodeData[10].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[10]) < 0) return dpiTestCase_setFailedFromError(testCase); // perform insert if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiTestCase_setFailedFromError(testCase); // use dpiData_getJsonArray and fetch number of elements. arrData.value = *(topNode->value); arrayVal = dpiData_getJsonArray(&arrData); if (dpiTestCase_expectIntEqual(testCase, arrayVal->numElements, 10) < 0) return DPI_FAILURE; // use dpiData_getJsonObject and fetch number of fields. arrData.value = *(arrayVal->elements[9].value); jsonObj = dpiData_getJsonObject(&arrData); if (dpiTestCase_expectIntEqual(testCase, jsonObj->numFields, 2) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4303() // Verify that integer values can be stored in a JSON array -- and when // fetched, that they retain the same values. //----------------------------------------------------------------------------- int dpiTest_4303(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; int64_t valueToPass[] = {9, 255, 999, 65535, 0, 4294967295, -9223372036854775, 9223372036854775, 0, 1}; uint32_t numElements = 10, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiJsonNode inNodes[11], *node; dpiDataBuffer inNodeData[11]; dpiData *data, *outValue; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodeData[i].asInt64 = valueToPass[i]; inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_INT64; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; // verify value matches array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; if (dpiTestCase_expectDoubleEqual(testCase, node->value->asDouble, valueToPass[i]) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4304() // Verify that double values can be stored in a JSON array -- and when // fetched, that they retain the same values. //----------------------------------------------------------------------------- int dpiTest_4304(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; double valueToPass[] = {-0.123456789101112, 0.123456789101112, -1234567.12345678, 9999999.99999999}; uint32_t numElements = 4, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiJsonNode inNodes[5], *node; dpiDataBuffer inNodeData[5]; dpiData *data, *outValue; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData[i].asDouble = valueToPass[i]; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); // verify value if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; if (dpiTestCase_expectDoubleEqual(testCase, node->value->asDouble, valueToPass[i]) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4305() // Verify that strings and raw bytes can be stored in a JSON array -- and // when fetched, that they retain the same values. //----------------------------------------------------------------------------- int dpiTest_4305(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; char valueToPass[][100] = {"Test String aaaaaa\naabbbbcccdddeeefffgxyzzzz", "a", "12ABCD\\EFGHIJ\nKLMNOPQRSTUVWXYZ", "abcdeadcdasdf"}; uint32_t numElements = 4, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiJsonNode inNodes[5], *node; dpiDataBuffer inNodeData[5]; dpiData *data, *outValue; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = (i < 2) ? DPI_ORACLE_TYPE_VARCHAR : DPI_ORACLE_TYPE_RAW; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_BYTES; inNodeData[i].asBytes.ptr = valueToPass[i]; inNodeData[i].asBytes.length = strlen(inNodeData[i].asBytes.ptr); } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); // verify value if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; if (dpiTestCase_expectStringEqual(testCase, node->value->asBytes.ptr, node->value->asBytes.length, valueToPass[i], strlen(valueToPass[i])) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4306() // Verify that date values can be stored in a JSON array -- and when // fetched, that they retain the same values. //----------------------------------------------------------------------------- int dpiTest_4306(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; uint32_t numElements = 60, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiData *data, *outValue, temp; dpiJsonNode inNodes[61], *node; dpiDataBuffer inNodeData[61]; dpiTimestamp *timestamp; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_DATE; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; inNodeData[i].asTimestamp.year = 2021 - i; inNodeData[i].asTimestamp.month = i % 12 + 1; inNodeData[i].asTimestamp.day = i % 28 + 1; inNodeData[i].asTimestamp.hour = i % 23 + 1; inNodeData[i].asTimestamp.minute = i % 59 + 1; inNodeData[i].asTimestamp.second = i % 59 + 1; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); // verify value if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; timestamp = &node->value->asTimestamp; dpiData_setTimestamp(&temp, 2021 - i, i % 12 + 1, i % 28 + 1, i % 23 + 1, i % 59 + 1, i % 59 + 1, 0, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, timestamp, dpiData_getTimestamp(&temp)) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4307() // Verify that timestamp values can be stored in a JSON array -- and when // fetched, that they retain the same values. //----------------------------------------------------------------------------- int dpiTest_4307(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; uint32_t numElements = 60, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiData *data, *outValue, temp; dpiJsonNode inNodes[61], *node; dpiDataBuffer inNodeData[61]; dpiTimestamp *timestamp; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_TIMESTAMP; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_TIMESTAMP; inNodeData[i].asTimestamp.year = 2021 - i; inNodeData[i].asTimestamp.month = i % 12 + 1; inNodeData[i].asTimestamp.day = i % 28 + 1; inNodeData[i].asTimestamp.hour = i % 23 + 1; inNodeData[i].asTimestamp.minute = i % 59 + 1; inNodeData[i].asTimestamp.second = i % 59 + 1; inNodeData[i].asTimestamp.fsecond = i % 999999999; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); // verify value if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; timestamp = &node->value->asTimestamp; dpiData_setTimestamp(&temp, 2021 - i, i % 12 + 1, i % 28 + 1, i % 23 + 1, i % 59 + 1, i % 59 + 1, i % 999999999, 0, 0); if (dpiTestCase_expectTimestampEqual(testCase, timestamp, dpiData_getTimestamp(&temp)) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4308() // Set the value using dpiJson_setValue() multiple times and verify // dpiJson_getValue() returns the proper topnode value each time. //----------------------------------------------------------------------------- int dpiTest_4308(dpiTestCase *testCase, dpiTestParams *params) { dpiJsonNode inNode, *topNode; dpiDataBuffer inNodeData; double valueToPass; dpiData *data; dpiConn *conn; dpiVar *inVar; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // setup node valueToPass = 1.123; inNode.value = &inNodeData; inNode.oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNode.nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData.asDouble = valueToPass; // create variable and populate it with the node if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(data), DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, topNode->value->asDouble, valueToPass) < 0) return DPI_FAILURE; // setup node valueToPass = 99.9; inNodeData.asDouble = valueToPass; data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(data), DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, topNode->value->asDouble, valueToPass) < 0) return DPI_FAILURE; if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4309() // Set the value using dpiJson_setValue() and call dpiJson_getValue() // using different values of dpiJsonOptions. Verify it returns the correct // native type. //----------------------------------------------------------------------------- int dpiTest_4309(dpiTestCase *testCase, dpiTestParams *params) { dpiJsonNode inNode, *topNode; double valueToPass = 1.25; dpiDataBuffer inNodeData; uint32_t stringRepLength; char stringRep[40]; dpiData *data; dpiConn *conn; dpiVar *inVar; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // setup node inNode.value = &inNodeData; inNode.oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNode.nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData.asDouble = valueToPass; // create variable and populate it with the node if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNode) < 0) return dpiTestCase_setFailedFromError(testCase); // use default options (value returned as double) if (dpiJson_getValue(dpiData_getJson(data), DPI_JSON_OPT_DEFAULT, &topNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectDoubleEqual(testCase, topNode->value->asDouble, valueToPass) < 0) return DPI_FAILURE; // use option to convert numbers to strings (value returned as string) stringRepLength = (uint32_t) snprintf(stringRep, sizeof(stringRep), "%g", valueToPass); if (dpiJson_getValue(dpiData_getJson(data), DPI_JSON_OPT_NUMBER_AS_STRING, &topNode) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectStringEqual(testCase, topNode->value->asBytes.ptr, topNode->value->asBytes.length, stringRep, stringRepLength) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4310() // Verify that double values can be stored in a JSON array using the // following combination 'DPI_ORACLE_TYPE_NATIVE_DOUBLE' with // 'DPI_NATIVE_TYPE_DOUBLE' -- and when fetched, that they retain the same // values. //----------------------------------------------------------------------------- int dpiTest_4310(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; double valueToPass[] = {-0.123456789101112, 0.123456789101112, -1234567.12345678, 9999999.99999999}; uint32_t numElements = 4, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiJsonNode inNodes[5], *node; dpiDataBuffer inNodeData[5]; dpiData *data, *outValue; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_NATIVE_DOUBLE; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData[i].asDouble = valueToPass[i]; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); // verify value if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; if (dpiTestCase_expectDoubleEqual(testCase, node->value->asDouble, valueToPass[i]) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4311() // Verify that float values can be stored in a JSON array -- and when // fetched, that they retain the same values. //----------------------------------------------------------------------------- int dpiTest_4311(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestJson values (:1)"; const char *selectSql = "select jsoncol from TestJson"; float valueToPass[] = {-0.123456789101112, 0.123456789101112, -1234567.12345678, 9999999.99999999}; uint32_t numElements = 4, bufferRowIndex, i; dpiNativeTypeNum nativeTypeNum; dpiJsonNode inNodes[5], *node; dpiDataBuffer inNodeData[5]; dpiData *data, *outValue; dpiJsonArray *array; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 21, 0) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__truncateJsonTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_NATIVE_FLOAT; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_FLOAT; inNodeData[i].asFloat = valueToPass[i]; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; // create variable and populate it with the JSON value if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); // insert row if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // fetch row if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiJson_getValue(dpiData_getJson(outValue), DPI_JSON_OPT_DEFAULT, &node) < 0) return dpiTestCase_setFailedFromError(testCase); // verify value if (dpiTestCase_expectIntEqual(testCase, node->value->asJsonArray.numElements, numElements) < 0) return DPI_FAILURE; array = &node->value->asJsonArray; for (i = 0; i < array->numElements; i++) { node = &array->elements[i]; if (dpiTestCase_expectDoubleEqual(testCase, node->value->asFloat, valueToPass[i]) < 0) return DPI_FAILURE; } if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(4300); dpiTestSuite_addCase(dpiTest_4300, "call public functions with Json set to NULL"); dpiTestSuite_addCase(dpiTest_4301, "insert and fetch JSON scalar value"); dpiTestSuite_addCase(dpiTest_4302, "insert and fetch JSON object value"); dpiTestSuite_addCase(dpiTest_4303, "insert and fetch JSON array int values"); dpiTestSuite_addCase(dpiTest_4304, "insert and fetch JSON array double values"); dpiTestSuite_addCase(dpiTest_4305, "insert and fetch JSON array string values"); dpiTestSuite_addCase(dpiTest_4306, "insert and fetch JSON array date values"); dpiTestSuite_addCase(dpiTest_4307, "insert and fetch JSON array timestamp values"); dpiTestSuite_addCase(dpiTest_4308, "call dpiJson_setValue() and dpiJson_getValue() twice"); dpiTestSuite_addCase(dpiTest_4309, "call dpiJson_getValue() with different options"); dpiTestSuite_addCase(dpiTest_4310, "insert and fetch JSON array native double values"); dpiTestSuite_addCase(dpiTest_4311, "insert and fetch JSON array native float values"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_4400_vector.c000066400000000000000000001261531510466437300166350ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_4400_json.c // Test suite for all the Vector related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest__compareVectors() // Compare two vectors to ensure they have the same values. //----------------------------------------------------------------------------- int dpiTest__compareVectors(dpiTestCase *testCase, dpiVectorInfo *vector1, dpiVectorInfo *vector2) { uint32_t i; int status; // ensure the number of dimensions matches first if (vector1->numDimensions != vector2->numDimensions) { return dpiTestCase_setFailed(testCase, "vector dimension counts do not match"); } // compare arrays for (i = 0; i < vector1->numDimensions; i++) { status = 0; switch(vector1->format) { case DPI_VECTOR_FORMAT_INT8: if (vector2->format == DPI_VECTOR_FORMAT_INT8) { status = dpiTestCase_expectIntEqual(testCase, vector1->dimensions.asInt8[i], vector2->dimensions.asInt8[i]); } else if (vector2->format == DPI_VECTOR_FORMAT_FLOAT32) { status = dpiTestCase_expectIntEqual(testCase, vector1->dimensions.asInt8[i], vector2->dimensions.asFloat[i]); } else { status = dpiTestCase_expectIntEqual(testCase, vector1->dimensions.asInt8[i], vector2->dimensions.asDouble[i]); } break; case DPI_VECTOR_FORMAT_FLOAT32: if (vector2->format == DPI_VECTOR_FORMAT_INT8) { status = dpiTestCase_expectDoubleEqual(testCase, vector1->dimensions.asFloat[i], vector2->dimensions.asInt8[i]); } else if (vector2->format == DPI_VECTOR_FORMAT_FLOAT32) { status = dpiTestCase_expectDoubleEqual(testCase, vector1->dimensions.asFloat[i], vector2->dimensions.asFloat[i]); } else { status = dpiTestCase_expectDoubleEqual(testCase, vector1->dimensions.asFloat[i], vector2->dimensions.asDouble[i]); } break; case DPI_VECTOR_FORMAT_FLOAT64: if (vector2->format == DPI_VECTOR_FORMAT_INT8) { status = dpiTestCase_expectDoubleEqual(testCase, vector1->dimensions.asDouble[i], vector2->dimensions.asInt8[i]); } else if (vector2->format == DPI_VECTOR_FORMAT_FLOAT32) { status = dpiTestCase_expectDoubleEqual(testCase, vector1->dimensions.asDouble[i], vector2->dimensions.asFloat[i]); } else { status = dpiTestCase_expectDoubleEqual(testCase, vector1->dimensions.asDouble[i], vector2->dimensions.asDouble[i]); } break; } if (status < 0) return DPI_FAILURE; } return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__deleteVectorTable() // Delete the vector table. //----------------------------------------------------------------------------- int dpiTest__deleteVectorTable(dpiTestCase *testCase, dpiConn *conn) { const char *sql = "delete TestVectors"; dpiStmt *stmt; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__getVectorInfo() // Populate the vector info structure. //----------------------------------------------------------------------------- void dpiTest__getVectorInfo(dpiVectorInfo *info, uint8_t format, uint32_t numDimensions, void *values) { memset(info, 0, sizeof(dpiVectorInfo)); info->format = format; info->numDimensions = numDimensions; info->dimensions.asPtr = values; } //----------------------------------------------------------------------------- // dpiTest__populateTable() // Insert data into the table. //----------------------------------------------------------------------------- int dpiTest__populateTable(dpiTestCase *testCase, const char *columnName, dpiVectorInfo *vectorInfo, const char *errExp) { dpiVector *vec; char sql[200]; dpiData *data; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 4) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__deleteVectorTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_newVector(conn, vectorInfo, &vec) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VECTOR, DPI_NATIVE_TYPE_VECTOR, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromVector(inVar, 0, vec) < 0) return dpiTestCase_setFailedFromError(testCase); snprintf(sql, sizeof(sql), "insert into TestVectors (IntCol, %s) values(1, :1)", columnName); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_COMMIT_ON_SUCCESS, NULL) < 0) { if (errExp) { if (dpiTestCase_expectError(testCase, errExp) < 0) return DPI_FAILURE; } else { return dpiTestCase_setFailedFromError(testCase); } } // cleanup if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVector_release(vec) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__populateTableViaType() // Insert data into the table via a type other than native vector. //----------------------------------------------------------------------------- int dpiTest__populateTableViaType(dpiTestCase *testCase, const char *columnName, const char *vector, dpiOracleTypeNum oraType, dpiNativeTypeNum nativeType, const char *errExp) { char sql[200]; dpiData *data; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 4) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__deleteVectorTable(testCase, conn) < 0) return DPI_FAILURE; if (dpiConn_newVar(conn, oraType, nativeType, 1, 100, 1, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); snprintf(sql, sizeof(sql), "insert into TestVectors (IntCol, %s) values(1, :1)", columnName); if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromBytes(inVar, 0, vector, strlen(vector)) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_COMMIT_ON_SUCCESS, NULL) < 0) { if (errExp) { if (dpiTestCase_expectError(testCase, errExp) < 0) return DPI_FAILURE; } else { return dpiTestCase_setFailedFromError(testCase); } } // cleanup if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest__verifySelect() // Select vector column from the table and verify the values are as expected. //----------------------------------------------------------------------------- int dpiTest__verifySelect(dpiTestCase *testCase, const char *sql, dpiVectorInfo *inVectorInfo) { dpiNativeTypeNum nativeTypeNum; dpiVectorInfo outVectorInfo; uint32_t bufferRowIndex; dpiData *outValue; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 4) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_prepareStmt(conn, 0, sql, strlen(sql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getQueryValue(stmt, 1, &nativeTypeNum, &outValue) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVector_getValue(outValue->value.asVector, &outVectorInfo) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__compareVectors(testCase, inVectorInfo, &outVectorInfo) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4400() // Call each of the dpiVector public functions with vector parameter set to // NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4400(dpiTestCase *testCase, dpiTestParams *params) { const char *expectedError = "DPI-1002:"; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 4) < 0) return DPI_FAILURE; dpiVector_addRef(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiVector_getValue(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiVector_setValue(NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiVar_setFromVector(NULL, 0, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_newVector(NULL, NULL, NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiVector_release(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4401() // Insert and fetch from int8 vector column and verify the values. //----------------------------------------------------------------------------- int dpiTest_4401(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector8Col from TestVectors"; int8_t values[] = {-128, -10, 0, 40, 50, 60, 70, 80, 90, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 10, values); if (dpiTest__populateTable(testCase, "Vector8Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4402() // Insert and fetch from float32 vector column and verify the values. //----------------------------------------------------------------------------- int dpiTest_4402(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector32Col from TestVectors"; float values[] = {-99.999, -104.1, -0.1234, 1.9, 222.222, 5.5, 0.0099, 999.999, 12345.1, 333333.333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 10, values); if (dpiTest__populateTable(testCase, "Vector32Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4403() // Insert and fetch from float64 vector column and verify the values. //----------------------------------------------------------------------------- int dpiTest_4403(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector64Col from TestVectors"; double values[] = {-999.999, -104.1, -0.1234, 1.9, 222.222, 5.5, 0.0099, 999.999, 12345.1, 3333333.33333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 10, values); if (dpiTest__populateTable(testCase, "Vector64Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4404() // Insert and fetch from flex vector column as int8 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4404(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex8Col from TestVectors"; int8_t values[] = {-128, -10, 0, 40, 50, 60, 90, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 10, values); if (dpiTest__populateTable(testCase, "VectorFlex8Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4405() // Insert and fetch from flex vector column as float32 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4405(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex32Col from TestVectors"; float values[] = {-99.999, -104.1, -0.1234, 1.9, 222.222, 0.0099, 999.999, 12345.1, 333333.333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 10, values); if (dpiTest__populateTable(testCase, "VectorFlex32Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4406() // Insert and fetch from flex vector column as float64 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4406(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex64Col from TestVectors"; double values[] = {-999.999, -104.1, -0.1234, 222.222, 5.5, 0.0099, 999.999, 3333333.33333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 8, values); if (dpiTest__populateTable(testCase, "VectorFlex64Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4407() // Insert and fetch from flex type column as int8 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4407(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexTypeCol from TestVectors"; int8_t values[] = {-128, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 2, values); if (dpiTest__populateTable(testCase, "VectorFlexTypeCol", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4408() // Insert and fetch from flex type column as float32 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4408(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexTypeCol from TestVectors"; float values[] = {-99.999, 333333.333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 2, values); if (dpiTest__populateTable(testCase, "VectorFlexTypeCol", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4409() // Insert and fetch from flex type column as float64 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4409(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexTypeCol from TestVectors"; double values[] = {-99999.999, 3333333.33333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 2, values); if (dpiTest__populateTable(testCase, "VectorFlexTypeCol", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4410() // Insert and fetch from flex all column as int8 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4410(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexAllCol from TestVectors"; int8_t values[] = {-128, 127, 0}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 3, values); if (dpiTest__populateTable(testCase, "VectorFlexAllCol", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4411() // Insert and fetch from flex all column as float32 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4411(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexAllCol from TestVectors"; float values[] = {-99.999, 3333.333, 1.0, -5.9}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 4, values); if (dpiTest__populateTable(testCase, "VectorFlexAllCol", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4412() // Insert and fetch from flex all column as float64 and verify the values. //----------------------------------------------------------------------------- int dpiTest_4412(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexAllCol from TestVectors"; double values[] = {-99999.999, 3333333.33333, 0.0, 1.333, -555.555}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 5, values); if (dpiTest__populateTable(testCase, "VectorFlexAllCol", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4413() // Verify int8 vector column with wrong dimension count (error ORA-51803). //----------------------------------------------------------------------------- int dpiTest_4413(dpiTestCase *testCase, dpiTestParams *params) { int8_t values[] = {-128, -10, 0, 40, 50, 60, 70, 80, 90, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 9, values); if (dpiTest__populateTable(testCase, "Vector8Col", &vectorInfo, "ORA-51803:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4414() // Verify float32 vector column with wrong dimension count (error ORA-51803). //----------------------------------------------------------------------------- int dpiTest_4414(dpiTestCase *testCase, dpiTestParams *params) { float values[] = {-99.999, -104.1, -0.1234, 1.9, 222.222, 5.5, 0.0099, 999.999, 12345.1}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 9, values); if (dpiTest__populateTable(testCase, "Vector32Col", &vectorInfo, "ORA-51803:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4415() // Verify float64 vector column with wrong dimension count (error ORA-51803). //----------------------------------------------------------------------------- int dpiTest_4415(dpiTestCase *testCase, dpiTestParams *params) { double values[] = {-999.999, -104.1, -0.1234, 1.9, 222.222, 5.5, 0.0099, 999.999, 12345.1, 3333333.33333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 9, values); if (dpiTest__populateTable(testCase, "Vector64Col", &vectorInfo, "ORA-51803:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4416() // Insert int8 vector into float32 column and verify. //----------------------------------------------------------------------------- int dpiTest_4416(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector32Col from TestVectors"; int8_t values[] = {28, -10, 0, 40, 50, 60, 70, 80, 90, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 10, values); if (dpiTest__populateTable(testCase, "Vector32Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4417() // Insert Int8 Vector into Float64 column and verify. //----------------------------------------------------------------------------- int dpiTest_4417(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector64Col from TestVectors"; int8_t values[] = {28, -10, 0, 40, 50, 60, 70, 80, 90, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 10, values); if (dpiTest__populateTable(testCase, "Vector64Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4418() // Insert float32 Vector into Int8 column and verify. //----------------------------------------------------------------------------- int dpiTest_4418(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector8Col from TestVectors"; float values[] = {-99, -104, 0, 1, 2, 5, -99, 9, 12, 33}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 10, values); if (dpiTest__populateTable(testCase, "Vector8Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4419() // Insert float32 Vector into float64 column and verify. //----------------------------------------------------------------------------- int dpiTest_4419(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector64Col from TestVectors"; float values[] = {-99.9, -104.1, -0.1234, 1.9, 222.222, 5.5, 0.0099, 999.999, 12345.1, 333333.333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 10, values); if (dpiTest__populateTable(testCase, "Vector64Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4420() // Insert float64 Vector into Int8 column and verify. //----------------------------------------------------------------------------- int dpiTest_4420(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector8Col from TestVectors"; double values[] = {-99, -104, 0, 1, 2, 5, -99, 9, 12, 33}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 10, values); if (dpiTest__populateTable(testCase, "Vector8Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4421() // Insert float64 Vector into float32 column and verify. //----------------------------------------------------------------------------- int dpiTest_4421(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select Vector32Col from TestVectors"; double values[] = {-91, -104, -0, 1, 2, 5, 0.0, 93333, 1112, 333333}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 10, values); if (dpiTest__populateTable(testCase, "Vector32Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4422() // Insert varchar into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4422(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexAllCol from TestVectors"; char *insVector = "[1, 2, 3]"; int8_t values[] = {1, 2, 3}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 3, values); if (dpiTest__populateTableViaType(testCase, "VectorFlexAllCol", insVector, DPI_ORACLE_TYPE_VARCHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4423() // Insert char into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4423(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex32Col from TestVectors"; const char *insVector = "[-99991.1111111, -22.33, 333.999]"; float values[] = {-99991.1111111, -22.33, 333.999}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 3, values); if (dpiTest__populateTableViaType(testCase, "VectorFlex32Col", insVector, DPI_ORACLE_TYPE_CHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4424() // Insert nchar into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4424(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex8Col from TestVectors"; const char *insVector = "[-1, 0, 127]"; int8_t values[] = {-1, 0, 127}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 3, values); if (dpiTest__populateTableViaType(testCase, "VectorFlex8Col", insVector, DPI_ORACLE_TYPE_NCHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4425() // Insert nvarchar into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4425(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex64Col from TestVectors"; const char *insVector = "[-0.123456789101112, 0.123456789101112," "-1234567.12345678, 9999999.99999999]"; double values[] = {-0.123456789101112, 0.123456789101112, -1234567.12345678, 9999999.99999999}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT64, 4, values); if (dpiTest__populateTableViaType(testCase, "VectorFlex64Col", insVector, DPI_ORACLE_TYPE_NVARCHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4426() // Insert raw into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4426(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexAllCol from TestVectors"; const char *insVector = "[-99991.1111111, -22.33, 333.999]"; float values[] = {-99991.1111111, -22.33, 333.999}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 3, values); if (dpiTest__populateTableViaType(testCase, "VectorFlexAllCol", insVector, DPI_ORACLE_TYPE_LONG_VARCHAR, DPI_NATIVE_TYPE_BYTES, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4427() // Insert unsupported datatype (RAW) into Vector column and verify // (error ORA-00932:). //----------------------------------------------------------------------------- int dpiTest_4427(dpiTestCase *testCase, dpiTestParams *params) { const char *insVector = "[-99991.1111111, -22.33, 333.999]"; if (dpiTest__populateTableViaType(testCase, "VectorFlexAllCol", insVector, DPI_ORACLE_TYPE_RAW, DPI_NATIVE_TYPE_BYTES, "ORA-00932:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4428() // Insert CLOB into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4428(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlexAllCol from TestVectors"; const char *insVector = "[-99991.1111111, -22.33, 333.999]"; float values[] = {-99991.1111111, -22.33, 333.999}; dpiVectorInfo vectorInfo; dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 3, values); if (dpiTest__populateTableViaType(testCase, "VectorFlexAllCol", insVector, DPI_ORACLE_TYPE_CLOB, DPI_NATIVE_TYPE_LOB, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4429() // Insert Json array into Vector column and verify. //----------------------------------------------------------------------------- int dpiTest_4429(dpiTestCase *testCase, dpiTestParams *params) { const char *selectSql = "select VectorFlex32Col from TestVectors"; const char *insertSql = "insert into TestVectors (IntCol, VectorFlex32Col) values(1, :1)"; float values[] = {-0.12345, -99991.11111, -22.33, 333.999}; dpiDataBuffer inNodeData[5]; uint8_t i, numElements = 4; dpiVectorInfo vectorInfo; dpiJsonNode inNodes[5]; dpiData *data; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 4) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiTest__deleteVectorTable(testCase, conn) < 0) return DPI_FAILURE; // prepare node structure memset(inNodes, 0, sizeof(inNodes)); memset(inNodeData, 0, sizeof(inNodeData)); for (i = 0; i < numElements; i++) { inNodes[i].value = &inNodeData[i]; inNodes[i].oracleTypeNum = DPI_ORACLE_TYPE_NUMBER; inNodes[i].nativeTypeNum = DPI_NATIVE_TYPE_DOUBLE; inNodeData[i].asDouble = values[i]; } inNodes[numElements].value = &inNodeData[numElements]; inNodes[numElements].oracleTypeNum = DPI_ORACLE_TYPE_JSON_ARRAY; inNodes[numElements].nativeTypeNum = DPI_NATIVE_TYPE_JSON_ARRAY; inNodeData[numElements].asJsonArray.numElements = numElements; inNodeData[numElements].asJsonArray.elements = &inNodes[0]; inNodeData[numElements].asJsonArray.elementValues = &inNodeData[0]; if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_JSON, DPI_NATIVE_TYPE_JSON, 1, 100, 1, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); data->isNull = 0; if (dpiJson_setValue(dpiData_getJson(data), &inNodes[numElements]) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_COMMIT_ON_SUCCESS, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); // query and validate the data dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_FLOAT32, 4, values); if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4430() // Update Vector Int8 column and verify. //----------------------------------------------------------------------------- int dpiTest_4430(dpiTestCase *testCase, dpiTestParams *params) { const char *updateSql = "update TestVectors set Vector8Col = :1 where IntCol = 1"; const char *selectSql = "select Vector8Col from TestVectors"; int8_t values[] = {28, -10, 0, 40, 50, 60, 70, 80, 90, 127}; int8_t updValues[] = {-128, -10, -5, -1, 0, 10, 5, 100, 1, 2}; dpiVectorInfo vectorInfo; dpiVector *vec; dpiData *data; dpiConn *conn; dpiStmt *stmt; dpiVar *inVar; // insert and verify inserted vector is correct dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 10, values); if (dpiTest__populateTable(testCase, "Vector8Col", &vectorInfo, NULL) < 0) return DPI_FAILURE; if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; // update table and verify update is correct dpiTest__getVectorInfo(&vectorInfo, DPI_VECTOR_FORMAT_INT8, 10, updValues); if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_newVector(conn, &vectorInfo, &vec) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_newVar(conn, DPI_ORACLE_TYPE_VECTOR, DPI_NATIVE_TYPE_VECTOR, 1, 0, 0, 0, NULL, &inVar, &data) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVar_setFromVector(inVar, 0, vec) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, updateSql, strlen(updateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_bindByPos(stmt, 1, inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_COMMIT_ON_SUCCESS, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTest__verifySelect(testCase, selectSql, &vectorInfo) < 0) return DPI_FAILURE; // cleanup if (dpiVar_release(inVar) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiVector_release(vec) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // main() //----------------------------------------------------------------------------- int main(int argc, char **argv) { dpiTestSuite_initialize(4400); dpiTestSuite_addCase(dpiTest_4400, "call public functions with Vector set to NULL"); dpiTestSuite_addCase(dpiTest_4401, "insert and fetch int8 vector col"); dpiTestSuite_addCase(dpiTest_4402, "insert and fetch float32 vector col"); dpiTestSuite_addCase(dpiTest_4403, "insert and fetch float64 vector col"); dpiTestSuite_addCase(dpiTest_4404, "insert and fetch flex int8 vector col"); dpiTestSuite_addCase(dpiTest_4405, "insert and fetch flex float32 vector col"); dpiTestSuite_addCase(dpiTest_4406, "insert and fetch flex float64 vector col"); dpiTestSuite_addCase(dpiTest_4407, "insert and fetch flex type (int8) vector col"); dpiTestSuite_addCase(dpiTest_4408, "insert and fetch flex type (float32) vector col"); dpiTestSuite_addCase(dpiTest_4409, "insert and fetch flex type (float64) vector col"); dpiTestSuite_addCase(dpiTest_4410, "insert and fetch flex All (int8) vector col"); dpiTestSuite_addCase(dpiTest_4411, "insert and fetch flex All (float32) vector col"); dpiTestSuite_addCase(dpiTest_4412, "insert and fetch flex All (float64) vector col"); dpiTestSuite_addCase(dpiTest_4413, "verify int8 vector col num dimensions"); dpiTestSuite_addCase(dpiTest_4414, "verify float32 vector col num dimensions"); dpiTestSuite_addCase(dpiTest_4415, "verify float64 vector col num dimensions"); dpiTestSuite_addCase(dpiTest_4416, "insert int8 vector into float32 col"); dpiTestSuite_addCase(dpiTest_4417, "insert int8 vector into float64 col"); dpiTestSuite_addCase(dpiTest_4418, "insert float32 vector into int8 col"); dpiTestSuite_addCase(dpiTest_4419, "insert float32 vector into float64 col"); dpiTestSuite_addCase(dpiTest_4420, "insert float64 vector into int8 col"); dpiTestSuite_addCase(dpiTest_4421, "insert float64 vector into float32 col"); dpiTestSuite_addCase(dpiTest_4422, "insert varchar into vector"); dpiTestSuite_addCase(dpiTest_4423, "insert char into vector"); dpiTestSuite_addCase(dpiTest_4424, "insert nchar into vector"); dpiTestSuite_addCase(dpiTest_4425, "insert nvarchar into vector"); dpiTestSuite_addCase(dpiTest_4426, "insert long varchar into vector"); dpiTestSuite_addCase(dpiTest_4427, "insert long varchar into vector"); dpiTestSuite_addCase(dpiTest_4428, "insert CLOB into vector"); dpiTestSuite_addCase(dpiTest_4429, "insert Json array into vector"); dpiTestSuite_addCase(dpiTest_4430, "update vector and verify"); return dpiTestSuite_run(); } odpi-5.6.4/test/test_4500_sessionless_txn.c000066400000000000000000000247521510466437300206010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // Copyright (c) 2025, Oracle and/or its affiliates. // // This software is dual-licensed to you under the Universal Permissive License // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose // either license. // // If you elect to accept the software under the Apache License, Version 2.0, // the following applies: // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // test_4500_sessionless_txn.c // Test suite for all the Sessionless transaction related test cases. //----------------------------------------------------------------------------- #include "TestLib.h" //----------------------------------------------------------------------------- // dpiTest_4500() // Call each of the Sessionless Transaction public functions with the // parameter set to NULL (error DPI-1002). //----------------------------------------------------------------------------- int dpiTest_4500(dpiTestCase *testCase, dpiTestParams *params) { dpiSessionlessTransactionId transactionId; const char *expectedError = "DPI-1002:"; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 6) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; dpiConn_beginSessionlessTransaction(NULL, &transactionId, 5, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_resumeSessionlessTransaction(NULL, &transactionId, 5, 0); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; dpiConn_suspendSessionlessTransaction(NULL); if (dpiTestCase_expectError(testCase, expectedError) < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4501() // Call dpiConn_resumeSessionlessTransaction with an invalid transaction id // (error ORA-26218). //----------------------------------------------------------------------------- int dpiTest_4501(dpiTestCase *testCase, dpiTestParams *params) { dpiSessionlessTransactionId transactionId; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 6) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; strcpy(transactionId.value, "not_a_valid_transaction_id"); transactionId.length = strlen(transactionId.value); dpiConn_resumeSessionlessTransaction(conn, &transactionId, 5, 0); if (dpiTestCase_expectError(testCase, "ORA-26218:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4502() // Call dpiConn_beginSessionlessTransaction with zero timeout value // (error ORA-26206). //----------------------------------------------------------------------------- int dpiTest_4502(dpiTestCase *testCase, dpiTestParams *params) { dpiSessionlessTransactionId transactionId; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 6) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; strcpy(transactionId.value, "txn_id_4502"); transactionId.length = strlen(transactionId.value); dpiConn_beginSessionlessTransaction(conn, &transactionId, 0, 0); if (dpiTestCase_expectError(testCase, "ORA-26206:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4503() // Begin a sessionless transaction and suspend it, then use a different // connection to resume. //----------------------------------------------------------------------------- int dpiTest_4503(dpiTestCase *testCase, dpiTestParams *params) { dpiSessionlessTransactionId transactionId; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 6) < 0) return DPI_FAILURE; // begin and suspend on one connection strcpy(transactionId.value, "txn_id_4503"); transactionId.length = strlen(transactionId.value); if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_beginSessionlessTransaction(conn, &transactionId, 5, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_suspendSessionlessTransaction(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // resume on a new connection and commit if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; if (dpiConn_resumeSessionlessTransaction(conn, &transactionId, 5, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_commit(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_release(conn) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4504() // Begin a sessionless transaction and suspend it, then wait for the timeout // to expire and attempt resume the transaction (error ORA-26218). //----------------------------------------------------------------------------- int dpiTest_4504(dpiTestCase *testCase, dpiTestParams *params) { dpiSessionlessTransactionId transactionId; dpiConn *conn; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 6) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; strcpy(transactionId.value, "txn_id_4504"); transactionId.length = strlen(transactionId.value); if (dpiConn_beginSessionlessTransaction(conn, &transactionId, 1, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_suspendSessionlessTransaction(conn) < 0) return dpiTestCase_setFailedFromError(testCase); sleep(3); dpiConn_resumeSessionlessTransaction(conn, &transactionId, 2, 0); if (dpiTestCase_expectError(testCase, "ORA-26218:") < 0) return DPI_FAILURE; return DPI_SUCCESS; } //----------------------------------------------------------------------------- // dpiTest_4505() // After performing suspend/resume of a sessionless transaction, verify // that a rollback has taken place. //----------------------------------------------------------------------------- int dpiTest_4505(dpiTestCase *testCase, dpiTestParams *params) { const char *insertSql = "insert into TestTempTable values (4506, 'test1')"; const char *truncateSql = "truncate table TestTempTable"; const char *selectSql = "select * from TestTempTable"; dpiSessionlessTransactionId transactionId; uint32_t bufferRowIndex; uint64_t rowCount; dpiConn *conn; dpiStmt *stmt; int found; if (dpiTestCase_setSkippedIfVersionTooOld(testCase, 0, 23, 6) < 0) return DPI_FAILURE; if (dpiTestCase_getConnection(testCase, &conn) < 0) return DPI_FAILURE; // truncate table if (dpiConn_prepareStmt(conn, 0, truncateSql, strlen(truncateSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // begin transaction and insert data if (dpiConn_beginSessionlessTransaction(conn, &transactionId, 5, 0) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_prepareStmt(conn, 0, insertSql, strlen(insertSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); // suspend and then immediately resume transaction if (dpiConn_suspendSessionlessTransaction(conn) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiConn_resumeSessionlessTransaction(conn, &transactionId, 5, 0) < 0) return dpiTestCase_setFailedFromError(testCase); // rollback transaction if (dpiConn_rollback(conn) < 0) return dpiTestCase_setFailedFromError(testCase); // verify that the rollback has taken place if (dpiConn_prepareStmt(conn, 0, selectSql, strlen(selectSql), NULL, 0, &stmt) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_execute(stmt, DPI_MODE_EXEC_DEFAULT, NULL) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_fetch(stmt, &found, &bufferRowIndex) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiStmt_getRowCount(stmt, &rowCount) < 0) return dpiTestCase_setFailedFromError(testCase); if (dpiTestCase_expectIntEqual(testCase, rowCount, 0) < 0) return DPI_FAILURE; if (dpiStmt_release(stmt) < 0) return dpiTestCase_setFailedFromError(testCase); return DPI_SUCCESS; } int main(int argc, char **argv) { dpiTestSuite_initialize(4500); dpiTestSuite_addCase(dpiTest_4500, "verify API with NULL parameters"); dpiTestSuite_addCase(dpiTest_4501, "verify with invalid transaction ID"); dpiTestSuite_addCase(dpiTest_4502, "verify with zero timeout value"); dpiTestSuite_addCase(dpiTest_4503, "resume transaction on a different connection"); dpiTestSuite_addCase(dpiTest_4504, "verify timeout expiry"); dpiTestSuite_addCase(dpiTest_4505, "verify rollback"); return dpiTestSuite_run(); } odpi-5.6.4/test/valgrind/000077500000000000000000000000001510466437300152575ustar00rootroot00000000000000odpi-5.6.4/test/valgrind/run.sh000077500000000000000000000032331510466437300164230ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2017, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #------------------------------------------------------------------------------ # # Sample script for running valgrind. # #------------------------------------------------------------------------------ echo "Running valgrind on $1..." valgrind \ --num-callers=40 \ --error-markers=-------------------------,------------------------- \ --redzone-size=256 \ --leak-check=yes \ --track-origins=yes \ --free-fill=0xaa \ --leak-check=full \ --error-limit=no \ --trace-children=yes \ --show-leak-kinds=definite,possible \ --suppressions=$(dirname $0)/suppressions.txt \ --gen-suppressions=all \ $@ odpi-5.6.4/test/valgrind/suppressions.txt000066400000000000000000000123241510466437300205770ustar00rootroot00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2017, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # #------------------------------------------------------------------------------ # # List of valgrind suppressions for ODPI-C library. Errors reported from within # OCI are ignored as these cannot be resolved by ODPI-C. # # Errors expected from the test suite are also ignored. #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ # OCI ERRORS #------------------------------------------------------------------------------ { suppress_oci_cond Memcheck:Cond ... obj:*/*clntsh* ... } { suppress_oci_leak Memcheck:Leak ... obj:*/*clntsh* ... } { suppress_oci_value8 Memcheck:Value8 ... obj:*/*clntsh* ... } { suppress_oci_addr1 Memcheck:Addr1 ... obj:*/*clntsh* ... } { suppress_oci_addr16 Memcheck:Addr16 ... obj:*/*clntsh* ... } { suppress_OCILobGetLength2__param Memcheck:Param write(buf) ... fun:dpiOci__lobGetLength2 ... } { suppress_OCIPasswordChange_param Memcheck:Param write(buf) ... fun:OCIPasswordChange ... } { suppress_OCIStmtExecute_param Memcheck:Param write(buf) ... fun:OCIStmtExecute ... } { suppress_OCISubscriptionRegister_param Memcheck:Param write(buf) ... fun:dpiOci__subscriptionRegister ... } { suppress_OCISubscriptionUnRegister_param Memcheck:Param write(buf) ... fun:dpiOci__subscriptionUnRegister ... } { suppress_OCITransStart_param Memcheck:Param write(buf) ... fun:dpiOci__transStart ... } { suppress_OCIEnvNlsCreate_leak Memcheck:Leak ... fun:OCIEnvNlsCreate ... } { suppress_OCIServerAttach_leak Memcheck:Leak ... fun:OCIServerAttach ... } #------------------------------------------------------------------------------ # EXPECTED TEST SUITE ERRORS #------------------------------------------------------------------------------ { suppress_test_105_addr4 Memcheck:Addr4 fun:dpiContext__startPublicFn fun:dpiContext_destroy fun:dpiTest_105_destroyTwice ... } { suppress_test_306_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiConn_create fun:dpiTest_306_createInvalidPool ... } { suppress_test_309_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_309_createReleaseTwice ... } { suppress_test_511_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_511_releaseTwice ... } { suppress_test_1100_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1100_releaseTwice ... } { suppress_test_1302_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1302_releaseObjTypeTwice ... } { suppress_test_1400_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1400_releaseObjTwice ... } { suppress_test_1500_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1500_releaseEnqOptionsTwice ... } { suppress_test_1600_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1600_releaseDeqOptionsTwice ... } { suppress_test_1700_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1700_releaseMsgPropsTwice ... } { suppress_test_1902_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_1902_releaseLobTwice ... } { suppress_test_2002_addr8 Memcheck:Addr8 fun:dpiGen__checkHandle fun:dpiGen__startPublicFn fun:dpiGen__release fun:dpiTest_2002_releaseRowIdTwice ... } { suppress_samples_env_leak Memcheck:Leak ... fun:dpiSamples__getEnvValue ... } odpi-5.6.4/util/000077500000000000000000000000001510466437300134475ustar00rootroot00000000000000odpi-5.6.4/util/tracing/000077500000000000000000000000001510466437300150765ustar00rootroot00000000000000odpi-5.6.4/util/tracing/mem_leak.py000077500000000000000000000065531510466437300172360ustar00rootroot00000000000000#! /usr/bin/env python #----------------------------------------------------------------------------- # Copyright (c) 2021, 2022, Oracle and/or its affiliates. # # This software is dual-licensed to you under the Universal Permissive License # (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License # 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose # either license. # # If you elect to accept the software under the Apache License, Version 2.0, # the following applies: # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #----------------------------------------------------------------------------- """ A script to help identify memory leaks. The script argument should be the name of a file containing the trace output when DPI_DEBUG_LEVEL is set to DPI_DEBUG_LEVEL_MEM (32): export DPI_DEBUG_LEVEL=32 ./myprog >& mem.log python mem_leak.py mem.log """ import sys ALLOCATED_STRING = ": allocated " FREED_STRING = ": freed " OCI_ALLOCATED_STRING = ": OCI allocated " OCI_FREED_STRING = ": OCI freed " def check_memory_use(file_name): """ Checks memory use found in the given file. This file is assumed to have been generated by setting DPI_DEBUG_LEVEL to the value 32. """ memory_locations = {} for line in open(file_name): # check for ODPI-C allocation pos = line.find(ALLOCATED_STRING) if pos > 0: parts = line[pos + len(ALLOCATED_STRING):].split() size = int(parts[0]) memory_location = parts[3] memory_locations.setdefault(memory_location, []).append(size) continue # check for ODPI-C free pos = line.find(FREED_STRING) if pos > 0: parts = line[pos + len(FREED_STRING):].split() memory_location = parts[2] memory_locations[memory_location].pop(0) if not memory_locations[memory_location]: del memory_locations[memory_location] continue # check for OCI allocation pos = line.find(OCI_ALLOCATED_STRING) if pos > 0: parts = line[pos + len(OCI_ALLOCATED_STRING):].split() size = int(parts[0]) memory_location = parts[3] memory_locations.setdefault(memory_location, []).append(size) continue # check for OCI free pos = line.find(OCI_FREED_STRING) if pos > 0: parts = line[pos + len(OCI_FREED_STRING):].split() memory_location = parts[2] memory_locations[memory_location].pop(0) if not memory_locations[memory_location]: del memory_locations[memory_location] continue print("Potential Memory Leaks") for memory_location in memory_locations: print(memory_location, "-> size", sum(memory_locations[memory_location])) check_memory_use(sys.argv[1])