A previous bug fix[1] relied on ODBC drivers to properly count down the
`StrLen_or_IndPtr` argument for consecutive calls to `SQLGetData()`.
Apparently, not all drivers handle this correctly, so we cannot assert
they do. Instead we fall back to the old behavior for drivers which
would violate the assertion.
A test against SQLServer (which we currently use in CI) would not make
sense, since the respective drivers do not exhibit that behavior.
Instead we target the regression test especially to a MS Access
database.
Since there is apparently no way to easily create an MS Access database
programmatically, we commit a minimal empty DB which is used for the
regression test, and could also be used by other test cases.
[1] <bccca0b53aa60a62e2988c750fc73c02d109e642>
Closes GH-16587.
* Remove usage of SDWORD, replace with SQLINTEGER
Some different driver managers disagree if this should be 4 or 8 bytes
in size. SQLGetDiagRec expects this to be an SQLINTEGER, so we should
just use that explicitly instead of hoping that it's the same size.
Fixes GH-14367
* Replace SWORD with SQLSMALLINT
While this hasn't caused issues like the SQLINTEGER/SDWORD confusion
has, we should use what SQLDescrimeParam calls for, which is
SQLSMALLINT.
* Missing check: SQLAllocHandle() for the environment wasn't checked in
pdo_odbc_handle_factory(). Add a check similar to the other ones for
SQLAllocHandle().
* Inconsistent check: one of the SQLAllocHandle() calls wasn't checked
for SQL_SUCCESS_WITH_INFO. However, looking at the other uses and the
documentation we should probably check this as well.
Furthermore, since there was a mix of "SQLAllocHandle: reason" and
"SQLAllocHandle (reason)" in the error reporting, I made them
consistently use the first option as that seems to be the most used for
error reporting in this file.
Closes GH-10740.
If `SQLPutData()` *fails*, we should not call `SQLParamData()` again,
because that yields the confusing `HY010` (Function sequence error).
Instead we properly handle `SQLPutData()` errors.
For the given case (paramter length > column length), some drivers let
`SQLPutData()` fail, while others do not. Either behavior seems to
conform to the ODBC specification. Anyhow, we do not want to silently
truncate the given parameter, since that would break the behavior for
drivers which do not fail, but still don't simply truncate the given
parameter. So it is finally up to userland to avoid passing overlong
parameters – with this patch they at least get useful information about
the actual issue.
Closes GH-9541.
Using php_info_print_table_header() for "Foo: bar" looks odd and out of place,
because the whole line is colored. It is also questionable from a HTML
semantics point of view, because it does not described the columns that follow.
The use of this across extensions is inconsistent. It was part of the skeleton,
but ext/date or ext/json already use a regular row.
We implement SQL_ATTR_CONNECTION_DEAD for ODBC and PDO_ODBC.
This is semantically appropriate and should be used whenever the
driver supports it. In the event that it fails or says the connection
isn't dead (which may be inaccurate in some cases), try the old
heuristic.
Closes GH-9353.
A connection string may contain just a single key, but
PHP used ";" as the heuristic to detect if a string was a connection
string versus plain DSN. However, a single-key connection string
would get treated like a DSN name, i.e. "DSN=*LOCAL". This makes it
so that "=" is used, as a connection string must contain a key.
Closes GH-8748.
Because the UID= and PWD= values are appended to the SQLDriverConnect
case when credentials are passed, we have to append them to the string
in case users are relying on this behaviour. However, they must be
quoted, or the arguments will be invalid (or possibly more injected).
This means users had to quote arguments or append credentials to the raw
connection string themselves.
It seems that ODBC quoting rules are consistent enough (and that
Microsoft trusts them enough to encode into the .NET BCL) that we can
actually check if the string is already quoted (in case a user is
already quoting because of this not being fixed), and if not, apply the
appropriate ODBC quoting rules.
This is because the code exists in main/, and are shared between
both ODBC extensions, so it doesn't make sense for it to only exist
in one or the other. There may be a better spot for it.
Closes GH-8307.
When we have a complex connection string (more than a DSN), PHP
appends a UID and PWD if none are present and a username and password
are called, so SQLDriverConnect works as expected.
However, it seems spprintf doesn't allocate with persistence if
required. As a result, it'll be considering leaking and crash PHP on
free when a persistent connection is used.
Closes GH-8110.
If `P->len` is negative (not only when it is `SQL_NULL_DATA`), we must
not go on, because the following code can't deal with that. This means
that the output parameter will be set to `NULL` without any indication
what went wrong, but it's still better than crashing.
Closes GH-7295.
If `SQLDescribeParam()` fails for a parameter, we must not assume
`SQL_LONGVARCHAR` for any param which is not `PDO_PARAM_LOB`. At least
mapping `PDO_PARAM_INT` to `SQL_INTEGER` should be safe, and not
introduce a BC break.
Closes GH-6973.
1. Update: http://www.php.net/license/3_01.txt to https, as there is anyway server header "Location:" to https.
2. Update few license 3.0 to 3.01 as 3.0 states "php 5.1.1, 4.1.1, and earlier".
3. In some license comments is "at through the world-wide-web" while most is without "at", so deleted.
4. fixed indentation in some files before |
PDO drivers allow for it, and procedural ODBC has its own facility
for it, but PDO_ODBC doesn't. If a connection is severed (for example,
on IBM i, ending a databse job, or killing the network connection
elsewhere), a persistent connection could get stuck. This adapts the
procedural ODBC code to PDO for handling connection liveness, so PDO
can reconnect if needed.
A discussion about the method to check liveness is linked; this might
not be the best method, but it's what procedural ODBC uses, so it's
consistent.
Closes GH-6805.
It is not guaranteed, that the driver inserts only a single NUL byte at
the end of the buffer. Apparently, there is no way to find out the
actual data length in the buffer after calling `SQLGetData()`, so we
adjust after the next `SQLGetData()` call.
We also prevent PDO::ODBC_ATTR_ASSUME_UTF8 from fetching garbage, by
fetching all chunks with the same C type.
Closes GH-6716.
Instead of requiring the type to be determined in advance by the
describer function and then requiring get_col to return a buffer
of appropriate type, allow get_col to return an arbitrary zval.
See UPGRADING.INTERNALS for a more detailed description of the
change.
This makes the result fetching simpler, more efficient and more
flexible. The general possibility already existed via the special
PDO_PARAM_ZVAL type, but the usage was very inconvenient and/or
inefficient. Now it's possible to easily implement behavior like
"return int if it fits, otherwise string" and to avoid any kind
of complex management of temporary buffers.
This also fixes bug #40913 (our second highest voted bug of all
time, for some reason). PARAM_LOB result bindings will now
consistently return a stream resource, independently of the used
database driver.
I've tried my best to update all PDO drivers for this change, but
some of the changes may be broken, as I cannot test or even build
some of these drivers (in particular PDO dblib and PDO oci).
Fixes are appreciated -- a working CI setup would be even more
appreciated ;)