We need to read the entire contents of the CLOB in Oracle backend and
not just the number of bytes corresponding to its length in characters
as returned by OCILobGetLength() because this may (and will) be strictly
less than its full size in bytes for any encoding using multiple bytes
per character, such as the de facto standard UTF-8.
Also make reading CLOBs more efficient by doing what Oracle
documentation suggests and using the LOB chunk size for reading.
Finally, add a unit test checking that using non-ASCII strings in UTF-8
(which had to be enabled for the CI) with CLOBs does work.
This commit is best viewed ignoring whitespace-only changes.
This will allow to use it for creating functions as well as procedures
(and also procedures with a name other than "soci_test" if this is ever
needed).
Don't do anything in prepare_for_describe() if the statement is not a
SELECT, as it is not necessary and results in "ORA-24333: zero iteration
count" error, since there's nothing to describe.
This commit is best viewed ignoring whitespace-only changes.
Closes#1119.
Improvements to connection string handling: don't duplicate parsing code
in Firebird, Oracle, PostgreSQL and SQLite backends.
Also allow using connection_parameters::set_option() to set some option
instead of having to specify it in the connection string itself.
See #1176.
This doesn't help with the problem corrected in the previous commit but
it still seems unnecessary to allocate LOBs which should be never used
because the corresponding indicator is null.
Although the test passed with Oracle 11 used in the CI job, it fails
with both (old) Oracle 18 and latest Oracle 23 because using xmltype()
with null values doesn't work.
Avoid doing it by testing for null explicitly in the test.
This is similar to 96668e9a (Don't pass null pointers to memcpy() in
trivial_blob_backend code, 2024-10-16) and done for the same reason:
when there is no data to read/write, the buffer pointer may be null and
passing it to memcpy() triggers UBSAN error, so avoid doing it.
oracle_standard_into_type_backend::type_ may not be initialized when
clean_up() is called, and comparing its value with x_xmltype and other
constants was triggering undefined behaviour in this case, so avoid
doing it by checking if ociData_ is non-null before doing it.
Also modify oracle_standard_use_type_backend in a similar way, even if
it doesn't suffer from this problem, for symmetry.
For now this will be only used to create the connection string in libpq
format, but might be used for the other backends too in the future, so
add it to the core.
This is similar to get_option() but removes the option from the
connection parameters and will be used in PostgreSQL backend, which
needs to pass the string with only the options known to libpq, but not
those specific to SOCI, when opening the database connection soon.
Even though these functions are trivial, still collect them in a single
place instead of repeating them in several different ones.
This will also make replacing them with something less trivial, e.g.
using ICU, simpler in the future.
We don't support ancient versions of PostgreSQL without single row mode
support, so don't bother checking whether it is available.
This should have been part of e3bb60e1 (Remove vestigial traces of
SOCI_POSTGRESQL_NOSINLGEROWMODE, 2024-03-27).
Don't duplicate the code for parsing space-separated possibly quoted
words in SQLite3 backend but just use the common function for it too.
Also correct handling of some boolean parameters, where previously
specifying any value, even "0" or "false", would enable it and document
the exact values accepted for them.
Add tests checking that parsing connection string works as expected.
At least some backends, e.g. SQLite3, allow specifying boolean options
without parameters to enable them (e.g. just "readonly" instead of
"readonly=1") and this seems to makes sense, so do allow such syntax.
However still forbid values without names, e.g. "=1", which was silently
allowed before even though it didn't make any sense.
Also effectively inline getWordUntil() into the function calling it, as
it makes it simpler to distinguish between having a value and not.
Adjust the tests to the new behaviour.
Replace the use of std::istringstream with the SOCI function which is
marginally more efficient but, more importantly, more correct, as it
checks for overflow.
Replace the use of Oracle-specific get_key_value() with the common
extract_options_from_space_separated_string() to ensure consistent
behaviour across the backends and fix a bug with dereferencing an
invalid iterator (one past end) in Oracle-specific code.
Closes#1175.
Move code present in Firebird backend, which is just one of several
different versions of the code doing the same thing, into a common core
class to allow reusing it in the other backends later.
Also add tests for this code now that it is actually testable.
This prepares for its reuse elsewhere.
Note that ideally the checks using this macro should be rewritten to use
CATCH matchers instead, which would result in much better output in case
of a failing test, but for now don't change anything and just move the
code around.
Prepare for reusing them from other source files.
Note that this requires using test_context from test-assert.h, which now
has to include test-context.h.
This allows to compile them once, instead of doing it for every backend:
while this doesn't matter for the CI builds, recompiling common-tests.h
a dozen times enormously slowed down local builds using all backends.
Now it is compiled only once, as test-common.cpp, and all the other
tests (except for the "empty" one) just link with the resulting library.
Also extract some parts of this file into separate headers, that can be
included only by the tests that actually need them.
Note that the entire test-common.cpp probably ought to be split into
multiple files, to speed up its build too, but this can be done later.
This is the only place where they're used so far and it doesn't make
sense to compile them many times over when building the tests for the
other backends.
If these helpers are needed in the other backends tests, we should
extract them into their own header and include it as necessary.
This definition was missing from blob.cpp and used wrong case in a few
other files, which didn't matter until recent changes exporting Oracle
backend classes, but results in link errors under Windows now.
UBSAN gives nonsensical errors for the ODBC job running under Ubuntu
18.04, e.g. it complains that
src/core/session.cpp:246:16: runtime error: member call on address
0x607000000250 which does not point to an object of type
'session_backend'
1: 0x607000000250: note: object is of type 'soci::odbc_session_backend'
which doesn't make any sense because odbc_session_backend is an object
of type session_backend. But apparently something is broken in this
compiler version, so disable UBSAN for this job for now.