After 2 days battling, I try asking help here. I'm using unixODBC (2.2.11) to work with DB2 (iSeries) and PHP (5.3) on a CentOS 5.4 server. I guess it's since the upgrade of PHP from 5.1 to 5.3, I get PHP to segfault on certain queries. After some investigation, I discovered the problem appears on some queries with long char fields, for example with this table :
TABLE (
CONTRACTID NUMERIC,
SOMETEXT CHAR(583)
)
This simple piece of code provokes the segfault :
try {
$conn = new PDO("odbc:".$dsn, $username, $password, array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
);
}
catch (Exception $e) {
echo $e->getMessage();
}
$sql = 'SELECT * FROM LIB.TABLE ';
$stmt = $conn->prepare($sql);
$vals = $stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Is there any column length limit or a bug with unixODBC and/or PHP >= 5.1 ?
This web application worked quite great, then I got into this problem..
Btw, I tested with a more up-to-date 64bits CentOS 6.2 machine with unixODBC 2.2.14 and PHP 5.3, and the problem is the same.
Any help greatly appreciated,
Thanks
fabien
UPDATE :
Using the PHP odbc functions, it works :
$conn = odbc_connect($dsn, $username, $password);
$res = odbc_exec($conn, $sql);
$rows = odbc_fetch_array($res);
So the problem is more tied to PDO, any idea?
Ran into the same problem here. Found that the 64-bit php-odbc module is causing the seg fault when returning a field with a NULL value. A workaround is to coalesce each field in which a NULL value could exist. It's not a good solution. I'm looking at the php-odbc.c code, but I can't guarantee a fix.
Workaround:
SELECT COALESCE(CHAR(fieldname),'') FROM ...
I think I'm going to replace this server with a 32-bit version. I have others that work just fine.
I had a similar problem on Centos 6.3 with Vertica 6 and the UnixODBC that comes with Centos, PHP would just segfault. So I ran strace php mytest.php and found that it tried to find and open /usr/lib64/libodbccr.so.1
However Centos 6.3 only has libodbccr.so.2
So the quick and dirty fix is to do the following in: /usr/lib64
ln -s libodbccr.so.2 libodbccr.so.1
Use at your own risk!
I cannot say I know of any issues in pdo (which I don't use anyway) or unixODBC or the DB2 driver. I'm not sure from your email if your first platform is using 64 bit builds or 32 bit builds but ODBC changed when Microsoft added 64 bit support (see SQLLEN/SQLULEN and 32/64 bit platforms and 64-bit ODBC). Basically, some ODBC APIs had a type changed from SQLINTEGER to SQLLEN and an SQLLEN is 64bits in a 64 bit build and 32 bits in a 32 bit build. However, as no one was to know Microsoft was going to do this and some of these arguments were actually described in the spec as 32 bit quantities some ODBC driver writers had already built ODBC drivers for 64 bit platforms using 32 bit quantities for these arguments. Obviously, if you mix an application or driver manager built one way with a driver built the other way all hell can break lose and you very well may get segfaults. So, firstly, if you are using 64 bit binaries you need to check your ODBC driver was built correctly - speak to IBM.
unixODBC 2.2.11 is rather old now and I know issues have been fixed but I'm still using it extensively and only have one small issue in the cursor library. Anyway, you tried 2.2.14 and the problem was the same. I doubt it is an unixODBC issue but that is only based on my extensive experience with it and not because I know for a fact.
Now, assuming you don't fall into the situation outlined above you can do a number of things. Try enabling logging in unixODBC then you can see what ODBC calls are being made and which one fails. You might also get a clue from the arguments passed as to what might be going on. You enable logging by adding the following to your odbcinst.ini file:
[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log
Look for a call to SQLBindCol or SQLGetData for the column in question. If this does not get you anywhere you can try pasting the end of it here and I'll look at it.
If you can run your PHP program from the command line and you install gdb you can run it under gdb and it will show you a stack dump of where the problem occurred. Just do gdb /path/to/php then type r myscript.php and enter to run it and when it segfaults you can use the bt (backtrace) command to show the stack. That should identify which code is causing the segfault although it is not necessarily that code which is fault (e.g., if php passed a pointer to a buffer of 10 bytes but lies and says it is 100 bytes the code which writes off the end is not at fault).
Related
I upgraded my PHP 5.6.30 (https://www.apachefriends.org/de/download.html) to PHP 7.0 (https://bitnami.com/stack/wamp/installer)
Everything worked fine so far and it reduces the loading time from my Page from 1,2 seconds to ~300 ms, when I use a MySQL-Database. But now I'm trying to connect to a MSSQL-Database with the following simple script, that worked fine with my old installation (PHP 5.6):
<?php
//Use the machine name and instance if multiple instances are used
$server = 'Server-Adress';
$user = '';
$pass = '';
//Define Port
$port='Port=1433';
$database = 'Databasename';
$connection_string = "DRIVER={SQL Server};SERVER=$server;$port;DATABASE=$database";
$conn = odbc_connect($connection_string,$user,$pass);
if ($conn) {
echo "Connection established.";
} else{
die("Connection could not be established.");
}
$sql = "SELECT * FROM st3_200 WHERE identifier = 1";
$result = odbc_exec($conn,$sql);
// Get Data From Result
while ($data[] = odbc_fetch_array($result));
// Free Result
odbc_free_result($result);
// Close Connection
odbc_close($conn);
// Show data
print_r($data);
?>
But now I got an error in my logs that says:
[Thu Dec 10 11:55:26.629956 2015] [:error] [pid 260:tid 968] [client
::1:63003] PHP Fatal error: Uncaught Error: Call to undefined
function odbc_connect() in
C:\Bitnami\wampstack-7.0.0-0\apache2\htdocs\test\query.php:11\nStack
trace:\n#0 {main}\n thrown in
C:\Bitnami\wampstack-7.0.0-0\apache2\htdocs\test\query.php on
line 11
First I thought, that my php.ini has a missing extension, so I enabled "extension=php_pdo_odbc.dll"
the difference from the php.ini in the 5.6 version is there is the extension:
"extension=php_mssql.dll" enabled. But I can't find them in the new PHP 7.0.ini
So my intension is there is no existing driver for odbc and PHP 7 yet?
I found some driver for Linux here:
https://aur.archlinux.org/packages/php7-odbc/
But I need something for my Windows environment.
Does anyone had the same issue and has already fixed it?
Thank und Greeting
Domi
Take a look in your php.ini, the string
extension=php_odbc.dll
seems to be missing in new installations, at least i had to add it manually in my new XAMPP installation (7.0.1)
and accidently just activated the pdo_odbc.dll
PHP7 has a few modules disabled by default that were previously enabled in PHP5.
It's an easy fix though since the extension should already exist in the \ext\ folder that came with PHP7. You just need to modify your php.ini file to include the line:
extension=php_odbc.dll
The line above is not already present and commented out; you actually need to add it!
PHP looks for the php.ini file in C:\Windows\ but it may also be located elsewhere on your machine. So check both C:\Windows\ and C:\php\ or where ever else you may have installed PHP.
After making the change you can check the results from the command line like this:
C:\php\php.exe -m
or (after restarting the web server / machine) from a .phtml file like this:
<? phpinfo(); ?>
That will output a list of enabled modules which should now include odbc; if not, then you may have modified the wrong php.ini file (keep looking) or forgot to restart the web server / machine.
Tips:
If you have a non-standard installation, you can use an absolute path like this:
extension=C:\php7x64\ext\php_odbc.dll
extension=php_mssql.dll (or extension=php_sqlsrv_56_nts.dll if you get it from Microsoft Drivers for PHP), is your problem: the Microsoft SQL driver for PHP 7 is not yet ready, the latest ETA is late January for the beta.
It looks like the cause of the delay is the intention to include SQL 2016 in that driver so you can migrate easier in the future.
UPDATE (2016/02/12):
As stated here (meet-bhagdev reply), there is an "early technical preview" of the PHP sqlsrv driver for Windows available on github.
Open your php.ini file and uncomment or add the following lines:
extension_dir = "C:\PHP\ext" ;<- your PHP path
extension=php_pdo_odbc.dll
extension=php_odbc.dll
Reset Internet Information Services:
On command prompt with admin rights type:
iisreset
This fixed the problem for me.
As an addition to Adrian B`s which mentions the official driver, you can also check https://github.com/thomsonreuters/msphpsql
This is an unofficial port. However there are limitations for the time being.
Supports only sqlsrv ODBC but not PDO
Doesn`t support ZTS, only NTS
Supports only x86
It supports a subset of ODBC functions , you can see the list on the page.
We need x86 driver from Microsoft.
http://www.microsoft.com/ja-jp/download/details.aspx?id=13255
*Sorry, 'ja-jp' is mine. Please select your country. There are 2 drivers, one is 32bit, but we need 64bit(x86) version.
Then we could set "ODBC data source (64bit)". It appears on the window.
Last, check your web. Maybe it works.
Mar. 29th. 2016 Naio
I guess you was right, you need download the SQL Server ODBC driver for your PHP client platform and OS.
Here is the link for the similar issue: Call to undefined function odbc_connect()
also you can try to install this connector for MySQL (if you use MySQL): Connector/ODBC
or if you use MSSQL: ODBC Driver 11 for SQL Server
I know this question is rather old. But I've come across the same issue recently ...
#Naio is right : there are indeed different versions of ODBC drivers, based on the architecture (32bits or 64bits). The driver that PHP uses depends on its own version.
In other words, if you are using a 32bits ODBC environement, make sure to use a 32bits version of PHP ...
My guess is that, by switching from PHP 5.6 to PHP 7.0 you also switched from a 32bits version to a 64bits version.
I'm trying to connect to a Sybase database with PHP5. I believe I've successfully compiled PHP with PDO_DBLIB, as phpinfo() lists dblib under PDO drivers, and freetds as the pdo_dblib flavour.
However, when I try to test a connection, I get an error reading:
'PDOException' with message 'could not find driver'
I'm trying to connect to a server on my LAN with this code:
$dbh = new PDO("sybase:host=192.168.1.xxx;dbname=[database-name]", '[user]', '[pass]');
Any suggestions would be greatly appreciated!
You should use dblib instead of sybase, like this:
$dbh = new PDO("dblib:host=192.168.1.xxx;dbname=[database-name]", '[user]', '[pass]');
PDO wouldn't work, or at least there is no PDO Sybase support for php. On Windows, you can use ODBC, and PDO_SQLSRV or PDO_ODBC, it might sound weird, but it should work.
Second option and I would recommend it, is to connect directly to Sybase (SqlAnywhere), but you need to install SQL Anywhere PHP Module
If you are using Ubuntu you can put the LD_LIBRARY_PATH inside envvars and it seems to read... still trying to find a way to get it to stick on RHEL based systems... Windows I am not too sure about I would hope you could set a system wide variable under
my computer -> properties -> advanced options
If are using RHEL based systems it might be better to include the:
export LD_LIBRARY_PATH=/path/to/library/ in the httpd restart script (check to see if it loads /etc/sysconfig/httpd and if so add the line in there - now restart apache and you should see some activity.
I'm new in sql anywhere, currently I'm trying to connect using PHP.
This is what I've got so far:
$conn = sqlanywhere_connect ( "UID=usr;PWD=pass;ENG=serv;DBN=bd_name;COMMLINKS=TCPIP{HOST=10.1.1.189:2638}" );
SQL Anywhere is installed on another machine, where I can't run apache, website is running on localhost (xampp). This is only for test, when website would be ready I will connect to correct db.
This is error I've got:
Warning: sqlanywhere_connect(): The SQLAnywhere client libraries could not be loaded. Please ensure that dbcapi.dll can be found in your PATH environment variable. in C:\xampp\htdocs\core\cache\includes\elements\modsnippet\25.include.cache.php on line 21
I haven't got dbcapi.dll file, but I'm not sure I should have it.
In documentation I couldnt find this file (SQL Anywhere 10 which I've got), but for SQL Anywhere 11 I could find pages where was info about this file.
To use sqlanywhere_connect I've download SQL Anywhere module for curren ver. of PHP onto my machine and I've add it to php.ini file.
What should I do? Should I download missing file? Would it be enough or I could get more errors asking for other files?
I had a similar problem and the solution proposed here:
https://groups.google.com/forum/#!msg/sql-anywhere-web-development/zK9Tf-X3cYk/GAoqK2DnB9EJ
worked for me.
Specifically, my xampp + php needed the 32 bit dbcapi.dll but when I installed SQL Anywhere 12 I neglected to check the box to install the 32 bit version as well. Re-installing, chossing "modify" and installing the 32 bit SQL Anywhere 12 got "php test.php" working.
I would down load the missing file and go from there you are using xamp which is pre-built to talk to mySQl I doubt there is any extra .dll in the Instillation to connect with SQLAnywhere
I am using PHP 5.3.3 on RHEL 5. I have installed all the necessary drivers and add-ons for ODBC connections to Teradata. I wrote a simple script to test it:
$con_string = "DRIVER={Teradata};DBCName=**HOST**; DATABASE=**database**;";
$con = odbc_pconnect( $con_string , "user", "pass" );
var_dump($con);
echo 'here';
$res = odbc_exec($con, "SELECT id FROM database.table");
echo 'there';
var_dump($res);
The output is as follows:
resource(5) of type (odbc link persistent)
hereSegmentation fault
Obviously the connection works. I have also tried other commands, some work, some don't. odbc_tables() and odbc_procedures() return the correct information without problem. However, anything related to a SQL query gets a seg fault. I have not been able to get trace/debug to turn on for ODBC.
Any help would be greatly appreciated!
I experienced this problem with using a resultset twice for two different odbc_exec's. It was resolved doing unset($res) before each odbc_exec so the odbc_exec always starts using a clean variable.
I don't yet have a good explanation 'why' (probably previous resultset variables require correct 'closes'...?), but this prevents my segmentation faults
Three things you can do. First, (assuming you are using unixODBC) find your odbcinst.ini file and add:
[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log
Run your PHP script from the command line and you should get a log. If it is segfaulting in unixODBC or your ODBC driver the last line should show an entry into an ODBC API but no exit. However, that will only give you a clue as to where it is failing.
Second thing you can do is find where your php executable is and run it under the debugger:
gdb /path/to/php
When you get the prompt do:
r /path/to/my/php_script
When it seg faults use the back trace (bt) command to show where it blew up.
Lastly, you could have a teradata ODBC driver which was not built with the same ODBC headers or defines as PHP and unixODBC. This is very tricky to discover but if you are on a 64 bit machine it is a possibility. You can use unixODBC's odbc_config command to find out how unixODBC was built. In particular odbc_config --ulen and --cflags. Unfortunately most debian based distributions don't include odbc_config yet - may be you'll be luckier on redhat. The thing you are looking for is teradata being built with SQLULEN 32 bits and unixODBC/PHP with it 64 bits - if you've got this situation you'll definitely get segfaults. If this is your issue you need to get the correct build from teradata or switch everything to 32 bit binaries.
Armed with this info you might be able to find out what is going wrong. You can always post the gdb back trace or the end of the unixODBC log file and I may be able to help.
I have seen this issue previously (specifically with Teradata ODBC connectivity) and remember having to patch and build a custom PHP executable in order to get it to work. I'm light on the details as it was some time ago but remember its due to a problem with PHP's ODBC_pconnect and the TD drivers. It seems that PHP's odbc_connect also uses odbc_pconnect so never worked - once odbc_connect was patched to remove odbc_pconnect I could use PHP as expected.
Sorry if that's a rambling mess, hopefully it will give you some pointers...
The database management system Sybase ASE supports multiple result sets, however the implementation of Sybase in PHP doesn't. There is a bug reported on this issue and there is also a patch supplied in that report (https://bugs.php.net/bug.php?id=48675). The patch is for version 5.2.9 and I've tried to add it to version 5.3.10. The source builds without warnings or errors, and testing the new function 'sybase_next_result()' does not yield a fatal error "Call to undefined function". This would suggest that the function is implemented, but not working as expected.
Configuration is:
configure --disable-isapi --enable-debug-pack --without-mssql --without-pdo-mssql --without-pi3web --with-mcrypt=static --disable-static-analyze --enable-cli --with-sybase-ct=%SYBASE%\%SYBASE_OCS%
There is a notice on 'sybase_query()' when there are multiple result sets saying "Sybase: Unexpected results, cancelling current in...". The first result set is retrieved. And this notice is returned even without the patch.
The number of stored procedures in the database that return multiple result sets is vast, and a 'sybase_next_result()' would be the best solution. In short, I looking for an equivalent to 'mssql_next_result()' (http://se2.php.net/manual/en/function.mssql-execute.php) for Sybase in PHP 5.3.10.
Worth noting is that the other parts of the Sybase implementation is in place and seems work as expected.
My testing environment is a WAMP server (Windows 7, Apache 2.21, MySQL 5.5.20, PHP 5.3.10) and Sybase ASE is version 15.7.0.
Is there anyone out there that has "solved" this?
With regards
//Jonas
Update:
A colleague gave me the instructions to use 'OutputDebugString()' (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363362(v=vs.85).aspx) and catch that with DebugView (http://technet.microsoft.com/en-us/sysinternals/bb896647).
From this I can say that 'sybase_next_result()' is called but the block
if (sybase_ptr->active_result_index) {
...
}
is not run. This is probably correct (as I see it).
The row
retcode = ct_results(sybase_ptr->cmd, &restype);
is always setting 'retcode' to 'CS_FAIL'. This is perhaps because the earlier
ZEND_FETCH_RESOURCE2(sybase_ptr, sybase_link *, sybase_link_index, id, "Sybase-Link", le_link, le_plink);
sets 'sybase_ptr' in sutch fashion that 'retcode' becomes 'CS_FAIL'.