├── CREDITS ├── tests ├── spook.png ├── large_blob.dat ├── large_clob.dat ├── skipif.inc ├── fvt_001.phpt ├── fvt_002.phpt ├── fvt_040.phpt ├── fvt_005.phpt ├── fvt_011.phpt ├── fvt_010.phpt ├── fvt_012.phpt ├── fvt_030.phpt ├── fvt_003.phpt ├── fvt_004.phpt ├── fvt_014.phpt ├── fvt_007.phpt ├── fvt_034.phpt ├── fvt_020.phpt ├── fvt_021.phpt ├── fvt_009.phpt ├── fvt_49872.phpt ├── fvt_026.phpt ├── fvt_022.phpt ├── fvt_023.phpt ├── fvt_033.phpt ├── fvt_008.phpt ├── fvt_035.phpt ├── fvt_006.phpt ├── fvt_027.phpt ├── fvt_032.phpt ├── fvt_017b.phpt ├── fvt_017.phpt ├── fvt_018.phpt ├── fvt_019.phpt ├── fvt_017c.phpt ├── fvt.inc ├── fvt_036.phpt ├── fvt_025.phpt ├── fvt_031.phpt ├── fvt_016.phpt ├── fvt_013.phpt ├── fvt_038.phpt ├── clob.dat ├── TESTMATRIX ├── fvt_024.phpt └── fvt_015.phpt ├── Makefile.frag ├── config.w32 ├── php_pdo_informix.h ├── config.m4 ├── package.xml ├── pdo_informix.c ├── php_pdo_informix_int.h ├── informix_driver.c └── informix_statement.c /CREDITS: -------------------------------------------------------------------------------- 1 | pdo_informix 2 | Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier 3 | -------------------------------------------------------------------------------- /tests/spook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-database-pdo_informix/master/tests/spook.png -------------------------------------------------------------------------------- /tests/large_blob.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-database-pdo_informix/master/tests/large_blob.dat -------------------------------------------------------------------------------- /tests/large_clob.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-database-pdo_informix/master/tests/large_clob.dat -------------------------------------------------------------------------------- /tests/skipif.inc: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /tests/fvt_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Connect to database 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 14 | print "Connection succeeded.\n"; 15 | } 16 | } 17 | 18 | $testcase = new Test(); 19 | $testcase->runTest(); 20 | ?> 21 | --EXPECT-- 22 | Attempting to connect.. 23 | Connection succeeded. 24 | -------------------------------------------------------------------------------- /tests/fvt_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Count number of affected rows 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | $sql = 'UPDATE animals SET id = 9'; 15 | $res = $this->db->exec($sql); 16 | print "Number of affected rows: " . $res; 17 | } 18 | } 19 | 20 | $testcase = new Test(); 21 | $testcase->runTest(); 22 | ?> 23 | --EXPECT-- 24 | Number of affected rows: 7 25 | -------------------------------------------------------------------------------- /tests/fvt_040.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Get the server info. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $result = $this->db->getAttribute(PDO::ATTR_SERVER_INFO); 14 | echo "Server Info: $result\n"; 15 | if ($result = NULL) { 16 | echo "Result is NULL...bad\n"; 17 | } 18 | } 19 | } 20 | 21 | $testcase = new Test(); 22 | $testcase->runTest(); 23 | ?> 24 | --EXPECTF-- 25 | Server Info: Informix 26 | -------------------------------------------------------------------------------- /tests/fvt_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Get the driver version 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | $result = $this->db->getAttribute(PDO::ATTR_CLIENT_VERSION); 15 | echo "Version is: $result\n"; 16 | if ($result = NULL) { 17 | echo "Result is NULL...bad\n"; 18 | } 19 | } 20 | } 21 | 22 | $testcase = new Test(); 23 | $testcase->runTest(); 24 | ?> 25 | --EXPECTF-- 26 | Version is: %d.%d.%d 27 | -------------------------------------------------------------------------------- /tests/fvt_011.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Count number of affected rows - Delete 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | 15 | $stmt = $this->db->query( "DELETE FROM animals WHERE weight > 10.0" ); 16 | echo "Number of affected rows: " . $stmt->rowCount(); 17 | } 18 | } 19 | 20 | $testcase = new Test(); 21 | $testcase->runTest(); 22 | ?> 23 | --EXPECT-- 24 | Number of affected rows: 3 25 | -------------------------------------------------------------------------------- /tests/fvt_010.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Count number of affected rows - Update 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | 15 | $stmt = $this->db->query( "UPDATE animals SET name = 'flyweight' WHERE weight < 10.0" ); 16 | echo "Number of affected rows: " . $stmt->rowCount(); 17 | } 18 | } 19 | 20 | $testcase = new Test(); 21 | $testcase->runTest(); 22 | ?> 23 | --EXPECT-- 24 | Number of affected rows: 4 25 | -------------------------------------------------------------------------------- /tests/fvt_012.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Count number of affected rows - Select 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | 15 | $stmt = $this->db->query( "SELECT name FROM animals WHERE weight < 10.0" ); 16 | print $stmt->rowCount() . "\n"; 17 | echo "Number of rows: " . count( $stmt->fetchAll() ) . "\n"; 18 | } 19 | } 20 | 21 | $testcase = new Test(); 22 | $testcase->runTest(); 23 | ?> 24 | --EXPECT-- 25 | -1 26 | Number of rows: 4 27 | 28 | -------------------------------------------------------------------------------- /tests/fvt_030.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: PDOStatement::fetch() 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | 15 | $stmt = $this->db->query( "SELECT id, breed, name, weight FROM animals WHERE id = 0" ); 16 | while( $row = $stmt->fetch( PDO::FETCH_BOTH ) ) { 17 | $breed = $row[1]; 18 | var_dump( $breed ); 19 | $name = $row["NAME"]; 20 | var_dump( $name ); 21 | } 22 | } 23 | } 24 | 25 | $testcase = new Test(); 26 | $testcase->runTest(); 27 | ?> 28 | --EXPECT-- 29 | string(3) "cat" 30 | string(16) "Pook " 31 | -------------------------------------------------------------------------------- /tests/fvt_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Connection attempt with wrong user/pwd 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 20 | print "Connection succeeded.\n"; 21 | }catch( PDOException $e ){ 22 | print "Connection failed.\n"; 23 | } 24 | } 25 | } 26 | 27 | $testcase = new Test(); 28 | $testcase->runTest(); 29 | ?> 30 | --EXPECT-- 31 | Attempting to connect.. 32 | Connection failed. 33 | -------------------------------------------------------------------------------- /tests/fvt_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Connection attempt with wrong user/pwd 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | dsn .= "UID=not_a_user;PWD=invalid_pass"; 14 | $this->user = ""; 15 | $this->pass = ""; 16 | } 17 | 18 | public function runTest() 19 | { 20 | print "Attempting to connect..\n"; 21 | try{ 22 | $this->connect(); 23 | print "Connection succeeded.\n"; 24 | }catch( PDOException $e ){ 25 | print "Connection failed.\n"; 26 | } 27 | } 28 | } 29 | 30 | $testcase = new Test(); 31 | $testcase->runTest(); 32 | ?> 33 | --EXPECT-- 34 | Attempting to connect.. 35 | Connection failed. 36 | -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | #OVERALL_TARGET += $(srcdir)/preprocessed_file.c 2 | 3 | #$(srcdir)/ifx.c: $(srcdir)/preprocessed_file.ec $(builddir)/pdo_informix.a 4 | # (if test -d $(INFORMIXDIR); then \ 5 | # THREADLIB=POSIX $(INFORMIXDIR)/bin/esql -e $(IFX_ESQL_FLAGS) $(srcdir)/ifx.ec; mv preprocessed_file.c $@; \ 6 | # THREADLIB=POSIX $(INFORMIXDIR)/bin/esql -e $(IFX_ESQL_FLAGS) $(srcdir)/ifx.ec; \ 7 | # mv preprocessed_file.c $@ || true; \ 8 | # else \ 9 | # touch $@; \ 10 | # fi) 11 | 12 | $(builddir)/pdo_informix.a: 13 | $(LIBTOOL) --mode=link $(CC) $(IFX_LIBOBJS) -o $@ 14 | 15 | realclean: distclean 16 | rm -rf acinclude.m4 aclocal.m4 autom4te.cache build config.guess config.h config.h.in config.nice config.sub configure configure.in .deps include install-sh ltmain.sh Makefile.global missing mkinstalldirs modules 17 | 18 | .PHONY: realclean 19 | -------------------------------------------------------------------------------- /tests/fvt_014.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: rowCount - insert, delete 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | 15 | $stmt = $this->db->query( "INSERT INTO animals VALUES ( 7 , 'monkey' , 'Evil Monkey' , 10.0 )" ); 16 | print "Num rows affected (Ins): " . $stmt->rowCount() . ", Column count: " . $stmt->columnCount() . "\n"; 17 | $stmt = null; 18 | 19 | $stmt = $this->db->query( "DELETE FROM animals WHERE id=7" ); 20 | print "Num rows affected (Del): " . $stmt->rowCount() . ", Column count: " . $stmt->columnCount() . "\n"; 21 | $stmt = null; 22 | } 23 | } 24 | 25 | $testcase = new Test(); 26 | $testcase->runTest(); 27 | ?> 28 | --EXPECT-- 29 | Num rows affected (Ins): 1, Column count: 0 30 | Num rows affected (Del): 1, Column count: 0 31 | -------------------------------------------------------------------------------- /tests/fvt_007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Test error conditions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | $sql = "DROP table testFloat"; 16 | $stmt = $this->db->exec($sql); 17 | } catch( Exception $e ){} 18 | 19 | $sql = "CREATE table testFloat (data FLOAT)"; 20 | $stmt = $this->db->exec($sql); 21 | 22 | $sql = "INSERT INTO testFloat (data) values (0.058290369626395423)"; 23 | $stmt = $this->db->exec($sql); 24 | 25 | $sql = "SELECT data FROM testFloat"; 26 | $stmt = $this->db->query($sql); 27 | 28 | while ( $row = $stmt->fetch() ) { 29 | print_r($row); 30 | } 31 | } 32 | } 33 | 34 | $testcase = new Test(); 35 | $testcase->runTest(); 36 | ?> 37 | --EXPECT-- 38 | Array 39 | ( 40 | [DATA] => 0.0582903696263954 41 | [0] => 0.0582903696263954 42 | ) 43 | 44 | -------------------------------------------------------------------------------- /tests/fvt_034.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Check error condition when inserting into non-existent table 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 14 | $myarr = array(array (10, "Java", 12, "Bean", 914.05)); 15 | $sql = "INSERT INTO doesnotexist VALUES(?, ?, ?, ?, ?, ?)"; 16 | $stmt = $this->db->prepare($sql); 17 | 18 | foreach ($myarr as $data) { 19 | if ($stmt->execute($data)) { 20 | echo "True\n"; 21 | } else { 22 | echo "False\n"; 23 | } 24 | } 25 | $stmt = null; 26 | } catch(exception $e) { 27 | print $e->getMessage(); 28 | } 29 | 30 | } 31 | } 32 | 33 | $testcase = new Test(); 34 | $testcase->runTest(); 35 | ?> 36 | --EXPECTF-- 37 | SQLSTATE[42S02]: Base table or view not found: -206 [%s][%s][%s]The specified table (doesnotexist) is not in the database. (SQLPrepare[-206] at %s) 38 | -------------------------------------------------------------------------------- /tests/fvt_020.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: rollback 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 15 | $res = $stmt->fetch( PDO::FETCH_NUM ); 16 | $rows = $res[0]; 17 | echo $rows."\n"; 18 | 19 | $this->db->beginTransaction(); 20 | $this->db->exec( "DELETE FROM animals" ); 21 | 22 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 23 | $res = $stmt->fetch( PDO::FETCH_NUM ); 24 | $rows = $res[0]; 25 | echo $rows."\n"; 26 | 27 | $this->db->rollBack(); 28 | 29 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 30 | $res = $stmt->fetch( PDO::FETCH_NUM ); 31 | $rows = $res[0]; 32 | echo $rows."\n"; 33 | } 34 | } 35 | 36 | $testcase = new Test(); 37 | $testcase->runTest(); 38 | ?> 39 | --EXPECTF-- 40 | 7 41 | 0 42 | 7 43 | -------------------------------------------------------------------------------- /tests/fvt_021.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: commit 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 15 | $res = $stmt->fetch( PDO::FETCH_NUM ); 16 | $rows = $res[0]; 17 | echo $rows."\n"; 18 | 19 | $this->db->beginTransaction(); 20 | $this->db->exec( "DELETE FROM animals" ); 21 | 22 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 23 | $res = $stmt->fetch( PDO::FETCH_NUM ); 24 | $rows = $res[0]; 25 | echo $rows."\n"; 26 | 27 | $this->db->commit(); 28 | 29 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 30 | $res = $stmt->fetch( PDO::FETCH_NUM ); 31 | $rows = $res[0]; 32 | echo $rows."\n"; 33 | } 34 | } 35 | 36 | $testcase = new Test(); 37 | $testcase->runTest(); 38 | ?> 39 | --EXPECTF-- 40 | 7 41 | 0 42 | 0 43 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | ARG_WITH("pdo-informix", "Informix IDS support for PDO. Pass the location of the Informix CSDK, for example, --with-pdo-informix=C:\\IBM\\CSDK", "no"); 2 | 3 | if (PHP_PDO_INFORMIX != "no") 4 | { 5 | if (CHECK_LIB("iclit09b.lib", "pdo_informix", PHP_PDO_INFORMIX) && 6 | CHECK_HEADER_ADD_INCLUDE('sql.h', 'CFLAGS_PDO_INFORMIX', PHP_PDO_INFORMIX + '\\incl\\cli;' + PHP_PHP_BUILD + "\\include\\informix\\cli") && 7 | CHECK_HEADER_ADD_INCLUDE('ifxtypes.h', 'CFLAGS_PDO_INFORMIX', PHP_PDO_INFORMIX + '\\incl\\esql;' + PHP_PHP_BUILD + "\\include\\informix\\esql")) 8 | { 9 | ADD_FLAG( 'CFLAGS_PDO_INFORMIX' , '/I "' + PHP_PDO_INFORMIX + '\\incl\\cli" '); 10 | ADD_FLAG( 'CFLAGS_PDO_INFORMIX' , '/I "' + PHP_PDO_INFORMIX + '\\incl\\esql" '); 11 | ADD_FLAG( 'LDFLAGS_PDO_INFORMIX' , '/libpath:"' + PHP_PDO_INFORMIX + '\\lib" ' ); 12 | EXTENSION('pdo_informix', "pdo_informix.c informix_driver.c informix_statement.c"); 13 | } 14 | else 15 | { 16 | WARNING("pdo_informix not enabled; libraries and headers not found"); 17 | } 18 | ADD_EXTENSION_DEP("pdo_informix", "pdo"); 19 | } 20 | -------------------------------------------------------------------------------- /tests/fvt_009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Test error conditions through faulty SQL 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $parmno = "200010"; 14 | try { 15 | $stmt = $this->db->prepare("SELECT empno, lastname, bonus, FROM employee WHERE empno > ?"); 16 | $stmt->execute( array( $parmno )); 17 | while ($row = $stmt->fetch()) { 18 | print_r($row); 19 | } 20 | } catch (PDOException $pe) { 21 | echo "Error code:\n"; 22 | print_r($this->db->errorCode()); 23 | echo "\n"; 24 | echo "Error info:\n"; 25 | print_r($this->db->errorInfo()); 26 | } 27 | } 28 | } 29 | 30 | $testcase = new Test(); 31 | $testcase->runTest(); 32 | ?> 33 | --EXPECTF-- 34 | Error code: 35 | 42000 36 | Error info: 37 | Array 38 | ( 39 | [0] => 42000 40 | [1] => -201 41 | [2] => [Informix][Informix ODBC Driver][Informix]A syntax error has occurred. (SQLPrepare[-201] at %s) 42 | ) 43 | -------------------------------------------------------------------------------- /tests/fvt_49872.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Check the clearing of error codes 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | /* Drop the test table, in case it exists */ 16 | $drop = 'DROP TABLE animals'; 17 | $result = $this->db->exec( $drop ); 18 | } catch( Exception $e ){} 19 | 20 | /* Create the test table */ 21 | $create = 'CREATE TABLE animals (id INTEGER)'; 22 | $result = $this->db->exec( $create ); 23 | 24 | $sql = "selec id from animals "; 25 | try { 26 | $stmt = $this->db->query($sql); 27 | } catch ( Exception $e) {} 28 | 29 | $sql = "select id from animals "; 30 | $stmt = $this->db->query($sql); 31 | print_r($this->db->errorInfo()); 32 | 33 | $res = $stmt->fetch(); 34 | print_r($res); 35 | } 36 | } 37 | 38 | $testcase = new Test(); 39 | $testcase->runTest(); 40 | ?> 41 | --EXPECT-- 42 | Array 43 | ( 44 | [0] => 00000 45 | [1] => 0 46 | [2] => ((null)[0] at (null):0) 47 | ) 48 | -------------------------------------------------------------------------------- /tests/fvt_026.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Check error code. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 11 | $this->prepareDB(); 12 | try { 13 | $err = $this->db->prepare('SELECT skull FROM bones'); 14 | $err->execute(); 15 | } catch (Exception $e) { 16 | echo "\nPDOStatement::errorCode(): "; 17 | print $this->db->errorCode(); 18 | } 19 | try { 20 | $err = $this->db->prepare('SELECT id FROM animals WHERE bones=100'); 21 | $err->execute(); 22 | } catch (Exception $e) { 23 | echo "\nPDOStatement::errorCode(): "; 24 | print $this->db->errorCode(); 25 | } 26 | try { 27 | $err = $this->db->prepare('SELECT id, skull FROM animals WHERE id=1'); 28 | $err->execute(); 29 | } catch (Exception $e) { 30 | echo "\nPDOStatement::errorCode(): "; 31 | print $this->db->errorCode(); 32 | } 33 | } 34 | } 35 | $testcase = new Test(); 36 | $testcase->runTest(); 37 | ?> 38 | --EXPECTF-- 39 | PDOStatement::errorCode(): 42S02 40 | PDOStatement::errorCode(): 42S22 41 | PDOStatement::errorCode(): 42S22 42 | -------------------------------------------------------------------------------- /tests/fvt_022.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: rollback with autocommit off 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(false); 18 | $this->prepareDB(); 19 | $stmt = $this->db->exec( "commit work" ); 20 | 21 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 22 | $res = $stmt->fetch( PDO::FETCH_NUM ); 23 | $rows = $res[0]; 24 | echo $rows."\n"; 25 | 26 | $this->db->exec( "DELETE FROM animals" ); 27 | 28 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 29 | $res = $stmt->fetch( PDO::FETCH_NUM ); 30 | $rows = $res[0]; 31 | echo $rows."\n"; 32 | 33 | $stmt = $this->db->exec( "rollback work" ); 34 | /* $this->db->rollBack(); */ 35 | 36 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 37 | $res = $stmt->fetch( PDO::FETCH_NUM ); 38 | $rows = $res[0]; 39 | echo $rows."\n"; 40 | } 41 | } 42 | 43 | $testcase = new Test(); 44 | $testcase->runTest(); 45 | ?> 46 | --EXPECTF-- 47 | 7 48 | 0 49 | 7 50 | -------------------------------------------------------------------------------- /tests/fvt_023.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: commit with autocommit off 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | dsn .= ";OptimizeAutoCommit=0;"; 14 | } 15 | 16 | public function runTest() 17 | { 18 | $this->connect(false); 19 | $this->prepareDB(); 20 | $stmt = $this->db->exec( "commit work" ); 21 | 22 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 23 | $res = $stmt->fetch( PDO::FETCH_NUM ); 24 | $rows = $res[0]; 25 | echo $rows."\n"; 26 | 27 | $this->db->exec( "DELETE FROM animals" ); 28 | 29 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 30 | $res = $stmt->fetch( PDO::FETCH_NUM ); 31 | $rows = $res[0]; 32 | echo $rows."\n"; 33 | 34 | $stmt = $this->db->exec( "commit work" ); 35 | /* $this->db->commit(); */ 36 | 37 | $stmt = $this->db->query( "SELECT count(*) FROM animals" ); 38 | $res = $stmt->fetch( PDO::FETCH_NUM ); 39 | $rows = $res[0]; 40 | echo $rows."\n"; 41 | } 42 | } 43 | 44 | $testcase = new Test(); 45 | $testcase->runTest(); 46 | ?> 47 | --EXPECTF-- 48 | 7 49 | 0 50 | 0 51 | -------------------------------------------------------------------------------- /tests/fvt_033.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Check error condition when given null connection parameters 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | user, $this->pass); 15 | } catch(Exception $e) { 16 | echo "Connection Failed\n"; 17 | echo $e->getMessage() . "\n\n"; 18 | } 19 | 20 | try { 21 | $my_null = NULL; 22 | $new_conn = new PDO($this->dsn, $my_null, $this->pass); 23 | } catch(Exception $e) { 24 | echo "Connection Failed\n"; 25 | echo $e->getMessage() . "\n"; 26 | } 27 | 28 | try { 29 | $my_null = NULL; 30 | $new_conn = new PDO($this->dsn, $this->user, $my_null); 31 | } catch(Exception $e) { 32 | echo "Connection Failed\n"; 33 | echo $e->getMessage(); 34 | } 35 | } 36 | } 37 | 38 | $testcase = new Test(); 39 | $testcase->runTest(); 40 | ?> 41 | --EXPECTF-- 42 | Connection Failed 43 | invalid data source name 44 | 45 | Connection Failed 46 | SQLSTATE=28000, SQL%sonnect: -951 [%s][%s][Informix]Incorrect password or user %s is not known on the database server. 47 | Connection Failed 48 | SQLSTATE=28000, SQL%sonnect: -951 [%s][%s][Informix]Incorrect password or user %s is not known on the database server. 49 | 50 | -------------------------------------------------------------------------------- /tests/fvt_008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Test error conditions through non-existent tables 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $sql = "CREATE TABLE testError(" . 14 | "id INTEGER," . 15 | "data VARCHAR(50)," . 16 | "attachment VARCHAR(50)," . 17 | "about VARCHAR(50))"; 18 | 19 | try { 20 | $stmt = $this->db->prepare($sql); 21 | $stmt->execute(); 22 | } catch (PDOException $pe) { 23 | echo $pe->getMessage(); 24 | } 25 | 26 | $this->db->exec("DROP TABLE testError"); 27 | $sql = "SELECT id FROM FINAL TABLE(INSERT INTO testError(data,about,attachment)values(?,?,?))"; 28 | 29 | try { 30 | $stmt = $this->db->prepare($sql); 31 | $stmt->execute(); 32 | } catch (PDOException $pe) { 33 | echo "Error code:\n"; 34 | print_r($this->db->errorCode()); 35 | echo "\n"; 36 | echo "Error info:\n"; 37 | print_r($this->db->errorInfo()); 38 | } 39 | } 40 | } 41 | 42 | $testcase = new Test(); 43 | $testcase->runTest(); 44 | ?> 45 | --EXPECTF-- 46 | Error code: 47 | 42S02 48 | Error info: 49 | Array 50 | ( 51 | [0] => 42S02 52 | [1] => -206 53 | [2] => [Informix][Informix ODBC Driver][Informix]The specified table (informix.testerror) is not in the database. (SQLPrepare[-206] at %s) 54 | ) 55 | 56 | -------------------------------------------------------------------------------- /tests/fvt_035.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Check return values from exec 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(false); 13 | 14 | try { 15 | $this->db->exec("DROP TABLE testExec"); 16 | } catch (Exception $e){} 17 | 18 | $sql = "CREATE TABLE testExec (id INTEGER)"; 19 | if ($this->db->exec($sql) === false) { 20 | echo "Did not work\n"; 21 | } else { 22 | echo "Worked\n"; 23 | } 24 | 25 | $this->db->exec("INSERT INTO testExec (id) values (1)"); 26 | 27 | $sql = "UPDATE testExec SET id = 5 WHERE id = 1"; 28 | if ($this->db->exec($sql) === false) { 29 | echo "Did not work\n"; 30 | } else { 31 | echo "Worked\n"; 32 | } 33 | 34 | $sql = "DELETE FROM testExec WHERE id = 1"; 35 | if ($this->db->exec($sql) === false) { 36 | echo "Did not work\n"; 37 | } else { 38 | echo "Worked\n"; 39 | } 40 | 41 | $this->db->exec("INSERT INTO testExec (id) values (2)"); 42 | $this->db->exec("INSERT INTO testExec (id) values (3)"); 43 | $this->db->exec("INSERT INTO testExec (id) values (4)"); 44 | 45 | $sql = "DELETE FROM testExec"; 46 | $rowCount = $this->db->exec($sql); 47 | echo "Row count: $rowCount"; 48 | } 49 | } 50 | 51 | $testcase = new Test(); 52 | $testcase->runTest(); 53 | ?> 54 | --EXPECTF-- 55 | Worked 56 | Worked 57 | Worked 58 | Row count: 4 59 | -------------------------------------------------------------------------------- /tests/fvt_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Test error conditions 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | try { 14 | $stmt1 = $this->db->prepare("SELECT id FROM animals WHERE colnotexist = 1 " ) ; 15 | print("Error Code: ".$this->db->errorCode()."\n"); 16 | print_r($this->db->errorInfo()); 17 | print("\n"); 18 | $stmt2 = $this->db->prepare("SELECT id FROM animals WHERE id = 1 " ) ; 19 | print("Error Code: ".$this->db->errorCode()."\n"); 20 | print_r($this->db->errorInfo()); 21 | print("\n"); 22 | } catch (PDOException $pe) { 23 | print("Error Code: ".$this->db->errorCode()."\n"); 24 | print_r($this->db->errorInfo()); 25 | print("\n"); 26 | $stmt2 = $this->db->prepare("SELECT id FROM animals WHERE id = 1 " ) ; 27 | print("Error Code: ".$this->db->errorCode()."\n"); 28 | print_r($this->db->errorInfo()); 29 | print("\n"); 30 | } 31 | } 32 | } 33 | 34 | $testcase = new Test(); 35 | $testcase->runTest(); 36 | ?> 37 | --EXPECTF-- 38 | Error Code: 42S22 39 | Array 40 | ( 41 | [0] => 42S22 42 | [1] => -217 43 | [2] => [Informix][Informix ODBC Driver][Informix]Column (colnotexist) not found in any table in the query (or SLV is undefined). (%s 44 | ) 45 | 46 | Error Code: 00000 47 | Array 48 | ( 49 | [0] => 00000 50 | [1] => 0 51 | [2] => ((null)[0] at (null):0) 52 | ) 53 | 54 | -------------------------------------------------------------------------------- /tests/fvt_027.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Testing fetchColumn with different modes and options 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 11 | $this->prepareDB(); 12 | $sql = "SELECT * FROM animals WHERE id > 0"; 13 | 14 | $stmt = $this->db->prepare($sql); 15 | $stmt->execute(); 16 | while( $value = $stmt->fetchColumn() ) { 17 | print "The column value is: " . $value . "\n"; 18 | } 19 | 20 | $stmt = $this->db->prepare($sql); 21 | $stmt->execute(); 22 | while( $value = $stmt->fetchColumn( 1 ) ) { 23 | print "The column value is: " . $value . "\n"; 24 | } 25 | 26 | $stmt = $this->db->prepare($sql); 27 | $stmt->execute(); 28 | while( $value = $stmt->fetchColumn( -1 ) ) { 29 | print "The column value is: " . $value . "\n"; 30 | } 31 | 32 | $stmt = $this->db->prepare($sql); 33 | $stmt->execute(); 34 | while( $value = $stmt->fetchColumn( 7 ) ) { 35 | print "The column value is: " . $value . "\n"; 36 | } 37 | } 38 | } 39 | $testcase = new Test(); 40 | $testcase->runTest(); 41 | ?> 42 | --EXPECT-- 43 | The column value is: 1 44 | The column value is: 2 45 | The column value is: 3 46 | The column value is: 4 47 | The column value is: 5 48 | The column value is: 6 49 | The column value is: dog 50 | The column value is: horse 51 | The column value is: gold fish 52 | The column value is: budgerigar 53 | The column value is: goat 54 | The column value is: llama 55 | -------------------------------------------------------------------------------- /tests/fvt_032.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Check error codes after a failed execution 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 14 | 15 | try { 16 | /* Drop the test table, in case it exists */ 17 | $drop = 'DROP TABLE test_error'; 18 | $result = $this->db->exec( $drop ); 19 | } catch( Exception $e ){} 20 | 21 | $this->db->exec("CREATE TABLE test_error (id INTEGER, data VARCHAR(50))"); 22 | 23 | echo "Begin\n"; 24 | $this->db->beginTransaction(); 25 | 26 | $stmt = $this->db->prepare("INSERT INTO test_error (id, data ) VALUES (?, ?)"); 27 | 28 | try { 29 | echo "Execute\n"; 30 | $res = $stmt->execute(array('a','b')); 31 | 32 | if($res) { 33 | echo "Commit\n"; 34 | $this->db->commit(); 35 | } else { 36 | $err = $stmt->errorInfo(); 37 | echo "Execute failed\n"; 38 | echo "$err[0]\n"; 39 | echo "$err[1]\n"; 40 | echo "$err[2]\n"; 41 | $this->db->rollBack(); 42 | } 43 | } catch(Exception $e) { 44 | $err = $stmt->errorInfo(); 45 | echo "Exception occured\n"; 46 | echo "$err[0]\n"; 47 | echo "$err[1]\n"; 48 | echo "$err[2]\n"; 49 | $this->db->rollBack(); 50 | } 51 | } 52 | } 53 | 54 | $testcase = new Test(); 55 | $testcase->runTest(); 56 | ?> 57 | --EXPECTF-- 58 | Begin 59 | Execute 60 | Exception occured 61 | 22018 62 | -11106 63 | [Informix][Informix ODBC Driver]Invalid character value for cast specification. (SQLExecute[-11106] at %s 64 | 65 | -------------------------------------------------------------------------------- /tests/fvt_017b.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Insert and retrieve a very large clob file. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | /* Drop the test table, in case it exists */ 16 | $drop = 'DROP TABLE animals'; 17 | $result = $this->db->exec( $drop ); 18 | } catch( Exception $e ){} 19 | 20 | /* Create the test table */ 21 | $create = 'CREATE TABLE animals (id INTEGER, my_clob text)'; 22 | $result = $this->db->exec( $create ); 23 | 24 | $fp = fopen( dirname(__FILE__) . "/large_clob.dat" , "r" ); 25 | $stmt = $this->db->prepare('insert into animals (id,my_clob) values (:id,:my_clob)'); 26 | print "inserting from file stream\n"; 27 | $stmt->bindValue( ':id' , 0 ); 28 | $stmt->bindParam( ':my_clob' , $fp , PDO::PARAM_LOB ); 29 | $stmt->execute(); 30 | print "succesful\n"; 31 | 32 | print "runnign query\n"; 33 | $stmt = $this->db->prepare( 'select id,my_clob from animals' ); 34 | 35 | $stmt->bindColumn( 'ID' , $id ); 36 | $stmt->bindColumn( 'MY_CLOB' , $clob , PDO::PARAM_LOB ); 37 | $rs = $stmt->execute(); 38 | while ($stmt->fetch(PDO::FETCH_BOUND)) { 39 | var_dump( $id ); 40 | var_dump( $clob ); 41 | $fp = fopen( dirname(__FILE__) . "/large_clob_out.dat" , "w" ); 42 | fwrite($fp , $clob); 43 | system( "diff large_clob.dat large_clob_out.dat" ); 44 | } 45 | print "done\n"; 46 | } 47 | } 48 | 49 | $testcase = new Test(); 50 | $testcase->runTest(); 51 | ?> 52 | --EXPECTF-- 53 | inserting from file stream 54 | succesful 55 | runnign query 56 | string(1) "0" 57 | string(%d) %a 58 | done 59 | -------------------------------------------------------------------------------- /tests/fvt_017.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Insert and retrieve a very large file. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | /* Drop the test table, in case it exists */ 16 | $drop = 'DROP TABLE animals'; 17 | $result = $this->db->exec( $drop ); 18 | } catch( Exception $e ){} 19 | 20 | /* Create the test table */ 21 | $create = 'CREATE TABLE animals (id INTEGER, my_blob byte)'; 22 | $result = $this->db->exec( $create ); 23 | 24 | $fp = fopen( dirname(__FILE__) . "/large_blob.dat" , "rb" ); 25 | $stmt = $this->db->prepare('insert into animals (id,my_blob) values (:id,:my_blob)'); 26 | print "inserting from file stream\n"; 27 | $stmt->bindValue( ':id' , 0 ); 28 | $stmt->bindParam( ':my_blob' , $fp , PDO::PARAM_LOB ); 29 | $stmt->execute(); 30 | print "succesful\n"; 31 | 32 | print "runnign query\n"; 33 | $stmt = $this->db->prepare( 'select id,my_blob from animals' ); 34 | 35 | $stmt->bindColumn( 'ID' , $id ); 36 | $stmt->bindColumn( 'MY_BLOB' , $blob , PDO::PARAM_LOB ); 37 | $rs = $stmt->execute(); 38 | while ($stmt->fetch(PDO::FETCH_BOUND)) { 39 | var_dump( $id ); 40 | var_dump( $blob ); 41 | $fp = fopen( dirname(__FILE__) . "/large_blob_out.dat" , "wb" ); 42 | echo "datalength: " . stream_copy_to_stream( $blob , $fp ) . "\n"; 43 | system( "diff large_blob.dat large_blob_out.dat" ); 44 | } 45 | print "done\n"; 46 | } 47 | } 48 | 49 | $testcase = new Test(); 50 | $testcase->runTest(); 51 | ?> 52 | --EXPECTF-- 53 | inserting from file stream 54 | succesful 55 | runnign query 56 | string(1) "0" 57 | string(4966) %a 58 | done 59 | -------------------------------------------------------------------------------- /tests/fvt_018.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Quote a string. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | print "Connection succeeded.\n"; 14 | $string = 'Nice'; 15 | print "Unquoted string: $string\n"; 16 | print "Quoted string: " . $this->db->quote($string) . "\n"; 17 | $string = 'Naughty \' string'; 18 | print "Unquoted string: $string\n"; 19 | print "Quoted string: " . $this->db->quote($string) . "\n"; 20 | $string = "Co'mpl''ex \"st'\"ring"; 21 | print "Unquoted string: $string\n"; 22 | print "Quoted string: " . $this->db->quote($string) . "\n"; 23 | $string = "''''"; 24 | print "Unquoted string: $string\n"; 25 | print "Quoted string: " . $this->db->quote($string) . "\n"; 26 | $string = ""; 27 | print "Unquoted string: $string\n"; 28 | print "Quoted string: " . $this->db->quote($string) . "\n"; 29 | $string = NULL; 30 | print "Unquoted string: $string\n"; 31 | print "Quoted string: " . $this->db->quote($string) . "\n"; 32 | $string = "'"; 33 | print "Unquoted string: $string\n"; 34 | print "Quoted string: " . $this->db->quote($string) . "\n"; 35 | $string = "'quoted'"; 36 | print "Unquoted string: $string\n"; 37 | print "Quoted string: " . $this->db->quote($string) . "\n"; 38 | } 39 | } 40 | 41 | $testcase = new Test(); 42 | $testcase->runTest(); 43 | ?> 44 | --EXPECT-- 45 | Connection succeeded. 46 | Unquoted string: Nice 47 | Quoted string: 'Nice' 48 | Unquoted string: Naughty ' string 49 | Quoted string: 'Naughty \' string' 50 | Unquoted string: Co'mpl''ex "st'"ring 51 | Quoted string: 'Co\'mpl\'\'ex \"st\'\"ring' 52 | Unquoted string: '''' 53 | Quoted string: '\'\'\'\'' 54 | Unquoted string: 55 | Quoted string: '' 56 | Unquoted string: 57 | Quoted string: '' 58 | Unquoted string: ' 59 | Quoted string: '\'' 60 | Unquoted string: 'quoted' 61 | Quoted string: '\'quoted\'' 62 | -------------------------------------------------------------------------------- /tests/fvt_019.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Get the last inserted serial numbers 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | /* Drop the test table, in case it exists */ 16 | $drop = 'DROP TABLE testSerial'; 17 | $result = $this->db->exec( $drop ); 18 | } catch( Exception $e ){} 19 | 20 | /* Create the test table */ 21 | $create = 'CREATE TABLE testSerial (id serial, data varchar(50))'; 22 | $result = $this->db->exec( $create ); 23 | 24 | /* Insert and get the first serial */ 25 | $insert = 'INSERT INTO testSerial(id, data) values(?, ?);'; 26 | $stmt = $this->db->prepare($insert); 27 | $data = array('0', 'test1'); 28 | $result = $stmt->execute($data); 29 | 30 | if ($result == true) { 31 | echo ("Last Serial Inserted: " . $this->db->lastInsertId() . "\n"); 32 | } 33 | 34 | /* Insert the second serial */ 35 | $insert = 'INSERT INTO testSerial(id, data) values(?, ?);'; 36 | $stmt = $this->db->prepare($insert); 37 | $data = array('0', 'test2'); 38 | $result = $stmt->execute($data); 39 | 40 | /* Insert and get the third serial */ 41 | $insert = 'INSERT INTO testSerial(id, data) values(?, ?);'; 42 | $stmt = $this->db->prepare($insert); 43 | $data = array('0', 'test3'); 44 | $result = $stmt->execute($data); 45 | 46 | if ($result == true) { 47 | echo ("Last Serial Inserted: " . $this->db->lastInsertId() . "\n"); 48 | } 49 | 50 | /* Insert and get the forth serial */ 51 | $insert = 'INSERT INTO testSerial(id, data) values(?, ?);'; 52 | $stmt = $this->db->prepare($insert); 53 | $data = array('0', 'test4'); 54 | $result = $stmt->execute($data); 55 | 56 | if ($result == true) { 57 | echo ("Last Serial Inserted: " . $this->db->lastInsertId()); 58 | } 59 | } 60 | } 61 | 62 | $testcase = new Test(); 63 | $testcase->runTest(); 64 | ?> 65 | --EXPECT-- 66 | Last Serial Inserted: 1 67 | Last Serial Inserted: 3 68 | Last Serial Inserted: 4 69 | -------------------------------------------------------------------------------- /tests/fvt_017c.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Select LOBs, including null and 0-length 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 14 | 15 | try { 16 | /* Drop the test table, in case it exists */ 17 | $drop = 'DROP TABLE animals'; 18 | $result = $this->db->exec( $drop ); 19 | } catch( Exception $e ){} 20 | 21 | /* Create the test table */ 22 | $create = 'CREATE TABLE animals (id INTEGER, my_clob clob, my_blob blob)'; 23 | $result = $this->db->exec( $create ); 24 | 25 | $data = array ( 26 | array(1, 'this is the clob that never ends...', 27 | 'this is the blob that never ends...') 28 | , 29 | array(2, null,null) 30 | ); 31 | 32 | $stmt = $this->db->prepare('insert into animals (id,my_clob,my_blob) values (?,?,?)'); 33 | 34 | print "inserting\n"; 35 | foreach ($data as $row) { 36 | $stmt->execute($row); 37 | } 38 | 39 | print "succesful\n"; 40 | print "running query\n"; 41 | 42 | $stmt = $this->db->prepare( 'select id,my_clob,my_blob from animals' ); 43 | 44 | $rs = $stmt->execute(); 45 | 46 | $count = 0; 47 | while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 48 | var_dump( $row['ID'] ); 49 | 50 | // this is a temporary workaround 51 | // until zero-length/lob stream 52 | // issue is fixed 53 | if ($count < 2) { 54 | var_dump( $row['MY_CLOB'] ); 55 | var_dump( $row['MY_BLOB'] ); 56 | } 57 | var_dump(strpos($row['MY_CLOB'], 'lob')); 58 | $count++; 59 | } 60 | 61 | print "done\n"; 62 | } 63 | } 64 | 65 | $testcase = new Test(); 66 | $testcase->runTest(); 67 | ?> 68 | 69 | --EXPECTF-- 70 | inserting 71 | succesful 72 | running query 73 | string(1) "1" 74 | string(35) "this is the clob that never ends..." 75 | string(35) "this is the blob that never ends..." 76 | int(13) 77 | string(1) "2" 78 | string(0) "" 79 | string(0) "" 80 | bool(false) 81 | done 82 | 83 | -------------------------------------------------------------------------------- /tests/fvt.inc: -------------------------------------------------------------------------------- 1 | dsn = getenv('PDOTEST_DSN'); 14 | } 15 | else 16 | { 17 | $this->dsn = $_dsn; 18 | } 19 | 20 | if( $_user == null ) 21 | { 22 | $this->user = getenv('PDOTEST_USER'); 23 | } 24 | else 25 | { 26 | $this->user = $_user; 27 | } 28 | 29 | if( $_pass == null ) 30 | { 31 | $this->pass = getenv('PDOTEST_PASS'); 32 | } 33 | else 34 | { 35 | $this->pass = $_pass; 36 | } 37 | } 38 | 39 | public function connect($autoCommit=true) 40 | { 41 | $this->db = new PDO($this->dsn,$this->user,$this->pass,array( PDO::ATTR_AUTOCOMMIT => $autoCommit )); 42 | $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 43 | $this->db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER); 44 | $this->db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); 45 | return $this->db; 46 | } 47 | 48 | public function prepareDB() 49 | { 50 | try { 51 | /* Drop the test table, in case it exists */ 52 | $drop = 'DROP TABLE animals'; 53 | $result = $this->db->exec( $drop ); 54 | } catch( Exception $e ){} 55 | 56 | /* Create the test table */ 57 | $create = 'CREATE TABLE animals (id INTEGER, breed VARCHAR(32), name CHAR(16), weight DECIMAL(7,2))'; 58 | $result = $this->db->exec( $create ); 59 | 60 | /* Populate the test table */ 61 | $animals = array( 62 | array(0, 'cat', 'Pook', 3.2), 63 | array(1, 'dog', 'Peaches', 12.3), 64 | array(2, 'horse', 'Smarty', 350.0), 65 | array(3, 'gold fish', 'Bubbles', 0.1), 66 | array(4, 'budgerigar', 'Gizmo', 0.2), 67 | array(5, 'goat', 'Rickety Ride', 9.7), 68 | array(6, 'llama', 'Sweater', 150) 69 | ); 70 | 71 | $insert = 'INSERT INTO animals (id, breed, name, weight) VALUES (?, ?, ?, ?)'; 72 | $stmt = $this->db->prepare( $insert ); 73 | if ($stmt) 74 | { 75 | foreach ($animals as $animal) 76 | { 77 | $result = $stmt->execute($animal); 78 | } 79 | } 80 | 81 | /* Create test view 82 | $result = $this->db->exec('CREATE VIEW anime_cat AS 83 | SELECT name, breed FROM animals 84 | WHERE id = 0'); */ 85 | } 86 | 87 | abstract public function runTest(); 88 | } 89 | ?> 90 | -------------------------------------------------------------------------------- /tests/fvt_036.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Test the setting of different options 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 14 | 15 | /* Set up */ 16 | try { 17 | $this->db->exec("DROP TABLE test"); 18 | } catch (Exception $e){} 19 | $this->db->exec("CREATE TABLE test (id INTEGER)"); 20 | $this->db->exec("INSERT INTO test values (1)"); 21 | $this->db->exec("INSERT INTO test values (2)"); 22 | $this->db->exec("INSERT INTO test values (3)"); 23 | $this->db->exec("INSERT INTO test values (4)"); 24 | $this->db->exec("INSERT INTO test values (5)"); 25 | 26 | /* Test ATTR_AUTOCOMMIT */ 27 | $this->db->setAttribute(PDO::ATTR_AUTOCOMMIT, false); 28 | $this->db->beginTransaction(); 29 | $stmt = $this->db->query( "SELECT count(*) FROM test" ); 30 | $res = $stmt->fetch( PDO::FETCH_NUM ); 31 | echo $res[0]."\n"; 32 | $this->db->exec( "DELETE FROM test" ); 33 | $stmt = $this->db->query( "SELECT count(*) FROM test" ); 34 | $res = $stmt->fetch( PDO::FETCH_NUM ); 35 | echo $res[0]."\n"; 36 | $this->db->rollBack(); 37 | $stmt = $this->db->query( "SELECT count(*) FROM test" ); 38 | $res = $stmt->fetch( PDO::FETCH_NUM ); 39 | echo $res[0]."\n"; 40 | 41 | /* Test ATTR_ERRMODE */ 42 | $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 43 | try { 44 | $this->db->exec("INSERT INTO nontest values (6)"); 45 | } catch (Exception $e) { 46 | echo "Failed: " . $e->getMessage() . "\n"; 47 | } 48 | 49 | /* Test ATTR_CASE */ 50 | $this->db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER); 51 | $stmt = $this->db->query( "SELECT id FROM test" ); 52 | $res = $stmt->fetch(); 53 | var_dump( $res ); 54 | $this->db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); 55 | $stmt = $this->db->query( "SELECT id FROM test" ); 56 | $res = $stmt->fetch(); 57 | var_dump( $res ); 58 | 59 | /* Test ATTR_PERSISTENT */ 60 | $op = array(PDO::ATTR_PERSISTENT => true); 61 | $pdb = new PDO($this->dsn, $this->user, $this->pass, $op); 62 | var_dump($pdb); 63 | $pdb = null; 64 | $pdb = new PDO($this->dsn, $this->user, $this->pass, $op); 65 | var_dump($pdb); 66 | $pdb = null; 67 | } 68 | } 69 | 70 | $testcase = new Test(); 71 | $testcase->runTest(); 72 | ?> 73 | --EXPECTF-- 74 | 5 75 | 0 76 | 5 77 | Failed: %a 78 | array(2) { 79 | ["ID"]=> 80 | string(1) "1" 81 | [0]=> 82 | string(1) "1" 83 | } 84 | array(2) { 85 | ["id"]=> 86 | string(1) "1" 87 | [0]=> 88 | string(1) "1" 89 | } 90 | object(PDO)#%d (0) { 91 | } 92 | object(PDO)#%d (0) { 93 | } 94 | 95 | -------------------------------------------------------------------------------- /tests/fvt_025.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Get Column meta data. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 11 | $this->prepareDB(); 12 | $sql = "SELECT * FROM animals"; 13 | $stmt = $this->db->query($sql); 14 | $meta = $stmt->getColumnMeta(0); 15 | var_dump( $meta ); 16 | $meta = $stmt->getColumnMeta(1); 17 | var_dump( $meta ); 18 | $meta = $stmt->getColumnMeta(2); 19 | var_dump( $meta ); 20 | $meta = $stmt->getColumnMeta(3); 21 | var_dump( $meta ); 22 | try { 23 | $meta = $stmt->getColumnMeta(6); 24 | var_dump( $meta ); 25 | } catch( Exception $e ) { 26 | print "Error: " . $stmt->errorCode() . "\n"; 27 | } 28 | try{ 29 | $meta = $stmt->getColumnMeta(-1); 30 | var_dump( $meta ); 31 | } catch( Exception $e ) { 32 | print "Error: " . $stmt->errorCode() . "\n"; 33 | } 34 | } 35 | } 36 | 37 | $testcase = new Test(); 38 | $testcase->runTest(); 39 | ?> 40 | --EXPECT-- 41 | array(7) { 42 | ["scale"]=> 43 | int(0) 44 | ["native_type"]=> 45 | string(7) "INTEGER" 46 | ["flags"]=> 47 | array(3) { 48 | ["not_null"]=> 49 | bool(false) 50 | ["unsigned"]=> 51 | bool(false) 52 | ["auto_increment"]=> 53 | bool(false) 54 | } 55 | ["name"]=> 56 | string(2) "ID" 57 | ["len"]=> 58 | int(11) 59 | ["precision"]=> 60 | int(0) 61 | ["pdo_type"]=> 62 | int(2) 63 | } 64 | array(7) { 65 | ["scale"]=> 66 | int(0) 67 | ["native_type"]=> 68 | string(7) "VARCHAR" 69 | ["flags"]=> 70 | array(3) { 71 | ["not_null"]=> 72 | bool(false) 73 | ["unsigned"]=> 74 | bool(true) 75 | ["auto_increment"]=> 76 | bool(false) 77 | } 78 | ["name"]=> 79 | string(5) "BREED" 80 | ["len"]=> 81 | int(32) 82 | ["precision"]=> 83 | int(0) 84 | ["pdo_type"]=> 85 | int(2) 86 | } 87 | array(7) { 88 | ["scale"]=> 89 | int(0) 90 | ["native_type"]=> 91 | string(4) "CHAR" 92 | ["flags"]=> 93 | array(3) { 94 | ["not_null"]=> 95 | bool(false) 96 | ["unsigned"]=> 97 | bool(true) 98 | ["auto_increment"]=> 99 | bool(false) 100 | } 101 | ["name"]=> 102 | string(4) "NAME" 103 | ["len"]=> 104 | int(16) 105 | ["precision"]=> 106 | int(0) 107 | ["pdo_type"]=> 108 | int(2) 109 | } 110 | array(7) { 111 | ["scale"]=> 112 | int(2) 113 | ["native_type"]=> 114 | string(7) "DECIMAL" 115 | ["flags"]=> 116 | array(3) { 117 | ["not_null"]=> 118 | bool(false) 119 | ["unsigned"]=> 120 | bool(false) 121 | ["auto_increment"]=> 122 | bool(false) 123 | } 124 | ["name"]=> 125 | string(6) "WEIGHT" 126 | ["len"]=> 127 | int(9) 128 | ["precision"]=> 129 | int(2) 130 | ["pdo_type"]=> 131 | int(2) 132 | } 133 | Error: HY097 134 | Error: 42P10 135 | 136 | -------------------------------------------------------------------------------- /php_pdo_informix.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | (C) Copyright IBM Corporation 2006. | 4 | +----------------------------------------------------------------------+ 5 | | | 6 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 7 | | may not use this file except in compliance with the License. You may | 8 | | obtain a copy of the License at | 9 | | http://www.apache.org/licenses/LICENSE-2.0 | 10 | | | 11 | | Unless required by applicable law or agreed to in writing, software | 12 | | distributed under the License is distributed on an "AS IS" BASIS, | 13 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 14 | | implied. See the License for the specific language governing | 15 | | permissions and limitations under the License. | 16 | +----------------------------------------------------------------------+ 17 | | Authors: Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier, | 18 | | Ambrish Bhargava, Rahul Priyadarshi | 19 | +----------------------------------------------------------------------+ 20 | */ 21 | 22 | #ifndef PHP_PDO_INFORMIX_H 23 | #define PHP_PDO_INFORMIX_H 24 | 25 | #define PDO_INFORMIX_VERSION "1.3.1" 26 | 27 | extern zend_module_entry pdo_informix_module_entry; 28 | #define phpext_pdo_informix_ptr &pdo_informix_module_entry 29 | 30 | #ifdef PHP_WIN32 31 | #define PHP_PDO_INFORMIX_API __declspec(dllexport) 32 | #else 33 | #define PHP_PDO_INFORMIX_API 34 | #endif 35 | 36 | #ifdef ZTS 37 | #include "TSRM.h" 38 | #endif 39 | 40 | PHP_MINIT_FUNCTION(pdo_informix); 41 | PHP_MSHUTDOWN_FUNCTION(pdo_informix); 42 | PHP_RINIT_FUNCTION(pdo_informix); 43 | PHP_RSHUTDOWN_FUNCTION(pdo_informix); 44 | PHP_MINFO_FUNCTION(pdo_informix); 45 | 46 | PHP_FUNCTION(confirm_pdo_informix_compiled); /* For testing, remove later. */ 47 | 48 | /* 49 | Declare any global variables you may need between the BEGIN 50 | and END macros here: 51 | 52 | ZEND_BEGIN_MODULE_GLOBALS(pdo_informix) 53 | long global_value; 54 | char *global_string; 55 | ZEND_END_MODULE_GLOBALS(pdo_informix) 56 | */ 57 | 58 | /* 59 | In every utility function you add that needs to use variables 60 | in php_pdo_informix_globals, call TSRMLS_FETCH(); after declaring other 61 | variables used by that function, or better yet, pass in TSRMLS_CC 62 | after the last function argument and declare your utility function 63 | with TSRMLS_DC after the last declared argument. Always refer to 64 | the globals in your function as PDO_INFORMIX_G(variable). You are 65 | encouraged to rename these macros something shorter, see 66 | examples in any other php module directory. 67 | */ 68 | 69 | #ifdef ZTS 70 | #define PDO_INFORMIX_G(v) TSRMG(pdo_informix_globals_id, zend_pdo_informix_globals *, v) 71 | #else 72 | #define PDO_INFORMIX_G(v) (pdo_informix_globals.v) 73 | #endif 74 | 75 | #endif /* PHP_PDO_INFORMIX_H */ 76 | -------------------------------------------------------------------------------- /tests/fvt_031.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Tests all Fetch orientations 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | dsn .= ";EnableScrollableCursors=1;"; 14 | } 15 | public function runTest() 16 | { 17 | $this->connect(); 18 | $this->prepareDB(); 19 | 20 | $stmt = $this->db->prepare( "SELECT id, breed, name, weight FROM animals ORDER BY id" , 21 | array( PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL ) ); 22 | $stmt->execute(); 23 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_FIRST ); 24 | var_dump( $row ); 25 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_NEXT ); 26 | var_dump( $row ); 27 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_PRIOR ); 28 | var_dump( $row ); 29 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_LAST ); 30 | var_dump( $row ); 31 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_ABS , 2 ); 32 | var_dump( $row ); 33 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_REL , 1 ); 34 | var_dump( $row ); 35 | } 36 | } 37 | 38 | $testcase = new Test(); 39 | $testcase->runTest(); 40 | ?> 41 | --EXPECT-- 42 | array(8) { 43 | ["ID"]=> 44 | string(1) "0" 45 | [0]=> 46 | string(1) "0" 47 | ["BREED"]=> 48 | string(3) "cat" 49 | [1]=> 50 | string(3) "cat" 51 | ["NAME"]=> 52 | string(16) "Pook " 53 | [2]=> 54 | string(16) "Pook " 55 | ["WEIGHT"]=> 56 | string(4) "3.20" 57 | [3]=> 58 | string(4) "3.20" 59 | } 60 | array(8) { 61 | ["ID"]=> 62 | string(1) "1" 63 | [0]=> 64 | string(1) "1" 65 | ["BREED"]=> 66 | string(3) "dog" 67 | [1]=> 68 | string(3) "dog" 69 | ["NAME"]=> 70 | string(16) "Peaches " 71 | [2]=> 72 | string(16) "Peaches " 73 | ["WEIGHT"]=> 74 | string(5) "12.30" 75 | [3]=> 76 | string(5) "12.30" 77 | } 78 | array(8) { 79 | ["ID"]=> 80 | string(1) "0" 81 | [0]=> 82 | string(1) "0" 83 | ["BREED"]=> 84 | string(3) "cat" 85 | [1]=> 86 | string(3) "cat" 87 | ["NAME"]=> 88 | string(16) "Pook " 89 | [2]=> 90 | string(16) "Pook " 91 | ["WEIGHT"]=> 92 | string(4) "3.20" 93 | [3]=> 94 | string(4) "3.20" 95 | } 96 | array(8) { 97 | ["ID"]=> 98 | string(1) "6" 99 | [0]=> 100 | string(1) "6" 101 | ["BREED"]=> 102 | string(5) "llama" 103 | [1]=> 104 | string(5) "llama" 105 | ["NAME"]=> 106 | string(16) "Sweater " 107 | [2]=> 108 | string(16) "Sweater " 109 | ["WEIGHT"]=> 110 | string(6) "150.00" 111 | [3]=> 112 | string(6) "150.00" 113 | } 114 | array(8) { 115 | ["ID"]=> 116 | string(1) "1" 117 | [0]=> 118 | string(1) "1" 119 | ["BREED"]=> 120 | string(3) "dog" 121 | [1]=> 122 | string(3) "dog" 123 | ["NAME"]=> 124 | string(16) "Peaches " 125 | [2]=> 126 | string(16) "Peaches " 127 | ["WEIGHT"]=> 128 | string(5) "12.30" 129 | [3]=> 130 | string(5) "12.30" 131 | } 132 | array(8) { 133 | ["ID"]=> 134 | string(1) "2" 135 | [0]=> 136 | string(1) "2" 137 | ["BREED"]=> 138 | string(5) "horse" 139 | [1]=> 140 | string(5) "horse" 141 | ["NAME"]=> 142 | string(16) "Smarty " 143 | [2]=> 144 | string(16) "Smarty " 145 | ["WEIGHT"]=> 146 | string(6) "350.00" 147 | [3]=> 148 | string(6) "350.00" 149 | } 150 | -------------------------------------------------------------------------------- /tests/fvt_016.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Insert integer by binding an empty string, a NULL, and an integer string to column 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | /* Drop the test table, in case it exists */ 16 | $drop = 'DROP TABLE animals'; 17 | $result = $this->db->exec( $drop ); 18 | } catch( Exception $e ){} 19 | 20 | /* Create the test table */ 21 | $create = 'CREATE TABLE animals (id INTEGER)'; 22 | $result = $this->db->exec( $create ); 23 | 24 | $null = NULL; 25 | $empty_string0 = ""; 26 | $empty_string1 = ""; 27 | $int_string = "0"; 28 | 29 | $sql = "INSERT INTO animals VALUES ( :mynull0 ) "; 30 | $stmt = $this->db->prepare ( $sql ); 31 | $stmt->bindParam ( ":mynull0" , $null ); 32 | $stmt->execute(); 33 | $stmt = $this->db->query( "SELECT * FROM animals" ); 34 | $res = $stmt->fetch( PDO::FETCH_BOTH ); 35 | $rows = $res[0]; 36 | print "Null contents: $rows\n"; 37 | 38 | $delete = 'DELETE FROM animals'; 39 | $result = $this->db->exec( $delete ); 40 | 41 | $sql = "INSERT INTO animals VALUES ( :mynull1 ) "; 42 | $stmt = $this->db->prepare ( $sql ); 43 | $stmt->bindParam ( ":mynull1" , $null, PDO::PARAM_INT ); 44 | $stmt->execute(); 45 | $stmt = $this->db->query( "SELECT * FROM animals" ); 46 | $res = $stmt->fetch( PDO::FETCH_BOTH ); 47 | $rows = $res[0]; 48 | print "Null contents with int specified: $rows\n"; 49 | 50 | $delete = 'DELETE FROM animals'; 51 | $result = $this->db->exec( $delete ); 52 | 53 | $sql = "INSERT INTO animals VALUES ( :myemptystring0 ) "; 54 | $stmt = $this->db->prepare ( $sql ); 55 | $stmt->bindParam ( ":myemptystring0" , $empty_string0); 56 | $stmt->execute(); 57 | $stmt = $this->db->query( "SELECT * FROM animals" ); 58 | $res = $stmt->fetch( PDO::FETCH_BOTH ); 59 | $rows = $res[0]; 60 | print "Empty string contents: $rows\n"; 61 | 62 | $delete = 'DELETE FROM animals'; 63 | $result = $this->db->exec( $delete ); 64 | 65 | $sql = "INSERT INTO animals VALUES ( :myemptystring1 ) "; 66 | $stmt = $this->db->prepare ( $sql ); 67 | $stmt->bindParam ( ":myemptystring1" , $empty_string1, PDO::PARAM_INT ); 68 | $stmt->execute(); 69 | $stmt = $this->db->query( "SELECT * FROM animals" ); 70 | $res = $stmt->fetch( PDO::FETCH_BOTH ); 71 | $rows = $res[0]; 72 | print "Empty string contents with int specified: $rows\n"; 73 | 74 | $delete = 'DELETE FROM animals'; 75 | $result = $this->db->exec( $delete ); 76 | 77 | $sql = "INSERT INTO animals VALUES ( :myintstring0 ) "; 78 | $stmt = $this->db->prepare ( $sql ); 79 | $stmt->bindParam ( ":myintstring0" , $int_string ); 80 | $stmt->execute(); 81 | $stmt = $this->db->query( "SELECT * FROM animals" ); 82 | $res = $stmt->fetch( PDO::FETCH_BOTH ); 83 | $rows = $res[0]; 84 | print "Int string contents: $rows\n"; 85 | 86 | $delete = 'DELETE FROM animals'; 87 | $result = $this->db->exec( $delete ); 88 | 89 | $sql = "INSERT INTO animals VALUES ( :myintstring1 ) "; 90 | $stmt = $this->db->prepare ( $sql ); 91 | $stmt->bindParam ( ":myintstring1" , $int_string, PDO::PARAM_INT ); 92 | $stmt->execute(); 93 | $stmt = $this->db->query( "SELECT * FROM animals" ); 94 | $res = $stmt->fetch( PDO::FETCH_BOTH ); 95 | $rows = $res[0]; 96 | print "Int string contents with int specified: $rows\n"; 97 | 98 | print "done\n"; 99 | } 100 | } 101 | 102 | $testcase = new Test(); 103 | $testcase->runTest(); 104 | ?> 105 | --EXPECT-- 106 | Null contents: 107 | Null contents with int specified: 108 | Empty string contents: 0 109 | Empty string contents with int specified: 110 | Int string contents: 0 111 | Int string contents with int specified: 0 112 | done 113 | -------------------------------------------------------------------------------- /tests/fvt_013.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Scrollable cursor; retrieve negative row 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | $this->prepareDB(); 14 | 15 | $stmt = $this->db->prepare( "SELECT * FROM animals" , array(PDO::ATTR_CURSOR, PDO::CURSOR_SCROLL) ); 16 | $stmt->execute(); 17 | var_dump( $stmt->fetchAll() ); 18 | $stmt->execute(); 19 | try{ 20 | $row = $stmt->fetch( PDO::FETCH_BOTH , PDO::FETCH_ORI_ABS , -1 ); 21 | var_dump( $row ); 22 | }catch( PDOException $e ){ 23 | $info = $stmt->errorInfo(); 24 | if( $info[1] == -11086 ) 25 | { 26 | print "Cannot retrieve negative row\n"; 27 | } 28 | else 29 | { 30 | print $e . "\n"; 31 | } 32 | } 33 | } 34 | } 35 | 36 | $testcase = new Test(); 37 | $testcase->runTest(); 38 | ?> 39 | --EXPECT-- 40 | array(7) { 41 | [0]=> 42 | array(8) { 43 | ["ID"]=> 44 | string(1) "0" 45 | [0]=> 46 | string(1) "0" 47 | ["BREED"]=> 48 | string(3) "cat" 49 | [1]=> 50 | string(3) "cat" 51 | ["NAME"]=> 52 | string(16) "Pook " 53 | [2]=> 54 | string(16) "Pook " 55 | ["WEIGHT"]=> 56 | string(4) "3.20" 57 | [3]=> 58 | string(4) "3.20" 59 | } 60 | [1]=> 61 | array(8) { 62 | ["ID"]=> 63 | string(1) "1" 64 | [0]=> 65 | string(1) "1" 66 | ["BREED"]=> 67 | string(3) "dog" 68 | [1]=> 69 | string(3) "dog" 70 | ["NAME"]=> 71 | string(16) "Peaches " 72 | [2]=> 73 | string(16) "Peaches " 74 | ["WEIGHT"]=> 75 | string(5) "12.30" 76 | [3]=> 77 | string(5) "12.30" 78 | } 79 | [2]=> 80 | array(8) { 81 | ["ID"]=> 82 | string(1) "2" 83 | [0]=> 84 | string(1) "2" 85 | ["BREED"]=> 86 | string(5) "horse" 87 | [1]=> 88 | string(5) "horse" 89 | ["NAME"]=> 90 | string(16) "Smarty " 91 | [2]=> 92 | string(16) "Smarty " 93 | ["WEIGHT"]=> 94 | string(6) "350.00" 95 | [3]=> 96 | string(6) "350.00" 97 | } 98 | [3]=> 99 | array(8) { 100 | ["ID"]=> 101 | string(1) "3" 102 | [0]=> 103 | string(1) "3" 104 | ["BREED"]=> 105 | string(9) "gold fish" 106 | [1]=> 107 | string(9) "gold fish" 108 | ["NAME"]=> 109 | string(16) "Bubbles " 110 | [2]=> 111 | string(16) "Bubbles " 112 | ["WEIGHT"]=> 113 | string(4) "0.10" 114 | [3]=> 115 | string(4) "0.10" 116 | } 117 | [4]=> 118 | array(8) { 119 | ["ID"]=> 120 | string(1) "4" 121 | [0]=> 122 | string(1) "4" 123 | ["BREED"]=> 124 | string(10) "budgerigar" 125 | [1]=> 126 | string(10) "budgerigar" 127 | ["NAME"]=> 128 | string(16) "Gizmo " 129 | [2]=> 130 | string(16) "Gizmo " 131 | ["WEIGHT"]=> 132 | string(4) "0.20" 133 | [3]=> 134 | string(4) "0.20" 135 | } 136 | [5]=> 137 | array(8) { 138 | ["ID"]=> 139 | string(1) "5" 140 | [0]=> 141 | string(1) "5" 142 | ["BREED"]=> 143 | string(4) "goat" 144 | [1]=> 145 | string(4) "goat" 146 | ["NAME"]=> 147 | string(16) "Rickety Ride " 148 | [2]=> 149 | string(16) "Rickety Ride " 150 | ["WEIGHT"]=> 151 | string(4) "9.70" 152 | [3]=> 153 | string(4) "9.70" 154 | } 155 | [6]=> 156 | array(8) { 157 | ["ID"]=> 158 | string(1) "6" 159 | [0]=> 160 | string(1) "6" 161 | ["BREED"]=> 162 | string(5) "llama" 163 | [1]=> 164 | string(5) "llama" 165 | ["NAME"]=> 166 | string(16) "Sweater " 167 | [2]=> 168 | string(16) "Sweater " 169 | ["WEIGHT"]=> 170 | string(6) "150.00" 171 | [3]=> 172 | string(6) "150.00" 173 | } 174 | } 175 | Cannot retrieve negative row 176 | -------------------------------------------------------------------------------- /tests/fvt_038.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Testing the lastInsertID function. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | try { 14 | /* Drop the test table, in case it exists */ 15 | $drop = 'DROP TABLE animals'; 16 | $result = $this->db->exec( $drop ); 17 | } catch( Exception $e ){} 18 | try { 19 | /* Drop the test table, in case it exists */ 20 | $drop = 'DROP TABLE owner'; 21 | $result = $this->db->exec( $drop ); 22 | } catch( Exception $e ){} 23 | 24 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 25 | 26 | /* Create the test table */ 27 | $create = 'CREATE TABLE animals (id INTEGER, name varchar(20))'; 28 | $result = $this->db->exec( $create ); 29 | $stmt = $this->db->query( "INSERT INTO animals ( id, name ) VALUES ( 1, 'dog' )" ); 30 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 31 | 32 | $drop = 'DROP TABLE animals'; 33 | $result = $this->db->exec( $drop ); 34 | 35 | /* Create the test table */ 36 | $create = 'CREATE TABLE animals (id SERIAL, name varchar(20))'; 37 | 38 | $result = $this->db->exec( $create ); 39 | $stmt = $this->db->exec( "INSERT INTO animals (name) VALUES ( 'dog' )" ); 40 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 41 | 42 | $sql = "select id from animals "; 43 | $stmt = $this->db->query($sql); 44 | $res = $stmt->fetch(); 45 | print_r($res); 46 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n"; 47 | 48 | $stmt = $this->db->query( "INSERT INTO animals (id, name) VALUES ( 1147483647, 'dog' )" ); 49 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n"; 50 | 51 | $stmt = $this->db->query( "INSERT INTO animals (name) VALUES ( 'dog' )" ); 52 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n"; 53 | 54 | /* Create the test table */ 55 | $create = 'CREATE TABLE owner (id SERIAL8, name varchar(20))'; 56 | $result = $this->db->exec( $create ); 57 | $stmt = $this->db->query( "INSERT INTO owner (name) VALUES ( 'tom' )" ); 58 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 59 | 60 | $drop = 'DROP TABLE animals'; 61 | $result = $this->db->exec( $drop ); 62 | 63 | /* Create the test table */ 64 | $create = 'CREATE TABLE animals (id INTEGER, name varchar(20))'; 65 | $result = $this->db->exec( $create ); 66 | $stmt = $this->db->query( "INSERT INTO animals ( id, name ) VALUES ( 1, 'dog' )" ); 67 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 68 | 69 | $drop = 'DROP TABLE animals'; 70 | $result = $this->db->exec( $drop ); 71 | 72 | /* Create the test table */ 73 | $create = 'CREATE TABLE animals (id SERIAL, name varchar(20))'; 74 | $result = $this->db->exec( $create ); 75 | $stmt = $this->db->prepare( "INSERT INTO animals ( id, name ) VALUES ( 1, 'dog' )" ); 76 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 77 | $stmt->execute(); 78 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 79 | 80 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 81 | print "Last Insert Id: " . $this->db->lastInsertId( "INSERT INTO animals ( id, name ) 82 | VALUES ( 2, 'dog' )" ) . "\n" ; 83 | $stmt->closeCursor(); 84 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 85 | $stmt = $this->db->prepare( "INSERT INTO animals ( id, name ) VALUES ( 2, 'dog' )" ); 86 | $stmt->closeCursor(); 87 | print "Last Insert Id: " . $this->db->lastInsertId() . "\n" ; 88 | print "Last Insert Id: " . $this->db->lastInsertId( null ); 89 | 90 | } 91 | } 92 | $testcase = new Test(); 93 | $testcase->runTest(); 94 | ?> 95 | --EXPECTF-- 96 | Last Insert Id: 0 97 | Last Insert Id: 0 98 | Last Insert Id: 1 99 | Array 100 | ( 101 | [ID] => 1 102 | [0] => 1 103 | ) 104 | Last Insert Id: 1 105 | Last Insert Id: 1147483647 106 | Last Insert Id: 1147483648 107 | Last Insert Id: 0 108 | Last Insert Id: 0 109 | Last Insert Id: 0 110 | Last Insert Id: 1 111 | Last Insert Id: 1 112 | Last Insert Id: 1 113 | Last Insert Id: 1 114 | Last Insert Id: 1 115 | Last Insert Id: 1 116 | -------------------------------------------------------------------------------- /tests/clob.dat: -------------------------------------------------------------------------------- 1 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 2 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 3 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 4 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 5 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 6 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | if test "$PHP_PDO" != "no"; then 2 | 3 | PHP_ARG_WITH(pdo-informix, for Informix driver for PDO, 4 | [ --with-pdo-informix[=DIR] Include PDO Informix support, DIR is the base 5 | Informix install directory, defaults to ${INFORMIXDIR:-nothing}.]) 6 | 7 | if test "$PHP_PDO_INFORMIX" != "no"; then 8 | 9 | if test -n "$PHP_PDO_INFORMIX" -a "$PHP_PDO_INFORMIX" != "yes"; then 10 | INFORMIXDIR="$PHP_PDO_INFORMIX" 11 | else 12 | if test "$INFORMIXDIR" = ""; then 13 | AC_MSG_ERROR([INFORMIXDIR environment variable is not set. Please use --with-pdo-informix= or set the INFORMIXDIR environment variable.]) 14 | fi 15 | fi 16 | 17 | AC_MSG_CHECKING([for PDO includes]) 18 | if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then 19 | pdo_inc_path=$abs_srcdir/ext 20 | elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then 21 | pdo_inc_path=$abs_srcdir/ext 22 | elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then 23 | pdo_inc_path=$prefix/include/php/ext 24 | else 25 | AC_MSG_ERROR([Cannot find php_pdo_driver.h.]) 26 | fi 27 | AC_MSG_RESULT($pdo_inc_path) 28 | 29 | dnl Don't forget to add additional source files here 30 | php_pdo_informix_sources_core="pdo_informix.c informix_driver.c informix_statement.c" 31 | 32 | AC_MSG_CHECKING([for includes and libraries]) 33 | 34 | if test -d "$INFORMIXDIR"; then 35 | if test ! -d "$INFORMIXDIR/incl/cli"; then 36 | AC_MSG_ERROR([Cannot find Informix Client SDK includes in $INFORMIXDIR/inc/cli]) 37 | fi 38 | if test ! -d "$INFORMIXDIR/incl/esql"; then 39 | AC_MSG_ERROR([Cannot find ESQL/C includes in $INFORMIXDIR/inc/esql]) 40 | fi 41 | if test ! -d "$INFORMIXDIR/$PHP_LIBDIR"; then 42 | AC_MSG_ERROR([Cannot find Informix libraries in $INFORMIXDIR/$PHP_LIBDIR]) 43 | fi 44 | if test ! -d "$INFORMIXDIR/$PHP_LIBDIR/cli"; then 45 | AC_MSG_ERROR([Cannot find Informix Client SDK libraries in $INFORMIXDIR/$PHP_LIBDIR/cli]) 46 | fi 47 | if test ! -d "$INFORMIXDIR/$PHP_LIBDIR/esql"; then 48 | AC_MSG_ERROR([Cannot find ESQL/C libraries in $INFORMIXDIR/$PHP_LIBDIR/esql]) 49 | fi 50 | else 51 | AC_MSG_ERROR([Informix base installation directory '$INFORMIXDIR' doesn't exist.]) 52 | fi 53 | 54 | AC_MSG_RESULT($INFORMIXDIR) 55 | 56 | PHP_ADD_INCLUDE($INFORMIXDIR/incl/cli) 57 | PHP_ADD_INCLUDE($INFORMIXDIR/incl/esql) 58 | dnl PHP_ADD_INCLUDE($INFORMIXDIR/incl/) 59 | PHP_ADD_LIBPATH($INFORMIXDIR/$PHP_LIBDIR, PDO_INFORMIX_SHARED_LIBADD) 60 | PHP_ADD_LIBPATH($INFORMIXDIR/$PHP_LIBDIR/cli, PDO_INFORMIX_SHARED_LIBADD) 61 | PHP_ADD_LIBPATH($INFORMIXDIR/$PHP_LIBDIR/esql, PDO_INFORMIX_SHARED_LIBADD) 62 | 63 | dnl Check if thread safety flags are needed 64 | if test "$enable_experimental_zts" = "yes"; then 65 | IFX_ESQL_FLAGS="-thread" 66 | CPPFLAGS="$CPPFLAGS -DIFX_THREAD" 67 | else 68 | IFX_ESQL_FLAGS="" 69 | fi 70 | 71 | IFX_LIBS=`THREADLIB=POSIX $INFORMIXDIR/bin/esql $IFX_ESQL_FLAGS -libs` 72 | IFX_LIBS=`echo $IFX_LIBS | sed -e 's/Libraries to be used://g' -e 's/esql: error -55923: No source or object file\.//g'` 73 | 74 | dnl Seems to get rid of newlines. 75 | dnl According to Perls DBD-Informix, might contain these strings. 76 | 77 | case "$host_alias" in 78 | *aix*) 79 | CPPFLAGS="$CPPFLAGS -D__H_LOCALEDEF";; 80 | esac 81 | 82 | AC_MSG_CHECKING([Informix version]) 83 | IFX_VERSION=[`$INFORMIXDIR/bin/esql -V | grep "ESQL Version" | sed -ne '1 s/\(.*\)ESQL Version \([0-9]*\)\.\([0-9]*\).*/\2\3/p'`] 84 | AC_MSG_RESULT($IFX_VERSION) 85 | AC_DEFINE_UNQUOTED(IFX_VERSION, $IFX_VERSION, [ ]) 86 | 87 | if test $IFX_VERSION -ge 900; then 88 | AC_DEFINE(HAVE_IFX_IUS,1,[ ]) 89 | dnl IFX_ESQL_FLAGS="$IFX_ESQL_FLAGS -EDHAVE_IFX_IUS" 90 | dnl else 91 | dnl IFX_ESQL_FLAGS="$IFX_ESQL_FLAGS -EUHAVE_IFX_IUS" 92 | fi 93 | 94 | PHP_NEW_EXTENSION(pdo_informix, $php_pdo_informix_sources_core, $ext_shared,,-I$pdo_inc_path) 95 | 96 | PHP_ADD_MAKEFILE_FRAGMENT 97 | 98 | PHP_ADD_LIBRARY_DEFER(ifcli, 1, PDO_INFORMIX_SHARED_LIBADD) 99 | PHP_ADD_LIBRARY_DEFER(ifdmr, 1, PDO_INFORMIX_SHARED_LIBADD) 100 | 101 | 102 | for i in $IFX_LIBS; do 103 | case "$i" in 104 | *.o) 105 | IFX_LIBOBJS="$IFX_LIBOBJS $i" 106 | PHP_ADD_LIBPATH($ext_builddir, PDO_INFORMIX_SHARED_LIBADD) 107 | dnl PHP_ADD_LIBRARY_DEFER(pdo_informix, 1, PDO_INFORMIX_SHARED_LIBADD) 108 | ;; 109 | -lm) 110 | ;; 111 | -lc) 112 | ;; 113 | -l*) 114 | lib=`echo $i | cut -c 3-` 115 | PHP_ADD_LIBRARY_DEFER($lib, 1, PDO_INFORMIX_SHARED_LIBADD) 116 | ;; 117 | *.a) 118 | case "`uname -s 2>/dev/null`" in 119 | UnixWare | SCO_SV | UNIX_SV) 120 | DLIBS="$DLIBS $i" 121 | ;; 122 | *) 123 | ac_dir="`echo $i|sed 's#[^/]*$##;s#\/$##'`" 124 | ac_lib="`echo $i|sed 's#^/.*/$PHP_LIBDIR##g;s#\.a##g'`" 125 | DLIBS="$DLIBS -L$ac_dir -l$ac_lib" 126 | ;; 127 | esac 128 | ;; 129 | esac 130 | done 131 | 132 | PHP_SUBST(PDO_INFORMIX_SHARED_LIBADD) 133 | PHP_SUBST(INFORMIXDIR) 134 | PHP_SUBST(IFX_LIBOBJS) 135 | PHP_SUBST(IFX_ESQL_FLAGS) 136 | 137 | fi 138 | 139 | fi 140 | -------------------------------------------------------------------------------- /tests/TESTMATRIX: -------------------------------------------------------------------------------- 1 | Driver exposed function Purpose FVT's 2 | --------------------------------+-----------------------------------+-------------------- 3 | informix_handle_closer | close connection | 4 | informix_handle_preparer | prepare statement | fvt_031 5 | -> bind column | | pdo_015 6 | -> bind param | | pdo_021,pdo_024 7 | -> bind value | | pdo_028 8 | informix_handle_doer | query / execute / #rows affected | fvt_002,fvt_010,fvt_011,fvt_012,fvt_014 9 | informix_handle_begin | begin transaction | pdo_017 10 | informix_handle_commit | commit transaction | 11 | -> with AUTOCOMMIT = 0 | | fvt_023 12 | -> with AUTOCOMMIT = 1,begin| | fvt_020 13 | -+- -+- 14 | informix_handle_rollback | rollback transaction | 15 | -> with AUTOCOMMIT = 0 | | fvt_021 16 | -> with AUTOCOMMIT = 1,begin| | pdo_017 17 | -+- -+- 18 | informix_handle_get_attribute | get attributes | fvt_020,fvt_021 19 | -> ATTR_AUTOCOMMIT | | 20 | -> ATTR_PREFETCH | (NO IMPL) | 21 | -> ATTR_TIMEOUT | (NO IMPL) | 22 | -> ATTR_SERVER_VERSION | (NO IMPL) <-- | 23 | -> ATTR_CLIENT_VERSION | | 24 | -> ATTR_SERVER_INFO | (NO IMPL) | 25 | -> ATTR_CONNECTION_STATUS | (NO IMPL) | 26 | -> ATTR_PERSISTENT | (NO IMPL) | 27 | -> ATTR_FETCH_CATALOG_NAMES | (NO IMPL) | 28 | -> ATTR_FETCH_TABLE_NAMES | (NO IMPL) | 29 | -+- -+- 30 | informix_handle_set_attribute | set attributes (NO IMPL) | fvt_020,fvt_021 31 | -> ATTR_AUTOCOMMIT | | 32 | -> ATTR_PREFETCH | | 33 | -> ATTR_TIMEOUT | | 34 | -> ATTR_PERSISTENT | | 35 | -> ATTR_FETCH_CATALOG_NAMES | | 36 | -> ATTR_FETCH_TABLE_NAMES | | 37 | -+- -+- 38 | informix_handle_factory | open connection | fvt_001,fvt_003,fvt_004 39 | ================================|===================================|================== 40 | informix_stmt_dtor | close statement | 41 | informix_stmt_executer | execute | fvt_031 42 | -> LOB as stream | | bug_34630 43 | -> LOB as string | | 44 | -> other simple datatypes | | pdo_021,pdo_024 45 | -+- -+- 46 | informix_stmt_fetcher | fetch | 47 | -> Forward Only | | pdo_020,fvt_031 48 | -> FETCH_ORI_FIRST | | fvt_031 49 | -> FETCH_ORI_LAST | | fvt_031 50 | -> FETCH_ORI_NEXT | | fvt_031 51 | -> FETCH_ORI_PRIOR | | fvt_031 52 | -> FETCH_ORI_ABS | | fvt_013,fvt_031 53 | -> FETCH_ORI_REL | | fvt_031 54 | -+- -+- 55 | informix_stmt_describer | fetch | 56 | informix_stmt_get_col | fetch | pdo_012,pdo_013,pdo_019 57 | -> FETCH_BOUND | | pdo_016,pdo_016a 58 | -> FETCH_ASSOC | | pdo_001 59 | -> FETCH_NAMED | | 60 | -> FETCH_NUM | | pdo_002 61 | -> FETCH_BOTH | | pdo_003,fvt_030 62 | -> FETCH_OBJ | | pdo_004 63 | -> FETCH_COLUMN | | pdo_015 64 | -> FETCH_CLASS | | pdo_005 65 | -> FETCH_GROUP | | pdo_006 66 | -> FETCH_UNIQUE | | pdo_007,pdo_008 67 | -> FETCH_CLASSTYPE | | pdo_009,pdo_010 68 | -> FETCH_FUNC | | pdo_011 69 | -> FETCH_INTO | | pdo_025 70 | -> FETCH_LAZY | | pdo_027 71 | -+- -+- 72 | informix_stmt_param_hook | bound parameters/columns | 73 | informix_stmt_set_attribute | sets attributes | 74 | -> ATTR_CURSOR_NAME | | 75 | -> ATTR_CURSOR | | 76 | -+- -+- 77 | informix_stmt_get_attribute | gets attributes | 78 | -> ATTR_CURSOR_NAME | | 79 | -> ATTR_CURSOR | | 80 | -+- -+- 81 | informix_stmt_get_column_meta | column meta data | pdo_022(skip) 82 | informix_stmt_next_rowset | next row set | 83 | 84 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | PDO_INFORMIX 7 | pecl.php.net 8 | PDO driver for IBM Informix INFORMIX databases 9 | This extension provides an IBM Informix Dynamic Server driver for PDO. To build and run 10 | PDO_INFORMIX, you must install the Informix Client Software Development Kit (CSDK) 11 | from http://ibm.com/informix/downloads.html. 12 | 13 | 14 | Rahul Priyadarshi 15 | rahulpriyadarshi 16 | rahul.priyadarshi@in.ibm.com 17 | yes 18 | 19 | 20 | IBM OpenDev 21 | kfbombar 22 | opendev@us.ibm.com 23 | yes 24 | 25 | 2013-06-16 26 | 27 | 28 | 1.3.1 29 | 1.3.1 30 | 31 | 32 | stable 33 | stable 34 | 35 | Apache License 2.0 36 | 37 | Fixed: Segmentation fault while fetching null value for Integer Field in specific case 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 5.0.3 105 | 106 | 107 | 1.4.0b1 108 | 109 | 110 | PDO 111 | pear.php.net 112 | 113 | 114 | 115 | PDO_INFORMIX 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /pdo_informix.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | (C) Copyright IBM Corporation 2006. | 4 | +----------------------------------------------------------------------+ 5 | | | 6 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 7 | | may not use this file except in compliance with the License. You may | 8 | | obtain a copy of the License at | 9 | | http://www.apache.org/licenses/LICENSE-2.0 | 10 | | | 11 | | Unless required by applicable law or agreed to in writing, software | 12 | | distributed under the License is distributed on an "AS IS" BASIS, | 13 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 14 | | implied. See the License for the specific language governing | 15 | | permissions and limitations under the License. | 16 | +----------------------------------------------------------------------+ 17 | | Authors: Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier, | 18 | | Ambrish Bhargava, Rahul Priyadarshi | 19 | +----------------------------------------------------------------------+ 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "php_ini.h" 28 | #include "ext/standard/info.h" 29 | #include "pdo/php_pdo_driver.h" 30 | #include "php_pdo_informix.h" 31 | #include "php_pdo_informix_int.h" 32 | 33 | /* If you declare any globals in php_pdo_informix.h uncomment this: 34 | ZEND_DECLARE_MODULE_GLOBALS(pdo_informix) 35 | */ 36 | 37 | /* True global resources - no need for thread safety here */ 38 | static int le_pdo_informix; 39 | extern pdo_driver_t pdo_informix_driver; /* the registration table */ 40 | 41 | /* {{{ pdo_informix_functions[] 42 | * 43 | * Every user visible function must have an entry in pdo_informix_functions[]. 44 | */ 45 | zend_function_entry pdo_informix_functions[] = 46 | { 47 | PHP_FE(confirm_pdo_informix_compiled, NULL) /* For testing, remove later. */ 48 | { 49 | NULL, NULL, NULL 50 | } /* Must be the last line in pdo_informix_functions[] */ 51 | }; 52 | /* }}} */ 53 | 54 | /* {{{ pdo_informix_deps 55 | */ 56 | #if ZEND_MODULE_API_NO >= 20041225 57 | static zend_module_dep pdo_informix_deps[] = { 58 | ZEND_MOD_REQUIRED("pdo") 59 | {NULL, NULL, NULL} 60 | }; 61 | #endif 62 | /* }}} */ 63 | 64 | /* {{{ pdo_informix_module_entry 65 | */ 66 | zend_module_entry pdo_informix_module_entry = 67 | { 68 | #if ZEND_MODULE_API_NO >= 20041225 69 | STANDARD_MODULE_HEADER_EX, NULL, 70 | pdo_informix_deps, 71 | #else 72 | STANDARD_MODULE_HEADER, 73 | #endif 74 | "pdo_informix", 75 | pdo_informix_functions, 76 | PHP_MINIT(pdo_informix), 77 | PHP_MSHUTDOWN(pdo_informix), 78 | PHP_RINIT(pdo_informix), /* Replace with NULL if there's nothing to do at request start */ 79 | PHP_RSHUTDOWN(pdo_informix), /* Replace with NULL if there's nothing to do at request end */ 80 | PHP_MINFO(pdo_informix), 81 | PDO_INFORMIX_VERSION, /* Replace with version number for your extension */ 82 | STANDARD_MODULE_PROPERTIES 83 | }; 84 | /* }}} */ 85 | 86 | #ifdef COMPILE_DL_PDO_INFORMIX 87 | ZEND_GET_MODULE(pdo_informix) 88 | #endif 89 | 90 | /* {{{ PHP_INI 91 | */ 92 | /* Remove comments and fill if you need to have entries in php.ini 93 | PHP_INI_BEGIN() 94 | STD_PHP_INI_ENTRY("pdo_informix.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_pdo_informix_globals, pdo_informix_globals) 95 | STD_PHP_INI_ENTRY("pdo_informix.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_pdo_informix_globals, pdo_informix_globals) 96 | PHP_INI_END() 97 | */ 98 | /* }}} */ 99 | 100 | /* {{{ php_pdo_informix_init_globals 101 | */ 102 | /* Uncomment this function if you have INI entries 103 | static void php_pdo_informix_init_globals(zend_pdo_informix_globals *pdo_informix_globals) 104 | { 105 | pdo_informix_globals->global_value = 0; 106 | pdo_informix_globals->global_string = NULL; 107 | } 108 | */ 109 | /* }}} */ 110 | 111 | /* {{{ PHP_MINIT_FUNCTION 112 | */ 113 | PHP_MINIT_FUNCTION(pdo_informix) 114 | { 115 | /* If you have INI entries, uncomment these lines 116 | ZEND_INIT_MODULE_GLOBALS(pdo_informix, php_pdo_informix_init_globals, NULL); 117 | REGISTER_INI_ENTRIES(); 118 | */ 119 | 120 | 121 | php_pdo_register_driver(&pdo_informix_driver); 122 | return TRUE; 123 | } 124 | /* }}} */ 125 | 126 | /* {{{ PHP_MSHUTDOWN_FUNCTION 127 | */ 128 | PHP_MSHUTDOWN_FUNCTION(pdo_informix) 129 | { 130 | /* uncomment this line if you have INI entries 131 | UNREGISTER_INI_ENTRIES(); 132 | */ 133 | 134 | php_pdo_unregister_driver(&pdo_informix_driver); 135 | return TRUE; 136 | } 137 | /* }}} */ 138 | 139 | /* Remove if there's nothing to do at request start */ 140 | /* {{{ PHP_RINIT_FUNCTION 141 | */ 142 | PHP_RINIT_FUNCTION(pdo_informix) 143 | { 144 | return TRUE; 145 | } 146 | /* }}} */ 147 | 148 | /* Remove if there's nothing to do at request end */ 149 | /* {{{ PHP_RSHUTDOWN_FUNCTION 150 | */ 151 | PHP_RSHUTDOWN_FUNCTION(pdo_informix) 152 | { 153 | return TRUE; 154 | } 155 | /* }}} */ 156 | 157 | /* {{{ PHP_MINFO_FUNCTION 158 | */ 159 | PHP_MINFO_FUNCTION(pdo_informix) 160 | { 161 | php_info_print_table_start(); 162 | php_info_print_table_header(2, "pdo_informix support", "enabled"); 163 | php_info_print_table_row(2, "Module release", PDO_INFORMIX_VERSION); 164 | php_info_print_table_end(); 165 | 166 | /* Remove comments if you have entries in php.ini 167 | DISPLAY_INI_ENTRIES(); 168 | */ 169 | } 170 | /* }}} */ 171 | 172 | 173 | /* Remove the following function when you have succesfully modified config.m4 174 | so that your module can be compiled into PHP, it exists only for testing 175 | purposes. */ 176 | 177 | /* Every user-visible function in PHP should document itself in the source */ 178 | /* {{{ proto string confirm_pdo_informix_compiled(string arg) 179 | Return a string to confirm that the module is compiled in */ 180 | PHP_FUNCTION(confirm_pdo_informix_compiled) 181 | { 182 | char *arg = NULL; 183 | int arg_len, len; 184 | char string[256]; 185 | 186 | if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FALSE) 187 | { 188 | return; 189 | } 190 | 191 | len = sprintf(string, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "pdo_informix", arg); 192 | RETURN_STRINGL(string, len, 1); 193 | } 194 | /* }}} */ 195 | -------------------------------------------------------------------------------- /php_pdo_informix_int.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | (C) Copyright IBM Corporation 2006 | 4 | +----------------------------------------------------------------------+ 5 | | | 6 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 7 | | may not use this file except in compliance with the License. You may | 8 | | obtain a copy of the License at | 9 | | http://www.apache.org/licenses/LICENSE-2.0 | 10 | | | 11 | | Unless required by applicable law or agreed to in writing, software | 12 | | distributed under the License is distributed on an "AS IS" BASIS, | 13 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 14 | | implied. See the License for the specific language governing | 15 | | permissions and limitations under the License. | 16 | +----------------------------------------------------------------------+ 17 | | Authors: Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier, | 18 | | Ambrish Bhargava, Rahul Priyadarshi | 19 | +----------------------------------------------------------------------+ 20 | */ 21 | 22 | #ifndef PHP_PDO_INFORMIX_INT_H 23 | #define PHP_PDO_INFORMIX_INT_H 24 | 25 | #include "infxcli.h" 26 | 27 | 28 | #define MAX_OPTION_LEN 10 29 | #define MAX_ERR_MSG_LEN (SQL_MAX_MESSAGE_LENGTH + SQL_SQLSTATE_SIZE + 1) 30 | #define CDTIMETYPE 112 31 | 32 | #ifndef SQL_XML 33 | #define SQL_XML -370 34 | #endif 35 | 36 | /* Maximum length of the name of the DBMS being accessed */ 37 | #define MAX_DBMS_IDENTIFIER_NAME 256 38 | 39 | 40 | #ifndef SQL_ATTR_GET_GENERATED_VALUE 41 | #define SQL_ATTR_GET_GENERATED_VALUE 2583 42 | #endif 43 | 44 | 45 | 46 | /* This function is called after executing a stmt for recording lastInsertId */ 47 | int record_last_insert_id( pdo_dbh_t *dbh, SQLHANDLE hstmt TSRMLS_DC); 48 | 49 | 50 | /* error handling functions and macros. */ 51 | void raise_sql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, SQLHANDLE handle, SQLSMALLINT hType, char *tag, char *file, int line TSRMLS_DC); 52 | void raise_informix_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *state, char *tag, char *message, char *file, int line TSRMLS_DC); 53 | void raise_dbh_error(pdo_dbh_t *dbh, char *tag, char *file, int line TSRMLS_DC); 54 | void raise_stmt_error(pdo_stmt_t *stmt, char *tag, char *file, int line TSRMLS_DC); 55 | void clear_stmt_error(pdo_stmt_t *stmt); 56 | int informix_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC); 57 | 58 | #define RAISE_DBH_ERROR(tag) raise_dbh_error(dbh, tag, __FILE__, __LINE__ TSRMLS_CC) 59 | #define RAISE_STMT_ERROR(tag) raise_stmt_error(stmt, tag, __FILE__, __LINE__ TSRMLS_CC) 60 | #define RAISE_INFORMIX_STMT_ERROR(state, tag, msg) raise_informix_error(stmt->dbh, stmt, state, tag, msg, __FILE__, __LINE__ TSRMLS_CC) 61 | #define RAISE_INFORMIX_DBH_ERROR(state, tag, msg) raise_informix_error(dbh, NULL, state, tag, msg, __FILE__, __LINE__ TSRMLS_CC) 62 | 63 | /* check for an SQL error in the context of an 64 | PDO method execution. */ 65 | #define check_dbh_error(rc, tag) \ 66 | { \ 67 | if ( rc == SQL_ERROR ) \ 68 | { \ 69 | RAISE_DBH_ERROR(tag); \ 70 | return FALSE; \ 71 | } \ 72 | } \ 73 | 74 | /* check for an SQL error in the context of an 75 | PDOStatement method execution. */ 76 | #define check_stmt_error(rc, tag) \ 77 | { \ 78 | if ( rc == SQL_ERROR ) \ 79 | { \ 80 | RAISE_STMT_ERROR(tag); \ 81 | return FALSE; \ 82 | } \ 83 | } \ 84 | 85 | /* check an allocation in the context of a PDO object. */ 86 | #define check_allocation(ptr, tag, msg) \ 87 | { \ 88 | if ((ptr) == NULL) \ 89 | { \ 90 | RAISE_INFORMIX_DBH_ERROR("HY001", tag, msg); \ 91 | return FALSE; \ 92 | } \ 93 | } \ 94 | 95 | /* check a storage allocation for a PDOStatement 96 | object context. */ 97 | #define check_stmt_allocation(ptr, tag, msg) \ 98 | { \ 99 | if ((ptr) == NULL) \ 100 | { \ 101 | RAISE_INFORMIX_STMT_ERROR("HY001", tag, msg); \ 102 | return FALSE; \ 103 | } \ 104 | } \ 105 | 106 | 107 | typedef struct _conn_error_data { 108 | SQLINTEGER sqlcode; /* native sql error code */ 109 | char *filename; /* name of the file raising the error */ 110 | int lineno; /* line number location of the error */ 111 | char *failure_name; /* the failure tag. */ 112 | SQLCHAR sql_state[8]; /* SQLSTATE code */ 113 | char err_msg[SQL_MAX_MESSAGE_LENGTH + 1]; /* error message associated with failure */ 114 | } conn_error_data; 115 | 116 | typedef struct _conn_handle_struct { 117 | SQLHANDLE henv; /* handle to the interface environment */ 118 | SQLHANDLE hdbc; /* the connection handle */ 119 | conn_error_data error_data; /* error handling information */ 120 | int last_insert_id; /* the last serial id inserted */ 121 | } conn_handle; 122 | 123 | /* values used for binding fetched data */ 124 | typedef union { 125 | long l_val; /* long values -- used for all int values, including bools */ 126 | char *str_val; /* used for string bindings */ 127 | } column_data_value; 128 | 129 | /* local descriptor for column data. These mirror the 130 | descriptors given back to the PDO driver. */ 131 | typedef struct { 132 | char *name; /* the column name */ 133 | SQLSMALLINT namelen; /* length of the column name */ 134 | SQLSMALLINT data_type; /* the database column type */ 135 | enum pdo_param_type returned_type; /* our returned parameter type */ 136 | SQLULEN data_size; /* maximum size of the data */ 137 | SQLSMALLINT nullable; /* the nullable flag */ 138 | SQLSMALLINT scale; /* the scale value */ 139 | SQLULEN out_length; /* the transfered data length. Filled in by a fetch */ 140 | column_data_value data; /* the transferred data */ 141 | } column_data; 142 | 143 | /* size of the buffer used to read LOB streams */ 144 | #define LOB_BUFFER_SIZE 8192 145 | 146 | typedef struct _stmt_handle_struct { 147 | SQLHANDLE hstmt; /* the statement handle associated with the stmt */ 148 | int executing; /* an executing state flag for error cleanup */ 149 | char *converted_statement; /* temporary version of the statement with parameter replacement */ 150 | char *lob_buffer; /* buffer used for reading in LOB parameters */ 151 | column_data *columns; /* the column descriptors */ 152 | enum pdo_cursor_type cursor_type; /* the type of cursor we support. */ 153 | SQLSMALLINT server_ver; /* the server version */ 154 | } stmt_handle; 155 | 156 | /* Defines the driver_data structure for caching param data */ 157 | typedef struct _param_node { 158 | SQLSMALLINT data_type; /* The database data type */ 159 | SQLULEN param_size; /* param size */ 160 | SQLSMALLINT nullable; /* is Nullable */ 161 | SQLSMALLINT scale; /* Decimal scale */ 162 | SQLSMALLINT ctype; /* the optimal C type for transfer */ 163 | SQLULEN transfer_length; /* the transfer length of the parameter */ 164 | } param_node; 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /tests/fvt_024.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Change fetch modes. 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 16 | $this->prepareDB(); 17 | $sql = "SELECT * FROM animals"; 18 | $stmt = $this->db->query($sql); 19 | $result = $stmt->setFetchMode(PDO::FETCH_NUM); 20 | $row = $stmt->fetch(); 21 | print "As row column numbers: " . $row[0] . " " . $row[1] . " " . $row[2] . "\n"; 22 | 23 | $stmt = $this->db->query($sql); 24 | $result = $stmt->setFetchMode(PDO::FETCH_ASSOC); 25 | $row = $stmt->fetch(); 26 | print "As row column names: " . $row["ID"] . "\n" ; 27 | 28 | $stmt = $this->db->query($sql); 29 | $result = $stmt->setFetchMode(PDO::FETCH_BOTH); 30 | $row = $stmt->fetch(); 31 | print "As row column numbers: " . $row[0] . " " . $row[1] . " " . $row[2] . "\n"; 32 | 33 | $stmt = $this->db->query($sql); 34 | $result = $stmt->setFetchMode(PDO::FETCH_BOTH); 35 | $row = $stmt->fetch(); 36 | print "As row column names: " . $row["ID"] . "\n" ; 37 | 38 | $stmt = $this->db->query($sql); 39 | $result = $stmt->setFetchMode(PDO::FETCH_ASSOC); 40 | $row = $stmt->fetch(); 41 | print "Rows not available: " . $row[1] . "\n" ; 42 | 43 | $stmt = $this->db->query($sql); 44 | $result = $stmt->setFetchMode(PDO::FETCH_COLUMN, 0); 45 | $row = $stmt->fetch(); 46 | print "As row column number: " . $row[0] . "\n" ; 47 | 48 | $stmt = $this->db->query($sql); 49 | $result = $stmt->setFetchMode(PDO::FETCH_COLUMN, 0); 50 | $row = $stmt->fetch(); 51 | print "Rows not available: " . $row[1] . "\n" ; 52 | 53 | $sth = $this->db->prepare('SELECT id, breed FROM animals' ); 54 | $sth->bindColumn(1, $id); 55 | $sth->bindColumn(2, $breed); 56 | $sth->execute(); 57 | 58 | $result = $sth->setFetchMode(PDO::FETCH_BOUND); 59 | while( $row = $sth->fetch() ) { 60 | print "The id is: " . $id . " Breed is: " . $breed . "\n"; 61 | print "Result in row : " . $row . "\n" ; 62 | } 63 | 64 | $sth = $this->db->prepare('SELECT id, breed FROM animals WHERE id > 2' ); 65 | $sth->setFetchMode(PDO::FETCH_INTO, new animalObj ); 66 | $sth->execute(); 67 | foreach($sth as $obj) { 68 | var_dump($obj); 69 | } 70 | 71 | $stmt = $this->db->prepare('SELECT id, breed FROM animals' ); 72 | $stmt->setFetchMode(PDO::FETCH_CLASS, 'animalObj', array(0)); 73 | $stmt->execute(); 74 | foreach($stmt as $obj) { 75 | var_dump($obj); 76 | } 77 | 78 | $stmt = $this->db->prepare('SELECT id, breed FROM animals' ); 79 | $stmt->setFetchMode(PDO::FETCH_OBJ); 80 | $data = $stmt->execute(); 81 | foreach($stmt as $obj) { 82 | var_dump($obj); 83 | } 84 | 85 | $stmt = $this->db->prepare('SELECT id, breed FROM animals' ); 86 | $stmt->setFetchMode(PDO::FETCH_LAZY); 87 | $data = $stmt->execute(); 88 | try { 89 | foreach($stmt as $obj) { 90 | var_dump($obj); 91 | } 92 | } catch( Exception $e) { 93 | print "Error: " . $stmt->errorCode() . "\n"; 94 | } 95 | } 96 | } 97 | 98 | $testcase = new Test(); 99 | $testcase->runTest(); 100 | ?> 101 | --EXPECTF-- 102 | As row column numbers: 0 cat Pook 103 | As row column names: 0 104 | As row column numbers: 0 cat Pook 105 | As row column names: 0 106 | 107 | Notice: Undefined offset: 1 in %s 108 | Rows not available: 109 | As row column number: 0 110 | 111 | Notice: Uninitialized string offset: 1 in %s 112 | Rows not available: 113 | The id is: 0 Breed is: cat 114 | Result in row : 1 115 | The id is: 1 Breed is: dog 116 | Result in row : 1 117 | The id is: 2 Breed is: horse 118 | Result in row : 1 119 | The id is: 3 Breed is: gold fish 120 | Result in row : 1 121 | The id is: 4 Breed is: budgerigar 122 | Result in row : 1 123 | The id is: 5 Breed is: goat 124 | Result in row : 1 125 | The id is: 6 Breed is: llama 126 | Result in row : 1 127 | object(animalObj)#4 (4) { 128 | ["id"]=> 129 | NULL 130 | ["breed"]=> 131 | NULL 132 | ["ID"]=> 133 | string(1) "3" 134 | ["BREED"]=> 135 | string(9) "gold fish" 136 | } 137 | object(animalObj)#4 (4) { 138 | ["id"]=> 139 | NULL 140 | ["breed"]=> 141 | NULL 142 | ["ID"]=> 143 | string(1) "4" 144 | ["BREED"]=> 145 | string(10) "budgerigar" 146 | } 147 | object(animalObj)#4 (4) { 148 | ["id"]=> 149 | NULL 150 | ["breed"]=> 151 | NULL 152 | ["ID"]=> 153 | string(1) "5" 154 | ["BREED"]=> 155 | string(4) "goat" 156 | } 157 | object(animalObj)#4 (4) { 158 | ["id"]=> 159 | NULL 160 | ["breed"]=> 161 | NULL 162 | ["ID"]=> 163 | string(1) "6" 164 | ["BREED"]=> 165 | string(5) "llama" 166 | } 167 | object(animalObj)#3 (4) { 168 | ["id"]=> 169 | NULL 170 | ["breed"]=> 171 | NULL 172 | ["ID"]=> 173 | string(1) "0" 174 | ["BREED"]=> 175 | string(3) "cat" 176 | } 177 | object(animalObj)#8 (4) { 178 | ["id"]=> 179 | NULL 180 | ["breed"]=> 181 | NULL 182 | ["ID"]=> 183 | string(1) "1" 184 | ["BREED"]=> 185 | string(3) "dog" 186 | } 187 | object(animalObj)#3 (4) { 188 | ["id"]=> 189 | NULL 190 | ["breed"]=> 191 | NULL 192 | ["ID"]=> 193 | string(1) "2" 194 | ["BREED"]=> 195 | string(5) "horse" 196 | } 197 | object(animalObj)#8 (4) { 198 | ["id"]=> 199 | NULL 200 | ["breed"]=> 201 | NULL 202 | ["ID"]=> 203 | string(1) "3" 204 | ["BREED"]=> 205 | string(9) "gold fish" 206 | } 207 | object(animalObj)#3 (4) { 208 | ["id"]=> 209 | NULL 210 | ["breed"]=> 211 | NULL 212 | ["ID"]=> 213 | string(1) "4" 214 | ["BREED"]=> 215 | string(10) "budgerigar" 216 | } 217 | object(animalObj)#8 (4) { 218 | ["id"]=> 219 | NULL 220 | ["breed"]=> 221 | NULL 222 | ["ID"]=> 223 | string(1) "5" 224 | ["BREED"]=> 225 | string(4) "goat" 226 | } 227 | object(animalObj)#3 (4) { 228 | ["id"]=> 229 | NULL 230 | ["breed"]=> 231 | NULL 232 | ["ID"]=> 233 | string(1) "6" 234 | ["BREED"]=> 235 | string(5) "llama" 236 | } 237 | object(stdClass)#6 (2) { 238 | ["ID"]=> 239 | string(1) "0" 240 | ["BREED"]=> 241 | string(3) "cat" 242 | } 243 | object(stdClass)#3 (2) { 244 | ["ID"]=> 245 | string(1) "1" 246 | ["BREED"]=> 247 | string(3) "dog" 248 | } 249 | object(stdClass)#6 (2) { 250 | ["ID"]=> 251 | string(1) "2" 252 | ["BREED"]=> 253 | string(5) "horse" 254 | } 255 | object(stdClass)#3 (2) { 256 | ["ID"]=> 257 | string(1) "3" 258 | ["BREED"]=> 259 | string(9) "gold fish" 260 | } 261 | object(stdClass)#6 (2) { 262 | ["ID"]=> 263 | string(1) "4" 264 | ["BREED"]=> 265 | string(10) "budgerigar" 266 | } 267 | object(stdClass)#3 (2) { 268 | ["ID"]=> 269 | string(1) "5" 270 | ["BREED"]=> 271 | string(4) "goat" 272 | } 273 | object(stdClass)#6 (2) { 274 | ["ID"]=> 275 | string(1) "6" 276 | ["BREED"]=> 277 | string(5) "llama" 278 | } 279 | object(PDORow)#7 (3) { 280 | ["queryString"]=> 281 | string(29) "SELECT id, breed FROM animals" 282 | ["ID"]=> 283 | string(1) "0" 284 | ["BREED"]=> 285 | string(3) "cat" 286 | } 287 | object(PDORow)#7 (3) { 288 | ["queryString"]=> 289 | string(29) "SELECT id, breed FROM animals" 290 | ["ID"]=> 291 | string(1) "1" 292 | ["BREED"]=> 293 | string(3) "dog" 294 | } 295 | object(PDORow)#7 (3) { 296 | ["queryString"]=> 297 | string(29) "SELECT id, breed FROM animals" 298 | ["ID"]=> 299 | string(1) "2" 300 | ["BREED"]=> 301 | string(5) "horse" 302 | } 303 | object(PDORow)#7 (3) { 304 | ["queryString"]=> 305 | string(29) "SELECT id, breed FROM animals" 306 | ["ID"]=> 307 | string(1) "3" 308 | ["BREED"]=> 309 | string(9) "gold fish" 310 | } 311 | object(PDORow)#7 (3) { 312 | ["queryString"]=> 313 | string(29) "SELECT id, breed FROM animals" 314 | ["ID"]=> 315 | string(1) "4" 316 | ["BREED"]=> 317 | string(10) "budgerigar" 318 | } 319 | object(PDORow)#7 (3) { 320 | ["queryString"]=> 321 | string(29) "SELECT id, breed FROM animals" 322 | ["ID"]=> 323 | string(1) "5" 324 | ["BREED"]=> 325 | string(4) "goat" 326 | } 327 | object(PDORow)#7 (3) { 328 | ["queryString"]=> 329 | string(29) "SELECT id, breed FROM animals" 330 | ["ID"]=> 331 | string(1) "6" 332 | ["BREED"]=> 333 | string(5) "llama" 334 | } 335 | -------------------------------------------------------------------------------- /tests/fvt_015.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | pdo_informix: Insert/select clob/blob columns with binding to local variable or stream 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | connect(); 13 | 14 | try { 15 | /* Drop the test table, in case it exists */ 16 | $drop = 'DROP TABLE animals'; 17 | $result = $this->db->exec( $drop ); 18 | } catch( Exception $e ){} 19 | 20 | /* Create the test table */ 21 | $server_info = $this->db->getAttribute(PDO::ATTR_SERVER_INFO); 22 | $create = 'CREATE TABLE animals (id INTEGER, my_clob text, my_blob byte)'; 23 | $res = $this->db->exec( $create ); 24 | 25 | $stmt = $this->db->prepare('insert into animals (id,my_clob,my_blob) values (:id,:my_clob,:my_blob)'); 26 | $clob = "test clob data\n"; 27 | $blob = "test blob data\n"; 28 | print "inserting from php variable\n"; 29 | $stmt->bindValue( ':id' , 0 ); 30 | $stmt->bindParam( ':my_clob' , $clob , PDO::PARAM_LOB , strlen($clob) ); 31 | $stmt->bindParam( ':my_blob' , $blob , PDO::PARAM_LOB , strlen($blob) ); 32 | $stmt->execute(); 33 | 34 | $stmt = $this->db->prepare( 'select id,my_clob,my_blob from animals' ); 35 | $res = $stmt->execute(); 36 | $res = $stmt->fetchAll(); 37 | var_dump( $res ); 38 | 39 | $res = $this->db->exec( "DELETE FROM animals" ); 40 | 41 | print "inserting from php file stream\n"; 42 | $fp1 = fopen( dirname(__FILE__) . "/clob.dat" , "rb" ); 43 | $fp2 = fopen( dirname(__FILE__) . "/spook.png" , "rb" ); 44 | $stmt = $this->db->prepare('insert into animals (id,my_clob,my_blob) values (:id,:my_clob,:my_blob)'); 45 | $stmt->bindValue( ':id' , 1 ); 46 | $stmt->bindParam( ':my_clob' , $fp1 , PDO::PARAM_LOB ); 47 | $stmt->bindParam( ':my_blob' , $fp2 , PDO::PARAM_LOB ); 48 | $stmt->execute(); 49 | 50 | $stmt = $this->db->prepare( 'select id,my_clob,my_blob from animals' ); 51 | $res = $stmt->execute(); 52 | $res = $stmt->fetchAll(); 53 | var_dump( $res ); 54 | 55 | $stmt = $this->db->prepare( 'select id,my_clob,my_blob from animals' ); 56 | $stmt->bindColumn( 1 , $id ); 57 | $stmt->bindColumn( 2 , $clob ); 58 | $stmt->bindColumn( 3 , $blob ); 59 | $res = $stmt->execute(); 60 | while ($stmt->fetch(PDO::FETCH_BOUND)) { 61 | var_dump( $id ); 62 | var_dump( $clob ); 63 | var_dump( $blob ); 64 | } 65 | 66 | 67 | print "done\n"; 68 | } 69 | } 70 | 71 | $testcase = new Test(); 72 | $testcase->runTest(); 73 | ?> 74 | --EXPECTF-- 75 | inserting from php variable 76 | array(1) { 77 | [0]=> 78 | array(6) { 79 | ["ID"]=> 80 | string(1) "0" 81 | [0]=> 82 | string(1) "0" 83 | ["MY_CLOB"]=> 84 | string(15) "test clob data 85 | " 86 | [1]=> 87 | string(15) "test clob data 88 | " 89 | ["MY_BLOB"]=> 90 | string(%d)%s 91 | [2]=> 92 | string(%d)%s 93 | } 94 | } 95 | inserting from php file stream 96 | array(1) { 97 | [0]=> 98 | array(6) { 99 | ["ID"]=> 100 | string(1) "1" 101 | [0]=> 102 | string(1) "1" 103 | ["MY_CLOB"]=> 104 | string(%d) "this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 105 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 106 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 107 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 108 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 109 | " 110 | [1]=> 111 | string(%d) "this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 112 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 113 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 114 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 115 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 116 | " 117 | ["MY_BLOB"]=> 118 | string(%d)%s 119 | [2]=> 120 | string(%d)%s 121 | } 122 | } 123 | string(1) "1" 124 | string(%d) "this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 125 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 126 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 127 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 128 | this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. this iss clob data. 129 | " 130 | string(%d)%s 131 | done 132 | -------------------------------------------------------------------------------- /informix_driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | (C) Copyright IBM Corporation 2006-2014. | 4 | +----------------------------------------------------------------------+ 5 | | | 6 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 7 | | may not use this file except in compliance with the License. You may | 8 | | obtain a copy of the License at | 9 | | http://www.apache.org/licenses/LICENSE-2.0 | 10 | | | 11 | | Unless required by applicable law or agreed to in writing, software | 12 | | distributed under the License is distributed on an "AS IS" BASIS, | 13 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 14 | | implied. See the License for the specific language governing | 15 | | permissions and limitations under the License. | 16 | +----------------------------------------------------------------------+ 17 | | Authors: Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier, | 18 | | Ambrish Bhargava, Rahul Priyadarshi | 19 | +----------------------------------------------------------------------+ 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "php_ini.h" 28 | #include "ext/standard/info.h" 29 | #include "pdo/php_pdo.h" 30 | #include "pdo/php_pdo_driver.h" 31 | #include "php_pdo_informix.h" 32 | #include "php_pdo_informix_int.h" 33 | #include "zend_exceptions.h" 34 | #include 35 | 36 | extern struct pdo_stmt_methods informix_stmt_methods; 37 | extern int informix_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC); 38 | 39 | 40 | /* allocate and initialize the driver_data portion of a PDOStatement object. */ 41 | static int dbh_new_stmt_data(pdo_dbh_t* dbh, pdo_stmt_t *stmt TSRMLS_DC) 42 | { 43 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 44 | 45 | stmt_handle *stmt_res = (stmt_handle *) emalloc(sizeof(stmt_handle)); 46 | check_allocation(stmt_res, "dbh_new_stmt_data", "Unable to allocate stmt driver data"); 47 | memset(stmt_res, '\0', sizeof(stmt_handle)); 48 | 49 | stmt_res->columns = NULL; 50 | 51 | /* attach to the statement */ 52 | stmt->driver_data = stmt_res; 53 | stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; 54 | return TRUE; 55 | } 56 | 57 | /* prepare a statement for execution. */ 58 | static int dbh_prepare_stmt(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *stmt_string, long stmt_len, zval *driver_options TSRMLS_DC) 59 | { 60 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 61 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 62 | int rc; 63 | SQLSMALLINT param_count; 64 | UCHAR server_info[30]; 65 | SQLSMALLINT server_len = 0; 66 | 67 | /* in case we need to convert the statement for positional syntax */ 68 | int converted_len = 0; 69 | stmt_res->converted_statement = NULL; 70 | 71 | /* clear the current error information to get ready for new execute */ 72 | clear_stmt_error(stmt); 73 | 74 | /* 75 | * the statement passed in to us at this point is the raw statement the 76 | * programmer specified. If the statement is using named parameters 77 | * (e.g., ":salary", we can't process this directly. Fortunately, PDO 78 | * has a utility function that will munge the SQL statement into the 79 | * form we require and do mappings from named to positional parameters. 80 | */ 81 | 82 | /* this is necessary...it tells the parser what we require */ 83 | stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL; 84 | rc = pdo_parse_params(stmt, (char *) stmt_string, stmt_len, 85 | &stmt_res->converted_statement, 86 | &converted_len TSRMLS_CC); 87 | 88 | /* 89 | * If the query needed reformatting, a new statement string has been 90 | * passed back to us. We're responsible for freeing this when we're done. 91 | */ 92 | if (rc == 1) { 93 | stmt_string = stmt_res->converted_statement; 94 | stmt_len = converted_len; 95 | } 96 | /* 97 | * A negative return indicates there was an error. The error_code 98 | * information in the statement contains the reason. 99 | */ 100 | else if (rc == -1) { 101 | /* copy the error information */ 102 | RAISE_INFORMIX_STMT_ERROR(stmt->error_code, "pdo_parse_params", 103 | "Invalid SQL statement"); 104 | /* this failed...error cleanup will happen later. */ 105 | return FALSE; 106 | } 107 | 108 | /* alloc handle and return only if it errors */ 109 | rc = SQLAllocHandle(SQL_HANDLE_STMT, conn_res->hdbc, &(stmt_res->hstmt)); 110 | check_stmt_error(rc, "SQLAllocHandle"); 111 | 112 | /* now see if the cursor type has been explicitly specified. */ 113 | stmt_res->cursor_type = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, 114 | PDO_CURSOR_FWDONLY TSRMLS_CC); 115 | 116 | /* 117 | * The default is just sequential access. If something else has been 118 | * specified, we need to make this scrollable. 119 | */ 120 | if (stmt_res->cursor_type != PDO_CURSOR_FWDONLY) { 121 | /* set the statement attribute */ 122 | rc = SQLSetStmtAttr(stmt_res->hstmt, SQL_ATTR_CURSOR_TYPE, (void *) SQL_CURSOR_DYNAMIC, 0); 123 | check_stmt_error(rc, "SQLSetStmtAttr"); 124 | } 125 | 126 | 127 | /* Prepare the stmt. */ 128 | rc = SQLPrepare((SQLHSTMT) stmt_res->hstmt, (SQLCHAR *) stmt_string, stmt_len); 129 | 130 | /* Check for errors from that prepare */ 131 | check_stmt_error(rc, "SQLPrepare"); 132 | if (rc == SQL_ERROR) { 133 | stmt_cleanup(stmt TSRMLS_CC); 134 | return FALSE; 135 | } 136 | 137 | /* we can get rid of the stmt copy now */ 138 | if (stmt_res->converted_statement != NULL) { 139 | efree(stmt_res->converted_statement); 140 | stmt_res->converted_statement = NULL; 141 | } 142 | 143 | rc = SQLNumResultCols((SQLHSTMT) stmt_res->hstmt, (SQLSMALLINT *) & param_count); 144 | check_stmt_error(rc, "SQLNumResultCols"); 145 | 146 | /* we're responsible for setting the column_count for the PDO driver. */ 147 | stmt->column_count = param_count; 148 | 149 | /* Get the server information: 150 | * server_info is in this form: 151 | * 0r.01.0000 152 | * where r is the major version 153 | */ 154 | rc = SQLGetInfo(conn_res->hdbc, SQL_DBMS_VER, &server_info, 155 | sizeof(server_info), &server_len); 156 | /* making char numbers into integers eg. "10" --> 10 or "09" --> 9 */ 157 | stmt_res->server_ver = ((server_info[0] - '0')*100) + ((server_info[1] - '0')*10) + (server_info[3] - '0'); 158 | /* 159 | * Attach the methods...we are now live, so errors will no longer immediately 160 | * force cleanup of the stmt driver-specific storage. 161 | */ 162 | stmt->methods = &informix_stmt_methods; 163 | 164 | return TRUE; 165 | } 166 | 167 | /* debugging routine for printing out failure information. */ 168 | static void current_error_state(pdo_dbh_t *dbh) 169 | { 170 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 171 | printf("Handling error %s (%s[%d] at %s:%d)\n", 172 | conn_res->error_data.err_msg, /* an associated message */ 173 | conn_res->error_data.failure_name, /* the routine name */ 174 | conn_res->error_data.sqlcode, /* native error code of the failure */ 175 | conn_res->error_data.filename, /* source file of the reported error */ 176 | conn_res->error_data.lineno); /* location of the reported error */ 177 | } 178 | 179 | /* 180 | * NB. The handle closer is used for PDO dtor purposes, but we also use this 181 | * for error cleanup if we need to throw an exception while creating the 182 | * connection. In that case, the closer is not automatically called by PDO, 183 | * so we need to force cleanup. 184 | */ 185 | static int informix_handle_closer( pdo_dbh_t * dbh TSRMLS_DC) 186 | { 187 | conn_handle *conn_res; 188 | 189 | conn_res = (conn_handle *) dbh->driver_data; 190 | 191 | /* 192 | * An error can occur at many stages of setup, so we need to check the 193 | * validity of each bit as we unwind. 194 | */ 195 | if (conn_res != NULL) { 196 | /* did we get at least as far as creating the environment? */ 197 | if (conn_res->henv != SQL_NULL_HANDLE) { 198 | /* 199 | * If we have a handle for the connection, we have 200 | * more stuff to clean up 201 | */ 202 | if (conn_res->hdbc != SQL_NULL_HANDLE) { 203 | /* 204 | * Roll back the transaction if this hasn't been committed yet. 205 | * There's no point in checking for errors here... 206 | * PDO won't process any of the failures even if they happen. 207 | */ 208 | if (dbh->auto_commit == 0) { 209 | SQLEndTran(SQL_HANDLE_DBC, (SQLHDBC) conn_res->hdbc, 210 | SQL_ROLLBACK); 211 | } 212 | SQLDisconnect((SQLHDBC) conn_res->hdbc); 213 | SQLFreeHandle(SQL_HANDLE_DBC, conn_res->hdbc); 214 | } 215 | /* and finally the handle */ 216 | SQLFreeHandle(SQL_HANDLE_ENV, conn_res->henv); 217 | } 218 | /* now free the driver data */ 219 | pefree(conn_res, dbh->is_persistent); 220 | dbh->driver_data = NULL; 221 | } 222 | return TRUE; 223 | } 224 | 225 | /* prepare a statement for execution. */ 226 | static int informix_handle_preparer( 227 | pdo_dbh_t *dbh, 228 | const char *sql, 229 | long sql_len, 230 | pdo_stmt_t *stmt, 231 | zval *driver_options 232 | TSRMLS_DC) 233 | { 234 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 235 | 236 | /* allocate new driver_data structure */ 237 | if (dbh_new_stmt_data(dbh, stmt TSRMLS_CC) == TRUE) { 238 | /* Allocates the stmt handle */ 239 | /* Prepares the statement */ 240 | /* returns the stat_handle back to the calling function */ 241 | return dbh_prepare_stmt(dbh, stmt, sql, sql_len, driver_options TSRMLS_CC); 242 | } 243 | return FALSE; 244 | } 245 | 246 | /* directly execute an SQL statement. */ 247 | static long informix_handle_doer( 248 | pdo_dbh_t *dbh, 249 | const char *sql, 250 | long sql_len 251 | TSRMLS_DC) 252 | { 253 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 254 | SQLHANDLE hstmt; 255 | SQLLEN rowCount; 256 | /* get a statement handle */ 257 | int rc = SQLAllocHandle(SQL_HANDLE_STMT, conn_res->hdbc, &hstmt); 258 | check_dbh_error(rc, "SQLAllocHandle"); 259 | 260 | rc = SQLExecDirect(hstmt, (SQLCHAR *) sql, sql_len); 261 | if (rc == SQL_ERROR) { 262 | /* 263 | * NB...we raise the error before freeing the handle so that 264 | * we catch the proper error record. 265 | */ 266 | raise_sql_error(dbh, NULL, hstmt, SQL_HANDLE_STMT, 267 | "SQLExecDirect", __FILE__, __LINE__ TSRMLS_CC); 268 | SQLFreeHandle(SQL_HANDLE_STMT, hstmt); 269 | 270 | /* 271 | * Things are a bit overloaded here...we're supposed to return a count 272 | * of the affected rows, but -1 indicates an error occurred. 273 | */ 274 | return -1; 275 | } 276 | 277 | /* 278 | * Check if SQL_NO_DATA_FOUND was returned: 279 | * SQL_NO_DATA_FOUND is returned if the SQL statement is a Searched UPDATE 280 | * or Searched DELETE and no rows satisfy the search condition. 281 | */ 282 | if (rc == SQL_NO_DATA) { 283 | rowCount = 0; 284 | } else { 285 | /* we need to update the number of affected rows. */ 286 | rc = SQLRowCount(hstmt, &rowCount); 287 | if (rc == SQL_ERROR) { 288 | /* 289 | * NB...we raise the error before freeing the handle so that 290 | * we catch the proper error record. 291 | */ 292 | raise_sql_error(dbh, NULL, hstmt, SQL_HANDLE_STMT, 293 | "SQLRowCount", __FILE__, __LINE__ TSRMLS_CC); 294 | SQLFreeHandle(SQL_HANDLE_STMT, hstmt); 295 | return -1; 296 | } 297 | /* 298 | * -1 will be retuned if the following: 299 | * If the last executed statement referenced by the input statement handle 300 | * was not an UPDATE, INSERT, DELETE, or MERGE statement, or if it did not 301 | * execute successfully, then the function sets the contents of RowCountPtr to -1. 302 | */ 303 | if (rowCount == -1) { 304 | rowCount = 0; 305 | } 306 | } 307 | 308 | /* Set the last serial id inserted */ 309 | rc = record_last_insert_id(dbh, hstmt TSRMLS_CC); 310 | if( rc == SQL_ERROR ) { 311 | return -1; 312 | } 313 | /* this is a one-shot deal, so make sure we free the statement handle */ 314 | SQLFreeHandle(SQL_HANDLE_STMT, hstmt); 315 | return rowCount; 316 | } 317 | 318 | /* start a new transaction */ 319 | static int informix_handle_begin( pdo_dbh_t *dbh TSRMLS_DC) 320 | { 321 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 322 | int rc = SQLSetConnectAttr(conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 323 | (SQLPOINTER) SQL_AUTOCOMMIT_OFF, SQL_NTS); 324 | check_dbh_error(rc, "SQLSetConnectAttr"); 325 | return TRUE; 326 | } 327 | 328 | static int informix_handle_commit( 329 | pdo_dbh_t *dbh 330 | TSRMLS_DC) 331 | { 332 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 333 | 334 | int rc = SQLEndTran(SQL_HANDLE_DBC, conn_res->hdbc, SQL_COMMIT); 335 | check_dbh_error(rc, "SQLEndTran"); 336 | if (dbh->auto_commit != 0) { 337 | rc = SQLSetConnectAttr(conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 338 | (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_NTS); 339 | check_dbh_error(rc, "SQLSetConnectAttr"); 340 | } 341 | return TRUE; 342 | } 343 | 344 | static int informix_handle_rollback( 345 | pdo_dbh_t *dbh 346 | TSRMLS_DC) 347 | { 348 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 349 | 350 | int rc = SQLEndTran(SQL_HANDLE_DBC, conn_res->hdbc, SQL_ROLLBACK); 351 | check_dbh_error(rc, "SQLEndTran"); 352 | if (dbh->auto_commit != 0) { 353 | rc = SQLSetConnectAttr(conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 354 | (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_NTS); 355 | check_dbh_error(rc, "SQLSetConnectAttr"); 356 | } 357 | return TRUE; 358 | } 359 | 360 | /* Set the driver attributes. We allow the setting of autocommit */ 361 | static int informix_handle_set_attribute( 362 | pdo_dbh_t *dbh, 363 | long attr, 364 | zval *return_value 365 | TSRMLS_DC) 366 | { 367 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 368 | int rc = 0; 369 | 370 | switch (attr) { 371 | case PDO_ATTR_AUTOCOMMIT: 372 | if (dbh->auto_commit != Z_LVAL_P(return_value)) { 373 | dbh->auto_commit = Z_LVAL_P(return_value); 374 | if (dbh->auto_commit == TRUE) { 375 | rc = SQLSetConnectAttr((SQLHDBC) conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 376 | (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_NTS); 377 | check_dbh_error(rc, "SQLSetConnectAttr"); 378 | } else { 379 | rc = SQLSetConnectAttr((SQLHDBC) conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 380 | (SQLPOINTER) SQL_AUTOCOMMIT_OFF, SQL_NTS); 381 | check_dbh_error(rc, "SQLSetConnectAttr"); 382 | } 383 | } 384 | return TRUE; 385 | break; 386 | default: 387 | return FALSE; 388 | } 389 | } 390 | 391 | /* fetch the last inserted serial id */ 392 | static char *informix_handle_lastInsertID(pdo_dbh_t * dbh, const char *name, unsigned int *len TSRMLS_DC) 393 | { 394 | char *id = emalloc(20); 395 | int rc = 0; 396 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 397 | 398 | sprintf(id, "%d", conn_res->last_insert_id); 399 | *len = strlen(id); 400 | 401 | return id; 402 | 403 | } 404 | 405 | /* fetch the supplemental error material */ 406 | static int informix_handle_fetch_error( 407 | pdo_dbh_t *dbh, 408 | pdo_stmt_t *stmt, 409 | zval *info 410 | TSRMLS_DC) 411 | { 412 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 413 | char suppliment[512]; 414 | 415 | if(conn_res->error_data.failure_name == NULL && conn_res->error_data.filename == NULL) { 416 | conn_res->error_data.filename="(null)"; 417 | conn_res->error_data.failure_name="(null)"; 418 | } 419 | sprintf(suppliment, "%s (%s[%d] at %s:%d)", 420 | conn_res->error_data.err_msg, /* an associated message */ 421 | conn_res->error_data.failure_name, /* the routine name */ 422 | conn_res->error_data.sqlcode, /* native error code of the failure */ 423 | conn_res->error_data.filename, /* source file of the reported error */ 424 | conn_res->error_data.lineno); /* location of the reported error */ 425 | /* 426 | * Now add the error information. These need to be added 427 | * in a specific order 428 | */ 429 | add_next_index_long(info, conn_res->error_data.sqlcode); 430 | add_next_index_string(info, suppliment, 1); 431 | 432 | return TRUE; 433 | } 434 | 435 | /* quotes an SQL statement */ 436 | static int informix_handle_quoter( 437 | pdo_dbh_t *dbh, 438 | const char *unq, 439 | int unq_len, 440 | char **q, 441 | int *q_len, 442 | enum pdo_param_type paramtype 443 | TSRMLS_DC) 444 | { 445 | char *sql; 446 | int new_length, i, j; 447 | 448 | if(!unq) { 449 | return FALSE; 450 | } 451 | 452 | /* allocate twice the source length first (worst case) */ 453 | sql = (char*)emalloc(((unq_len*2)+3)*sizeof(char)); 454 | 455 | /* set the first quote */ 456 | sql[0] = '\''; 457 | 458 | j = 1; 459 | for (i = 0; i < unq_len; i++) { 460 | switch (unq[i]) { 461 | case '\n': 462 | sql[j++] = '\\'; 463 | sql[j++] = 'n'; 464 | break; 465 | case '\r': 466 | sql[j++] = '\\'; 467 | sql[j++] = 'r'; 468 | break; 469 | case '\x1a': 470 | sql[j++] = '\\'; 471 | sql[j++] = 'Z'; 472 | break; 473 | case '\0': 474 | sql[j++] = '\\'; 475 | sql[j++] = '0'; 476 | break; 477 | case '\'': 478 | sql[j++] = '\\'; 479 | sql[j++] = '\''; 480 | break; 481 | case '\"': 482 | sql[j++] = '\\'; 483 | sql[j++] = '\"'; 484 | break; 485 | case '\\': 486 | sql[j++] = '\\'; 487 | sql[j++] = '\\'; 488 | break; 489 | default: 490 | sql[j++] = unq[i]; 491 | break; 492 | } 493 | } 494 | 495 | /* set the last quote and null terminating character */ 496 | sql[j++] = '\''; 497 | sql[j++] = '\0'; 498 | 499 | /* copy over final string and free the memory used */ 500 | *q = (char*)emalloc(((unq_len*2)+3)*sizeof(char)); 501 | strcpy(*q, sql); 502 | *q_len = strlen(sql); 503 | efree(sql); 504 | 505 | return TRUE; 506 | } 507 | 508 | 509 | /* Get the driver attributes. We return the autocommit and version information. */ 510 | static int informix_handle_get_attribute( 511 | pdo_dbh_t *dbh, 512 | long attr, 513 | zval *return_value 514 | TSRMLS_DC) 515 | { 516 | char value[MAX_DBMS_IDENTIFIER_NAME]; 517 | int rc; 518 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 519 | SQLINTEGER tc_flag; 520 | 521 | 522 | 523 | switch (attr) { 524 | case PDO_ATTR_CLIENT_VERSION: 525 | ZVAL_STRING(return_value, PDO_INFORMIX_VERSION, 1); 526 | return TRUE; 527 | 528 | case PDO_ATTR_AUTOCOMMIT: 529 | ZVAL_BOOL(return_value, dbh->auto_commit); 530 | return TRUE; 531 | 532 | case PDO_ATTR_SERVER_INFO: 533 | rc = SQLGetInfo(conn_res->hdbc, SQL_DBMS_NAME, 534 | (SQLPOINTER)value, MAX_DBMS_IDENTIFIER_NAME, NULL); 535 | check_dbh_error(rc, "SQLGetInfo"); 536 | ZVAL_STRING(return_value, value, 1); 537 | return TRUE; 538 | 539 | 540 | } 541 | return FALSE; 542 | } 543 | 544 | static int informix_handle_check_liveness( 545 | pdo_dbh_t *dbh 546 | TSRMLS_DC) 547 | { 548 | int rc = SQL_ERROR; 549 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 550 | SQLHANDLE hstmt; 551 | check_allocation(hstmt, "informix_handle_check_liveness", "Unable to allocate statement handle"); 552 | 553 | rc = SQLAllocHandle(SQL_HANDLE_STMT, conn_res->hdbc, &hstmt); 554 | if(rc != SQL_SUCCESS) { 555 | efree(hstmt); 556 | return FAILURE; 557 | } 558 | 559 | rc = SQLPrepare(hstmt, "SELECT today FROM systables WHERE tabid = 1", SQL_NTS); 560 | SQLFreeHandle(SQL_HANDLE_STMT, hstmt); 561 | if(rc != SQL_SUCCESS) { 562 | return FAILURE; 563 | } 564 | /* return the state from the query */ 565 | return SUCCESS; 566 | } 567 | static struct pdo_dbh_methods informix_dbh_methods = { 568 | informix_handle_closer, 569 | informix_handle_preparer, 570 | informix_handle_doer, 571 | informix_handle_quoter, 572 | informix_handle_begin, 573 | informix_handle_commit, 574 | informix_handle_rollback, 575 | informix_handle_set_attribute, 576 | informix_handle_lastInsertID, 577 | informix_handle_fetch_error, 578 | informix_handle_get_attribute, 579 | informix_handle_check_liveness, /* check_liveness */ 580 | NULL /* get_driver_methods */ 581 | }; 582 | 583 | /* handle the business of creating a connection. */ 584 | static int dbh_connect(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) 585 | { 586 | int rc = 0; 587 | int dsn_length = 0; 588 | char *new_dsn = NULL; 589 | SQLSMALLINT d_length = 0, u_length = 0, p_length = 0; 590 | /* 591 | * Allocate our driver data control block. If this is a persistent 592 | * connection, we need to allocate this from persistent storage. 593 | */ 594 | conn_handle *conn_res = (conn_handle *) pemalloc(sizeof(conn_handle), dbh->is_persistent); 595 | check_allocation(conn_res, "dbh_connect", "Unable to allocate driver data"); 596 | 597 | /* clear, and hook up to the PDO data structure. */ 598 | memset((void *) conn_res, '\0', sizeof(conn_handle)); 599 | dbh->driver_data = conn_res; 600 | 601 | /* we need an environment to use for a base */ 602 | rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &conn_res->henv); 603 | check_dbh_error(rc, "SQLAllocHandle"); 604 | /* and we're using the OBDC version 3 style interface */ 605 | rc = SQLSetEnvAttr((SQLHENV)conn_res->henv, SQL_ATTR_ODBC_VERSION, 606 | (void *) SQL_OV_ODBC3, 0); 607 | check_dbh_error(rc, "SQLSetEnvAttr"); 608 | 609 | /* now an actual connection handle */ 610 | rc = SQLAllocHandle(SQL_HANDLE_DBC, conn_res->henv, &(conn_res->hdbc)); 611 | check_dbh_error(rc, "SQLAllocHandle"); 612 | 613 | 614 | /* 615 | * NB: We don't have any specific driver options we support at this time, so 616 | * we don't need to do any option parsing. If the string contains a =, then 617 | * we need to use SQLDriverConnect to make the connection. This may require 618 | * reform var_dump($rows);atting the DSN string to include a userid and 619 | * password. 620 | */ 621 | if (strchr(dbh->data_source, '=') != NULL) { 622 | /* first check to see if we have a user name */ 623 | if (dbh->username != NULL && dbh->password != NULL) { 624 | /* 625 | * Ok, one was given...however, the DSN may already contain UID 626 | * information, so check first. 627 | */ 628 | if (strstr(dbh->data_source, ";uid=") == NULL 629 | && strstr(dbh->data_source, ";UID=") == NULL) { 630 | /* Make sure each of the connection parameters is not NULL */ 631 | d_length = strlen(dbh->data_source); 632 | u_length = strlen(dbh->username); 633 | p_length = strlen(dbh->password); 634 | dsn_length = d_length + u_length + p_length + sizeof(";UID=;PWD=;") + 1; 635 | new_dsn = pemalloc(dsn_length, dbh->is_persistent); 636 | check_allocation(new_dsn, "dbh_connect", "unable to allocate DSN string"); 637 | sprintf(new_dsn, "%s;UID=%s;PWD=%s;", dbh->data_source, 638 | dbh->username, dbh->password); 639 | if (dbh->data_source) { 640 | pefree((void *) dbh->data_source, dbh->is_persistent); 641 | } 642 | /* now replace the DSN with a properly formatted one. */ 643 | dbh->data_source = new_dsn; 644 | } 645 | 646 | } 647 | 648 | /* and finally try to connect */ 649 | rc = SQLDriverConnect((SQLHDBC) conn_res->hdbc, (SQLHWND) NULL, 650 | (SQLCHAR *) dbh->data_source, SQL_NTS, NULL, 651 | 0, NULL, SQL_DRIVER_NOPROMPT); 652 | check_dbh_error(rc, "SQLDriverConnect"); 653 | } else 654 | { 655 | /* Make sure each of the connection parameters is not NULL */ 656 | if (dbh->data_source) { 657 | d_length = strlen(dbh->data_source); 658 | } 659 | if (dbh->username) { 660 | u_length = strlen(dbh->username); 661 | } 662 | if (dbh->password) { 663 | p_length = strlen(dbh->password); 664 | } 665 | /* 666 | * No connection options specified, we can just connect with the name, 667 | * userid, and password as given. 668 | */ 669 | rc = SQLConnect((SQLHDBC) conn_res->hdbc, (SQLCHAR *) dbh->data_source, 670 | (SQLSMALLINT) d_length, 671 | (SQLCHAR *) dbh->username, 672 | (SQLSMALLINT) u_length, 673 | (SQLCHAR *)dbh->password, 674 | (SQLSMALLINT) p_length); 675 | check_dbh_error(rc, "SQLConnect"); 676 | } 677 | 678 | /* 679 | * Set NeedODBCTypesOnly=1 because we dont support 680 | * Smart Large Objects in PDO yet 681 | */ 682 | rc = SQLSetConnectAttr((SQLHDBC) conn_res->hdbc, SQL_INFX_ATTR_LO_AUTOMATIC, 683 | (SQLPOINTER) SQL_TRUE, SQL_NTS); 684 | check_dbh_error(rc, "SQLSetConnectAttr"); 685 | rc = SQLSetConnectAttr((SQLHDBC)conn_res->hdbc, SQL_INFX_ATTR_ODBC_TYPES_ONLY, 686 | (SQLPOINTER) SQL_TRUE, SQL_NTS); 687 | check_dbh_error(rc, "SQLSetConnectAttr"); 688 | 689 | /* if we're in auto commit mode, set the connection attribute. */ 690 | if (dbh->auto_commit != 0) { 691 | rc = SQLSetConnectAttr((SQLHDBC) conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 692 | (SQLPOINTER) SQL_AUTOCOMMIT_ON, SQL_NTS); 693 | check_dbh_error(rc, "SQLSetConnectAttr"); 694 | } else { 695 | rc = SQLSetConnectAttr((SQLHDBC) conn_res->hdbc, SQL_ATTR_AUTOCOMMIT, 696 | (SQLPOINTER) SQL_AUTOCOMMIT_OFF, SQL_NTS); 697 | check_dbh_error(rc, "SQLSetConnectAttr"); 698 | } 699 | 700 | /* set the desired case to be upper */ 701 | dbh->desired_case = PDO_CASE_UPPER; 702 | 703 | /* this is now live! all error handling goes through normal mechanisms. */ 704 | dbh->methods = &informix_dbh_methods; 705 | dbh->alloc_own_columns = 1; 706 | return TRUE; 707 | } 708 | 709 | 710 | /* 711 | * Main routine called to create a connection. The dbh structure is 712 | * allocated for us, and we attached a driver-specific control block 713 | * to the PDO allocated one, 714 | */ 715 | static int informix_handle_factory( 716 | pdo_dbh_t *dbh, 717 | zval *driver_options 718 | TSRMLS_DC) 719 | { 720 | /* go do the connection */ 721 | return dbh_connect(dbh, driver_options TSRMLS_CC); 722 | } 723 | 724 | pdo_driver_t pdo_informix_driver = 725 | { 726 | PDO_DRIVER_HEADER(informix), 727 | informix_handle_factory 728 | }; 729 | 730 | /* common error handling path for final disposition of an error.*/ 731 | static void process_pdo_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt TSRMLS_DC) 732 | { 733 | /* current_error_state(dbh);*/ 734 | 735 | conn_handle *conn_res = (conn_handle *)dbh->driver_data; 736 | strcpy(dbh->error_code, conn_res->error_data.sql_state); 737 | if (stmt != NULL) { 738 | /* what this a error in the stmt constructor? */ 739 | if (stmt->methods == NULL) { 740 | /* make sure we do any required cleanup. */ 741 | informix_stmt_dtor(stmt TSRMLS_CC); 742 | } 743 | strcpy(stmt->error_code, conn_res->error_data.sql_state); 744 | } 745 | 746 | /* 747 | * if we got an error very early, we need to throw an exception rather than 748 | * use the PDO error reporting. 749 | */ 750 | 751 | if (dbh->methods == NULL) { 752 | zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC, 753 | "SQLSTATE=%s, %s: %d %s", 754 | conn_res->error_data.sql_state, 755 | conn_res->error_data.failure_name, 756 | conn_res->error_data.sqlcode, 757 | conn_res->error_data.err_msg); 758 | informix_handle_closer(dbh TSRMLS_CC); 759 | } 760 | } 761 | 762 | /* 763 | * Handle an error return from an SQL call. The error information from the 764 | * call is saved in our error record. 765 | */ 766 | void raise_sql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, SQLHANDLE handle, 767 | SQLSMALLINT hType, char *tag, char *file, int line TSRMLS_DC) 768 | { 769 | SQLSMALLINT length; 770 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 771 | 772 | conn_res->error_data.failure_name = tag; 773 | conn_res->error_data.filename = file; 774 | conn_res->error_data.lineno = line; 775 | 776 | SQLGetDiagRec(hType, handle, 1, (SQLCHAR *) & (conn_res->error_data.sql_state), 777 | &(conn_res->error_data.sqlcode), 778 | (SQLCHAR *) & (conn_res->error_data.err_msg), 779 | SQL_MAX_MESSAGE_LENGTH, &length); 780 | /* the error message is not returned null terminated. */ 781 | conn_res->error_data.err_msg[length] = '\0'; 782 | 783 | /* now go tell PDO about this problem */ 784 | process_pdo_error(dbh, stmt TSRMLS_CC); 785 | } 786 | 787 | /* 788 | * Raise a driver-detected error. This is a faked-SQL type error, using a 789 | * provided sqlstate and message info. 790 | */ 791 | void raise_informix_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *state, char *tag, 792 | char *message, char *file, int line TSRMLS_DC) 793 | { 794 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 795 | 796 | conn_res->error_data.failure_name = tag; 797 | conn_res->error_data.filename = file; 798 | conn_res->error_data.lineno = line; 799 | strcpy(conn_res->error_data.err_msg, message); 800 | 801 | strcpy(conn_res->error_data.sql_state, state); 802 | conn_res->error_data.sqlcode = 1; /* just give a non-zero code state. */ 803 | /* now go tell PDO about this problem */ 804 | process_pdo_error(dbh, stmt TSRMLS_CC); 805 | } 806 | 807 | /* 808 | * Raise an error in a connection context. This ensures we use the 809 | * connection handle for retrieving error information. 810 | */ 811 | void raise_dbh_error(pdo_dbh_t *dbh, char *tag, char *file, int line TSRMLS_DC) 812 | { 813 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 814 | raise_sql_error(dbh, NULL, conn_res->hdbc, SQL_HANDLE_DBC, tag, file, 815 | line TSRMLS_CC); 816 | } 817 | 818 | /* 819 | * Raise an error in a statement context. This ensures we use the correct 820 | * handle for retrieving the diag record, as well as forcing stmt-related 821 | * cleanup. 822 | */ 823 | void raise_stmt_error(pdo_stmt_t *stmt, char *tag, char *file, int line TSRMLS_DC) 824 | { 825 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 826 | 827 | /* if we're in the middle of execution when an error was detected, make sure we cancel */ 828 | if (stmt_res->executing) { 829 | /* raise the error */ 830 | raise_sql_error(stmt->dbh, stmt, stmt_res->hstmt, SQL_HANDLE_STMT, tag, file, line TSRMLS_CC); 831 | /* cancel the statement */ 832 | SQLCancel(stmt_res->hstmt); 833 | /* make sure we release execution-related storage. */ 834 | if (stmt_res->lob_buffer != NULL) { 835 | efree(stmt_res->lob_buffer); 836 | stmt_res->lob_buffer = NULL; 837 | } 838 | if (stmt_res->converted_statement != NULL) { 839 | efree(stmt_res->converted_statement); 840 | stmt_res->converted_statement = NULL; 841 | } 842 | stmt_res->executing = 0; 843 | } else { 844 | /* raise the error */ 845 | raise_sql_error(stmt->dbh, stmt, stmt_res->hstmt, SQL_HANDLE_STMT, tag, file, line TSRMLS_CC); 846 | } 847 | } 848 | 849 | /* 850 | * Clears the error information 851 | */ 852 | void clear_stmt_error(pdo_stmt_t *stmt) 853 | { 854 | conn_handle *conn_res = (conn_handle *) stmt->dbh->driver_data; 855 | 856 | conn_res->error_data.sqlcode = 0; 857 | conn_res->error_data.filename = NULL; 858 | conn_res->error_data.lineno = 0; 859 | conn_res->error_data.failure_name = NULL; 860 | conn_res->error_data.sql_state[0] = '\0'; 861 | conn_res->error_data.err_msg[0] = '\0'; 862 | } 863 | -------------------------------------------------------------------------------- /informix_statement.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | (C) Copyright IBM Corporation 2006-2014. | 4 | +----------------------------------------------------------------------+ 5 | | | 6 | | Licensed under the Apache License, Version 2.0 (the "License"); you | 7 | | may not use this file except in compliance with the License. You may | 8 | | obtain a copy of the License at | 9 | | http://www.apache.org/licenses/LICENSE-2.0 | 10 | | | 11 | | Unless required by applicable law or agreed to in writing, software | 12 | | distributed under the License is distributed on an "AS IS" BASIS, | 13 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | 14 | | implied. See the License for the specific language governing | 15 | | permissions and limitations under the License. | 16 | +----------------------------------------------------------------------+ 17 | | Authors: Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier, | 18 | | Ambrish Bhargava, Rahul Priyadarshi | 19 | +----------------------------------------------------------------------+ 20 | */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "php_ini.h" 28 | #include "ext/standard/info.h" 29 | #include "pdo/php_pdo.h" 30 | #include "pdo/php_pdo_driver.h" 31 | #include "php_pdo_informix.h" 32 | #include "php_pdo_informix_int.h" 33 | 34 | struct lob_stream_data 35 | { 36 | stmt_handle *stmt_res; 37 | pdo_stmt_t *stmt; 38 | int colno; 39 | }; 40 | 41 | 42 | size_t lob_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) 43 | { 44 | SQLLEN readBytes = 0; 45 | struct lob_stream_data *data = stream->abstract; 46 | column_data *col_res = &data->stmt_res->columns[data->colno]; 47 | stmt_handle *stmt_res = data->stmt_res; 48 | pdo_stmt_t *stmt = data->stmt; 49 | int ctype = 0; 50 | SQLRETURN rc = 0; 51 | 52 | if (stream->eof == 1) { 53 | return (size_t)-1; 54 | } 55 | 56 | switch (col_res->data_type) { 57 | default: 58 | case SQL_LONGVARCHAR: 59 | ctype = SQL_C_CHAR; 60 | break; 61 | case SQL_LONGVARBINARY: 62 | case SQL_VARBINARY: 63 | case SQL_BINARY: 64 | case SQL_INFX_UDT_BLOB: 65 | case SQL_INFX_UDT_CLOB: 66 | ctype = SQL_C_BINARY; 67 | break; 68 | } 69 | 70 | rc = SQLGetData(stmt_res->hstmt, data->colno + 1, ctype, buf, count, &readBytes); 71 | check_stmt_error(rc, "SQLGetData"); 72 | 73 | if (rc == SQL_NO_DATA) { /*Already returned all of the data for the column*/ 74 | return (size_t)-1; 75 | } 76 | 77 | if (readBytes == SQL_NULL_DATA) { /*For NULL CLOB/BLOB values */ 78 | return (size_t) readBytes; 79 | } 80 | if (readBytes > count) { 81 | if ((col_res->data_type == SQL_LONGVARCHAR) && (count != 0)) { /*Dont return the NULL at end of CLOB buffer */ 82 | readBytes = count - 1; 83 | } else { 84 | readBytes = count; 85 | } 86 | } else if (count > readBytes) { 87 | stream->eof = 1; 88 | } 89 | return (size_t) readBytes; 90 | } 91 | 92 | size_t lob_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) 93 | { 94 | return 0; 95 | } 96 | 97 | int lob_stream_flush(php_stream *stream TSRMLS_DC) 98 | { 99 | return 0; 100 | } 101 | 102 | int lob_stream_close(php_stream *stream, int close_handle TSRMLS_DC) 103 | { 104 | struct lob_stream_data *data = stream->abstract; 105 | efree(data); 106 | return 0; 107 | } 108 | 109 | php_stream_ops lob_stream_ops = { 110 | lob_stream_write, /* Write */ 111 | lob_stream_read, /* Read */ 112 | lob_stream_close, /* Close */ 113 | lob_stream_flush, /* Flush */ 114 | "informix PDO Lob stream", 115 | NULL, /* Seek */ 116 | NULL, /* GetS */ 117 | NULL, /* Cast */ 118 | NULL /* Stat */ 119 | }; 120 | 121 | php_stream* create_lob_stream( pdo_stmt_t *stmt , stmt_handle *stmt_res , int colno TSRMLS_DC ) 122 | { 123 | struct lob_stream_data *data; 124 | column_data *col_res; 125 | php_stream *retval; 126 | char buf[1]; 127 | 128 | data = emalloc(sizeof(struct lob_stream_data)); 129 | data->stmt_res = stmt_res; 130 | data->stmt = stmt; 131 | data->colno = colno; 132 | col_res = &data->stmt_res->columns[data->colno]; 133 | retval = (php_stream *) php_stream_alloc(&lob_stream_ops, data, NULL, "r"); 134 | /* Find out if the column contains NULL data */ 135 | if (lob_stream_read(retval, buf, 0 TSRMLS_CC) == SQL_NULL_DATA) { 136 | php_stream_close(retval); 137 | return NULL; 138 | } else 139 | return retval; 140 | } 141 | 142 | /* 143 | * Clear up our column descriptors. This is done either from 144 | * the statement constructors or whenever we traverse from one 145 | * result set to the next. 146 | */ 147 | static void stmt_free_column_descriptors(pdo_stmt_t *stmt TSRMLS_DC) 148 | { 149 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 150 | if (stmt_res->columns != NULL) { 151 | int i; 152 | /* see if any of the columns have attached storage too. */ 153 | for (i = 0; i < stmt->column_count; i++) { 154 | /* 155 | * Was this a string form? We have an allocated string 156 | * buffer that also needs releasing. 157 | */ 158 | if (stmt_res->columns[i].returned_type == PDO_PARAM_STR) { 159 | efree(stmt_res->columns[i].data.str_val); 160 | } 161 | } 162 | 163 | /* free the entire column list. */ 164 | efree(stmt_res->columns); 165 | stmt_res->columns = NULL; 166 | } 167 | } 168 | 169 | /* 170 | * Cleanup any driver-allocated control blocks attached to a statement 171 | * instance. This cleans up the driver_data control block, as 172 | * well as any temporary allocations used during execution. 173 | */ 174 | void stmt_cleanup(pdo_stmt_t *stmt TSRMLS_DC) 175 | { 176 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 177 | if (stmt_res != NULL) { 178 | if (stmt_res->converted_statement != NULL) { 179 | efree(stmt_res->converted_statement); 180 | } 181 | if (stmt_res->lob_buffer != NULL) { 182 | stmt_res->lob_buffer = NULL; 183 | } 184 | /* free any descriptors we're keeping active */ 185 | stmt_free_column_descriptors(stmt TSRMLS_CC); 186 | efree(stmt_res); 187 | } 188 | stmt->driver_data = NULL; 189 | } 190 | 191 | /* get the parameter description information for a positional bound parameter. */ 192 | static int stmt_get_parameter_info(pdo_stmt_t * stmt, struct pdo_bound_param_data *param 193 | TSRMLS_DC) 194 | { 195 | param_node *param_res = (param_node *) param->driver_data; 196 | stmt_handle *stmt_res = NULL; 197 | int rc = 0; 198 | 199 | /* do we have the parameter information yet? */ 200 | if (param_res == NULL) { 201 | /* allocate a new one and attach to the PDO param structure */ 202 | param_res = (param_node *) emalloc(sizeof(param_node)); 203 | check_stmt_allocation(param_res, "stmt_get_parameter", 204 | "Unable to allocate parameter driver data"); 205 | 206 | /* get the statement specifics */ 207 | stmt_res = (stmt_handle *) stmt->driver_data; 208 | 209 | /* checks the server version for correct SQL column meta call */ 210 | if (stmt_res->server_ver >= 94) { 211 | /* 212 | * NB: The PDO parameter numbers are origin zero, but the 213 | * SQLDescribeParam() ones start with 1. 214 | */ 215 | rc = SQLDescribeParam((SQLHSTMT) stmt_res->hstmt, 216 | (SQLUSMALLINT) param->paramno + 1, 217 | ¶m_res->data_type, 218 | ¶m_res->param_size, ¶m_res->scale, ¶m_res->nullable); 219 | /* Free the memory if SQLDescribeParam failed */ 220 | if (rc == SQL_ERROR) { 221 | efree(param_res); 222 | param_res = NULL; 223 | } 224 | check_stmt_error(rc, "SQLDescribeParam"); 225 | } else { 226 | param_res->data_type = SQL_C_CHAR; 227 | } 228 | 229 | /* only attach this if we succeed */ 230 | param->driver_data = param_res; 231 | 232 | /* 233 | * but see if we need to alter this for binary forms or 234 | * can optimize numerics a little. 235 | */ 236 | switch (param_res->data_type) { 237 | /* 238 | * The binary forms need to be transferred as binary 239 | * data, not as char data. 240 | */ 241 | case SQL_BINARY: 242 | case SQL_INFX_UDT_BLOB: 243 | case SQL_INFX_UDT_CLOB: 244 | case SQL_VARBINARY: 245 | case SQL_LONGVARBINARY: 246 | param_res->ctype = SQL_C_BINARY; 247 | break; 248 | 249 | /* 250 | * Numeric forms we can map directly to a long 251 | * int value 252 | */ 253 | case SQL_SMALLINT: 254 | case SQL_INTEGER: 255 | param_res->ctype = SQL_C_LONG; 256 | break; 257 | 258 | /* everything else will transfer as binary */ 259 | default: 260 | /* by default, we transfer as character data */ 261 | param_res->ctype = SQL_C_CHAR; 262 | break; 263 | } 264 | } 265 | return TRUE; 266 | } 267 | 268 | /* 269 | * Bind a statement parameter to the PHP value supplying or receiving the 270 | * parameter data. 271 | */ 272 | int stmt_bind_parameter(pdo_stmt_t *stmt, struct pdo_bound_param_data *curr TSRMLS_DC) 273 | { 274 | int rc, is_num = 0; 275 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 276 | param_node *param_res = NULL; 277 | SQLSMALLINT inputOutputType; 278 | 279 | /* make sure we have current description information. */ 280 | if (stmt_get_parameter_info(stmt, curr TSRMLS_CC) == FALSE) { 281 | return FALSE; 282 | } 283 | 284 | param_res = (param_node *) curr->driver_data; 285 | 286 | /* 287 | * Now figure out the parameter type so we can tell the database code 288 | * how to handle this. 289 | * this is rare, really only used for stored procedures. 290 | */ 291 | if (curr->param_type & PDO_PARAM_INPUT_OUTPUT > 0) { 292 | inputOutputType = SQL_PARAM_INPUT_OUTPUT; 293 | } 294 | /* 295 | * If this is a non-positive length, we can't assign a value, 296 | * so this is by definition an INPUT param. 297 | */ 298 | else if (curr->max_value_len <= 0) { 299 | inputOutputType = SQL_PARAM_INPUT; 300 | } else { 301 | /* everything else is output. */ 302 | inputOutputType = SQL_PARAM_OUTPUT; 303 | } 304 | 305 | /* 306 | * Now do the actual binding, which is controlled by the 307 | * PDO supplied type. 308 | */ 309 | switch (PDO_PARAM_TYPE(curr->param_type)) { 310 | /* not implemented yet */ 311 | case PDO_PARAM_STMT: 312 | RAISE_INFORMIX_STMT_ERROR("IM001", "param_hook", 313 | "Driver does not support statement parameters"); 314 | return FALSE; 315 | 316 | /* this is a long value for PHP */ 317 | case PDO_PARAM_INT: 318 | /* 319 | * If the parameter type is a numeric type, we'll bind this 320 | * directly, 321 | */ 322 | if (param_res->ctype == SQL_C_LONG) { 323 | if (Z_TYPE_P(curr->parameter) == IS_NULL) { 324 | /* null value was found */ 325 | param_res->transfer_length = SQL_NULL_DATA; 326 | rc = SQLBindParameter(stmt_res->hstmt, 327 | curr->paramno + 1, 328 | inputOutputType, 329 | param_res->ctype, 330 | param_res->data_type, 331 | param_res->param_size, 332 | param_res->scale, NULL, 333 | curr->max_value_len <= 334 | 0 ? 0 : curr->max_value_len, 335 | ¶m_res->transfer_length); 336 | check_stmt_error(rc, "SQLBindParameter"); 337 | return TRUE; 338 | } else { 339 | convert_to_string(curr->parameter); 340 | if (!strcmp(curr->parameter->value.str.val, "")) { 341 | /* empty string was found */ 342 | param_res->transfer_length = SQL_NULL_DATA; 343 | rc = SQLBindParameter(stmt_res->hstmt, 344 | curr->paramno + 1, 345 | inputOutputType, 346 | param_res->ctype, 347 | param_res->data_type, 348 | param_res->param_size, 349 | param_res->scale, NULL, 350 | curr->max_value_len <= 351 | 0 ? 0 : curr->max_value_len, 352 | ¶m_res->transfer_length); 353 | check_stmt_error(rc, "SQLBindParameter"); 354 | return TRUE; 355 | } else { 356 | /* force this to be a real boolean value */ 357 | convert_to_long(curr->parameter); 358 | rc = SQLBindParameter(stmt_res->hstmt, 359 | curr->paramno + 1, 360 | inputOutputType, SQL_C_LONG, 361 | param_res->data_type, 362 | param_res->param_size, 363 | param_res->scale, 364 | &((curr->parameter)->value.lval), 365 | 0, NULL); 366 | check_stmt_error(rc, "SQLBindParameter"); 367 | return TRUE; 368 | } 369 | } 370 | } 371 | 372 | /* 373 | * NOTE: We fall through from above if there is a 374 | * type mismatch. 375 | */ 376 | 377 | /* a string value (very common) */ 378 | case PDO_PARAM_BOOL: 379 | case PDO_PARAM_STR: 380 | /* 381 | * If we're capable of handling an integer value, but 382 | * PDO is telling us string, then change this now. 383 | */ 384 | if (param_res->ctype == SQL_C_LONG) { 385 | /* change this to a character type */ 386 | param_res->ctype = SQL_C_CHAR; 387 | is_num = 1; 388 | } 389 | if (Z_TYPE_P(curr->parameter) == IS_NULL 390 | || (is_num && Z_STRVAL_P(curr->parameter) != NULL 391 | && (Z_STRVAL_P(curr->parameter) == '\0'))) { 392 | if (PDO_PARAM_TYPE(curr->param_type) == PDO_PARAM_BOOL ) { 393 | param_res->ctype = SQL_C_LONG; 394 | } else { 395 | param_res->ctype = SQL_C_CHAR; 396 | } 397 | param_res->param_size = 0; 398 | param_res->scale = 0; 399 | curr->max_value_len = 0; 400 | param_res->transfer_length = SQL_NULL_DATA; 401 | rc = SQLBindParameter(stmt_res->hstmt, curr->paramno + 1, 402 | inputOutputType, param_res->ctype, 403 | param_res->data_type, 404 | param_res->param_size, 405 | param_res->scale, 406 | &((curr->parameter)->value.lval), 407 | curr->max_value_len, 408 | ¶m_res->transfer_length); 409 | check_stmt_error(rc, "SQLBindParameter"); 410 | } else { 411 | /* force this to be a real string value */ 412 | convert_to_string(curr->parameter); 413 | /* 414 | * The transfer length to zero now...this 415 | * gets updated at EXEC_PRE time. 416 | */ 417 | param_res->transfer_length = 0; 418 | 419 | param_res->param_size = Z_STRLEN_P(curr->parameter); 420 | 421 | /* 422 | * Now we need to make sure the string buffer 423 | * is large enough to receive a new value if 424 | * this is an output or in/out parameter 425 | */ 426 | if (inputOutputType != SQL_PARAM_INPUT && 427 | curr->max_value_len > Z_STRLEN_P(curr->parameter)) { 428 | /* reallocate this to the new size */ 429 | Z_STRVAL_P(curr->parameter) = erealloc(Z_STRVAL_P(curr->parameter), 430 | curr->max_value_len + 1); 431 | check_stmt_allocation(Z_STRVAL_P(curr->parameter), 432 | "stmt_bind_parameter", 433 | "Unable to allocate bound parameter"); 434 | } 435 | 436 | rc = SQLBindParameter(stmt_res->hstmt, curr->paramno + 1, 437 | inputOutputType, param_res->ctype, 438 | param_res->data_type, 439 | param_res->param_size, 440 | param_res->scale, 441 | Z_STRVAL_P(curr->parameter), 442 | curr->max_value_len <= 443 | 0 ? 0 : curr->max_value_len, 444 | ¶m_res->transfer_length); 445 | check_stmt_error(rc, "SQLBindParameter"); 446 | } 447 | 448 | return TRUE; 449 | 450 | /* 451 | * This is either a string, or, if the length is zero, 452 | * then this is a pointer to a PHP stream. 453 | */ 454 | case PDO_PARAM_LOB: 455 | if (inputOutputType != SQL_PARAM_INPUT) { 456 | inputOutputType = SQL_PARAM_INPUT; 457 | } 458 | 459 | /* have we bound a LOB to a long type for some reason? */ 460 | if (param_res->ctype == SQL_C_LONG) { 461 | /* transfer this as character data. */ 462 | param_res->ctype = SQL_C_CHAR; 463 | } 464 | if (param_res->data_type == SQL_INFX_UDT_BLOB || 465 | param_res->data_type == SQL_INFX_UDT_CLOB) { 466 | /* transfer this as binary data. */ 467 | param_res->ctype = SQL_C_BINARY; 468 | } 469 | 470 | /* indicate we're going to transfer the data at exec time. */ 471 | param_res->transfer_length = SQL_DATA_AT_EXEC; 472 | 473 | /* 474 | * We can't bind LOBs at this point...we process all 475 | * of this at execute time. However, we set the value 476 | * data to the PDO binding control block and set the 477 | * SQL_DATA_AT_EXEC value to cause it to prompt us for 478 | * the data at execute time. The pointer is recoverable 479 | * at that time by using SQLParamData(), and we can 480 | * then process the request. 481 | */ 482 | rc = SQLBindParameter(stmt_res->hstmt, curr->paramno + 1, 483 | inputOutputType, param_res->ctype, 484 | param_res->data_type, 485 | param_res->param_size, param_res->scale, 486 | (SQLPOINTER) curr, 487 | 4096, 488 | ¶m_res->transfer_length); 489 | check_stmt_error(rc, "SQLBindParameter"); 490 | return TRUE; 491 | 492 | /* this is an unknown type */ 493 | default: 494 | RAISE_INFORMIX_STMT_ERROR( "IM001", "SQLBindParameter", "Unknown parameter type" ); 495 | return FALSE; 496 | } 497 | 498 | return TRUE; 499 | } 500 | 501 | /* handle the pre-execution phase for bound parameters. */ 502 | static int stmt_parameter_pre_execute(pdo_stmt_t *stmt, struct pdo_bound_param_data *curr TSRMLS_DC) 503 | { 504 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 505 | param_node *param_res = (param_node *) curr->driver_data; 506 | 507 | /* 508 | * Now we need to prepare the parameter binding information 509 | * for execution. If this is a LOB, then we need to ensure 510 | * the LOB data is going to be available and make sure 511 | * the binding is tagged to provide the data at exec time. 512 | */ 513 | if (PDO_PARAM_TYPE(curr->param_type) == PDO_PARAM_LOB) { 514 | /* 515 | * If the LOB data is a stream, we need to make sure it is 516 | * really there. 517 | */ 518 | if (Z_TYPE_P(curr->parameter) == IS_RESOURCE) { 519 | php_stream *stm; 520 | php_stream_statbuf sb; 521 | 522 | /* make sure we have a stream to work with */ 523 | php_stream_from_zval_no_verify(stm, &curr->parameter); 524 | 525 | if (stm == NULL) { 526 | RAISE_INFORMIX_STMT_ERROR( "HY000" , "SQLBindParameter" , 527 | "PDO_PARAM_LOB file stream is invalid"); 528 | } 529 | 530 | /* 531 | * Now see if we can retrieve length information from 532 | * the stream 533 | */ 534 | if (php_stream_stat(stm, &sb) == 0) { 535 | /* 536 | * Yes, we're able to give the statement some 537 | * hints about the size. 538 | */ 539 | param_res->transfer_length = SQL_LEN_DATA_AT_EXEC(sb.sb.st_size); 540 | } else { 541 | /* 542 | * Still unknown...we'll have to do everything 543 | * at execute size. 544 | */ 545 | param_res->transfer_length = SQL_LEN_DATA_AT_EXEC(0); 546 | } 547 | } else { 548 | /* 549 | * Convert this to a string value now. We bound the 550 | * data pointer to our parameter descriptor, so we 551 | * can't just supply this directly yet, but we can 552 | * at least give the size hint information. 553 | */ 554 | convert_to_string(curr->parameter); 555 | param_res->transfer_length = SQL_LEN_DATA_AT_EXEC(Z_STRLEN_P(curr->parameter)); 556 | } 557 | 558 | } else { 559 | if (Z_TYPE_P(curr->parameter) != IS_NULL && param_res != NULL) { 560 | /* 561 | * if we're processing this as string or binary data, 562 | * then directly update the length to the real value. 563 | */ 564 | if (param_res->ctype == SQL_C_LONG) { 565 | /* make sure this is a long value */ 566 | convert_to_long(curr->parameter); 567 | } else { 568 | /* 569 | * Make sure this is a string value...it might 570 | * have been changed between the bind and the 571 | * execute 572 | */ 573 | convert_to_string(curr->parameter); 574 | param_res->transfer_length = Z_STRLEN_P(curr->parameter); 575 | } 576 | } 577 | } 578 | return TRUE; 579 | } 580 | 581 | /* post-execution bound parameter handling. */ 582 | static int stmt_parameter_post_execute(pdo_stmt_t *stmt, struct pdo_bound_param_data *curr TSRMLS_DC) 583 | { 584 | param_node *param_res = (param_node *) curr->driver_data; 585 | 586 | /* 587 | * If the type of the parameter is a string, we need to update the 588 | * string length and make sure that these are null terminated. 589 | * Values returned from the DB are just copied directly into the bound 590 | * locations, so we need to update the PHP control blocks so that the 591 | * data is processed correctly. 592 | */ 593 | if ((param_res != NULL) && (Z_TYPE_P(curr->parameter) == IS_STRING)) { 594 | if (param_res->transfer_length < 0 || param_res->transfer_length == SQL_NULL_DATA) { 595 | Z_STRLEN_P(curr->parameter) = 0; 596 | Z_STRVAL_P(curr->parameter)[0] = '\0'; 597 | } else if (param_res->transfer_length == 0) { 598 | ZVAL_EMPTY_STRING(curr->parameter); 599 | } else { 600 | Z_STRLEN_P(curr->parameter) = param_res->transfer_length; 601 | Z_STRVAL_P(curr->parameter)[param_res->transfer_length] = '\0'; 602 | } 603 | } 604 | return TRUE; 605 | } 606 | 607 | /* bind a column to an internally allocated buffer location. */ 608 | static int stmt_bind_column(pdo_stmt_t *stmt, int colno TSRMLS_DC) 609 | { 610 | stmt_handle *stmt_res; 611 | column_data *col_res; 612 | struct pdo_column_data *col; 613 | int rc; 614 | SQLLEN in_length = 1; 615 | stmt_res = (stmt_handle *) stmt->driver_data; 616 | col_res = &stmt_res->columns[colno]; 617 | col = &stmt->columns[colno]; 618 | 619 | switch (col_res->data_type) { 620 | case SQL_LONGVARCHAR: 621 | case SQL_LONGVARBINARY: 622 | case SQL_VARBINARY: 623 | case SQL_BINARY: 624 | case SQL_INFX_UDT_BLOB: 625 | case SQL_INFX_UDT_CLOB: 626 | { 627 | /* we're going to need to do getdata calls to retrieve these */ 628 | col_res->out_length = 0; 629 | /* and this is returned as a stream */ 630 | col_res->returned_type = PDO_PARAM_LOB; 631 | col->param_type = PDO_PARAM_LOB; 632 | } 633 | break; 634 | /* 635 | * An extra byte is required to hold positive or negative value if the 636 | * data type is INTERVAL. That is why we are increasing in_length by 1. 637 | */ 638 | case SQL_INTERVAL_YEAR: 639 | case SQL_INTERVAL_MONTH: 640 | case SQL_INTERVAL_DAY: 641 | case SQL_INTERVAL_HOUR: 642 | case SQL_INTERVAL_MINUTE: 643 | case SQL_INTERVAL_SECOND: 644 | case SQL_INTERVAL_YEAR_TO_MONTH: 645 | case SQL_INTERVAL_DAY_TO_HOUR: 646 | case SQL_INTERVAL_DAY_TO_MINUTE: 647 | case SQL_INTERVAL_DAY_TO_SECOND: 648 | case SQL_INTERVAL_HOUR_TO_MINUTE: 649 | case SQL_INTERVAL_HOUR_TO_SECOND: 650 | case SQL_INTERVAL_MINUTE_TO_SECOND: 651 | in_length = in_length + 1; 652 | /* 653 | * A form we need to force into a string value... 654 | * this includes any unknown types 655 | */ 656 | case SQL_CHAR: 657 | case SQL_VARCHAR: 658 | case SQL_TYPE_TIME: 659 | case SQL_TYPE_TIMESTAMP: 660 | case SQL_BIGINT: 661 | case SQL_REAL: 662 | case SQL_FLOAT: 663 | case SQL_DOUBLE: 664 | case SQL_DECIMAL: 665 | case SQL_NUMERIC: 666 | default: 667 | if( col_res->data_type == SQL_CHAR || col_res->data_type == SQL_VARCHAR ){ 668 | /* Multiply the size by 4 to handle cases where client and server code pages are different. 669 | * 4 bytes should be able to cover any codeset character known*/ 670 | in_length = col_res->data_size * 4 + in_length; 671 | } else { 672 | in_length = col_res->data_size + in_length; 673 | } 674 | col_res->data.str_val = (char *) emalloc(in_length+1); 675 | check_stmt_allocation(col_res->data.str_val, 676 | "stmt_bind_column", 677 | "Unable to allocate column buffer"); 678 | col_res->data.str_val[in_length] = '\0'; 679 | rc = SQLBindCol((SQLHSTMT) stmt_res->hstmt, 680 | (SQLUSMALLINT) (colno + 1), SQL_C_CHAR, 681 | col_res->data.str_val, in_length, 682 | (SQLLEN *) (&col_res->out_length)); 683 | col_res->returned_type = PDO_PARAM_STR; 684 | col->param_type = PDO_PARAM_STR; 685 | } 686 | return TRUE; 687 | } 688 | 689 | /* allocate a set of internal column descriptors for a statement. */ 690 | static int stmt_allocate_column_descriptors(pdo_stmt_t *stmt TSRMLS_DC) 691 | { 692 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 693 | SQLSMALLINT nResultCols = 0; 694 | 695 | /* not sure */ 696 | int rc = SQLNumResultCols((SQLHSTMT) stmt_res->hstmt, &nResultCols); 697 | check_stmt_error(rc, "SQLNumResultCols"); 698 | 699 | /* 700 | * Make sure we set the count in the PDO stmt structure so the driver 701 | * knows how many columns we're dealing with. 702 | */ 703 | stmt->column_count = nResultCols; 704 | 705 | /* 706 | * Allocate the column descriptors now. We'll bind each column 707 | * individually before the first fetch. The binding process will 708 | * allocate any additional buffers we might need for the data. 709 | */ 710 | stmt_res->columns = (column_data *) ecalloc(sizeof(column_data), stmt->column_count); 711 | check_stmt_allocation(stmt_res->columns, "stmt_allocate_column_descriptors", 712 | "Unable to allocate column descriptor tables"); 713 | memset(stmt_res->columns, '\0', sizeof(column_data) * stmt->column_count); 714 | return TRUE; 715 | } 716 | 717 | /* 718 | * This is also used for error cleanup for errors that occur while 719 | * the stmt is still half constructed. 720 | */ 721 | int informix_stmt_dtor( pdo_stmt_t *stmt TSRMLS_DC) 722 | { 723 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 724 | 725 | if (stmt_res != NULL) { 726 | if (stmt_res->hstmt != SQL_NULL_HANDLE) { 727 | /* if we've done some work, we need to clean up. */ 728 | if (stmt->executed) { 729 | /* cancel anything we have pending at this point */ 730 | SQLCancel(stmt_res->hstmt); 731 | } 732 | SQLFreeHandle(SQL_HANDLE_STMT, stmt_res->hstmt); 733 | stmt_res->hstmt = SQL_NULL_HANDLE; 734 | } 735 | /* release any control blocks we have attached to this statement */ 736 | stmt_cleanup(stmt TSRMLS_CC); 737 | } 738 | return TRUE; 739 | } 740 | 741 | /* 742 | * Execute a PDOStatement. Used for both the PDOStatement::execute() method 743 | * as well as the PDO:query() method. 744 | */ 745 | static int informix_stmt_executer( pdo_stmt_t * stmt TSRMLS_DC) 746 | { 747 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 748 | int rc = 0; 749 | SQLLEN rowCount; 750 | 751 | /* 752 | * If this statement has already been executed, then we need to 753 | * cancel the previous execution before doing this again. 754 | */ 755 | if (stmt->executed) { 756 | rc = SQLFreeStmt(stmt_res->hstmt, SQL_CLOSE); 757 | check_stmt_error(rc, "SQLFreeStmt"); 758 | } 759 | 760 | /* 761 | * We're executing now...this tells error handling to Cancel 762 | * if there's an error. 763 | */ 764 | stmt_res->executing = 1; 765 | 766 | /* clear the current error information to get ready for new execute */ 767 | clear_stmt_error(stmt); 768 | 769 | stmt_res->lob_buffer = NULL; 770 | /* 771 | * Execute the statement. All parameters should be bound at 772 | * this point, but we might need to pump data in for some of 773 | * the parameters. 774 | */ 775 | rc = SQLExecute((SQLHSTMT) stmt_res->hstmt); 776 | check_stmt_error(rc, "SQLExecute"); 777 | /* 778 | * Now check if we have indirectly bound parameters. If we do, 779 | * then we need to push the data for those parameters into the 780 | * processing pipe. 781 | */ 782 | 783 | if (rc == SQL_NEED_DATA) { 784 | struct pdo_bound_param_data *param; 785 | 786 | /* 787 | * Get the associated parameter data. The bind process should have 788 | * stored a pointer to the parameter control block, so we identify 789 | * which one needs data from that. 790 | */ 791 | while ((SQLParamData(stmt_res->hstmt, (SQLPOINTER) & param)) == SQL_NEED_DATA) { 792 | 793 | /* 794 | * OK, we have a LOB. This is either in string form, in 795 | * which case we can supply it directly, or is a PHP stream. 796 | * If it is a stream, then the type is IS_RESOURCE, and we 797 | * need to pump the data in a buffer at a time. 798 | */ 799 | if (Z_TYPE_P(param->parameter) != IS_RESOURCE) { 800 | convert_to_string(param->parameter); 801 | rc = SQLPutData(stmt_res->hstmt, Z_STRVAL_P(param->parameter), 802 | Z_STRLEN_P(param->parameter)); 803 | check_stmt_error(rc, "SQLPutData"); 804 | continue; 805 | } else { 806 | /* 807 | * The LOB is a stream. This better still be good, else we 808 | * can't supply the data. 809 | */ 810 | php_stream *stm = NULL; 811 | int len; 812 | php_stream_from_zval_no_verify(stm, &(param->parameter)); 813 | if (!stm) { 814 | RAISE_INFORMIX_STMT_ERROR("HY000", "execute", 815 | "Input parameter LOB is no longer a valid stream"); 816 | return FALSE; 817 | } 818 | /* allocate a buffer if we haven't prior to this */ 819 | if (stmt_res->lob_buffer == NULL) { 820 | stmt_res->lob_buffer = emalloc(LOB_BUFFER_SIZE); 821 | check_stmt_allocation(stmt_res->lob_buffer, 822 | "stmt_execute", "Unable to allocate parameter data buffer"); 823 | } 824 | /* read a buffer at a time and push into the execution pipe. */ 825 | for (;;) { 826 | len = php_stream_read(stm, stmt_res->lob_buffer, LOB_BUFFER_SIZE); 827 | if (len == 0) { 828 | break; 829 | } 830 | /* add the buffer */ 831 | rc = SQLPutData(stmt_res->hstmt, stmt_res->lob_buffer, len); 832 | check_stmt_error(rc, "SQLPutData"); 833 | } 834 | } 835 | } 836 | /* Free any LOB buffer we might have */ 837 | if (stmt_res->lob_buffer != NULL) { 838 | efree(stmt_res->lob_buffer); 839 | } 840 | } 841 | else 842 | { 843 | /* 844 | * Now set the rowcount field in the statement. This will be the 845 | * number of rows affected by the SQL statement, not the number of 846 | * rows in the result set. 847 | */ 848 | rc = SQLRowCount(stmt_res->hstmt, &rowCount); 849 | check_stmt_error(rc, "SQLRowCount"); 850 | /* store the affected rows information. */ 851 | stmt->row_count = rowCount; 852 | 853 | /* Is this the first time we've executed this statement? */ 854 | if (!stmt->executed) { 855 | if (stmt_allocate_column_descriptors(stmt TSRMLS_CC) == FALSE) { 856 | return FALSE; 857 | } 858 | } 859 | } 860 | 861 | /* Set the last serial id inserted */ 862 | rc = record_last_insert_id(stmt->dbh, stmt_res->hstmt TSRMLS_CC); 863 | if( rc == SQL_ERROR ) { 864 | return FALSE; 865 | } 866 | 867 | /* we can turn off the cleanup flag now */ 868 | stmt_res->executing = 0; 869 | 870 | return TRUE; 871 | } 872 | 873 | /* fetch the next row of the result set. */ 874 | static int informix_stmt_fetcher( 875 | pdo_stmt_t *stmt, 876 | enum pdo_fetch_orientation ori, 877 | long offset 878 | TSRMLS_DC) 879 | { 880 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 881 | /* by default, we're just fetching the next one */ 882 | SQLSMALLINT direction = SQL_FETCH_NEXT; 883 | int rc = 0; 884 | 885 | /* convert the PDO orientation information to the SQL one */ 886 | switch (ori) { 887 | case PDO_FETCH_ORI_NEXT: 888 | direction = SQL_FETCH_NEXT; 889 | break; 890 | case PDO_FETCH_ORI_PRIOR: 891 | direction = SQL_FETCH_PRIOR; 892 | break; 893 | case PDO_FETCH_ORI_FIRST: 894 | direction = SQL_FETCH_FIRST; 895 | break; 896 | case PDO_FETCH_ORI_LAST: 897 | direction = SQL_FETCH_LAST; 898 | break; 899 | case PDO_FETCH_ORI_ABS: 900 | direction = SQL_FETCH_ABSOLUTE; 901 | break; 902 | case PDO_FETCH_ORI_REL: 903 | direction = SQL_FETCH_RELATIVE; 904 | break; 905 | } 906 | 907 | /* go fetch it. */ 908 | rc = SQLFetchScroll((SQLHSTMT)stmt_res->hstmt, direction, (SQLINTEGER) offset); 909 | check_stmt_error(rc, "SQLFetchScroll"); 910 | 911 | /* 912 | * The fetcher() routine has an overloaded return value. 913 | * A false return can indicate either an error or the end 914 | * of the row data. 915 | */ 916 | if (rc == SQL_NO_DATA) { 917 | /* 918 | * We are scrolling forward, then close the cursor 919 | * to release resources tied up by this statement. 920 | */ 921 | if (stmt_res->cursor_type == PDO_CURSOR_FWDONLY) { 922 | SQLCloseCursor(stmt_res->hstmt); 923 | } 924 | return FALSE; 925 | } else if (rc == SQL_ERROR) { 926 | return FALSE; 927 | } 928 | 929 | return TRUE; 930 | } 931 | 932 | /* process the various bound parameter events. */ 933 | static int informix_stmt_param_hook( 934 | pdo_stmt_t *stmt, 935 | struct pdo_bound_param_data *param, 936 | enum pdo_param_event event_type 937 | TSRMLS_DC) 938 | { 939 | /* 940 | * We get called for both parameters and bound columns. 941 | * We only need to process the parameters 942 | */ 943 | if (param->is_param) { 944 | switch (event_type) { 945 | case PDO_PARAM_EVT_ALLOC: 946 | break; 947 | 948 | case PDO_PARAM_EVT_FREE: 949 | /* 950 | * During the alloc event, we attached some driver 951 | * specific data. We need to free this now. 952 | */ 953 | if (param->driver_data != NULL) { 954 | efree(param->driver_data); 955 | param->driver_data = NULL; 956 | } 957 | break; 958 | 959 | case PDO_PARAM_EVT_EXEC_PRE: 960 | /* we're allocating a bound parameter, go do the binding */ 961 | stmt_bind_parameter(stmt, param TSRMLS_CC); 962 | return stmt_parameter_pre_execute(stmt, param TSRMLS_CC); 963 | case PDO_PARAM_EVT_EXEC_POST: 964 | return stmt_parameter_post_execute(stmt, param TSRMLS_CC); 965 | 966 | /* parameters aren't processed at the fetch phase. */ 967 | case PDO_PARAM_EVT_FETCH_PRE: 968 | case PDO_PARAM_EVT_FETCH_POST: 969 | break; 970 | } 971 | } else { 972 | switch (event_type) { 973 | case PDO_PARAM_EVT_ALLOC: 974 | break; 975 | case PDO_PARAM_EVT_FREE: 976 | break; 977 | case PDO_PARAM_EVT_EXEC_PRE: 978 | break; 979 | case PDO_PARAM_EVT_EXEC_POST: 980 | break; 981 | case PDO_PARAM_EVT_FETCH_PRE: 982 | if (param->param_type == PDO_PARAM_LOB) { 983 | (&((stmt_handle *) stmt->driver_data)-> 984 | columns[param->paramno])->returned_type = PDO_PARAM_LOB; 985 | } 986 | break; 987 | case PDO_PARAM_EVT_FETCH_POST: 988 | break; 989 | } 990 | } 991 | return TRUE; 992 | } 993 | 994 | /* describe a column for the PDO driver. */ 995 | static int informix_stmt_describer( 996 | pdo_stmt_t *stmt, 997 | int colno 998 | TSRMLS_DC) 999 | { 1000 | stmt_handle *stmt_res = (stmt_handle *)stmt->driver_data; 1001 | /* access the information for this column */ 1002 | column_data *col_res = &stmt_res->columns[colno]; 1003 | struct pdo_column_data *col = NULL; 1004 | char tmp_name[BUFSIZ]; 1005 | 1006 | /* get the column descriptor information */ 1007 | int rc = SQLDescribeCol((SQLHSTMT)stmt_res->hstmt, (SQLSMALLINT)(colno + 1 ), 1008 | tmp_name, BUFSIZ, &col_res->namelen, &col_res->data_type, &col_res->data_size, 1009 | &col_res->scale, &col_res->nullable); 1010 | check_stmt_error(rc, "SQLDescribeCol"); 1011 | 1012 | rc = SQLColAttribute(stmt_res->hstmt, colno+1, SQL_DESC_DISPLAY_SIZE, 1013 | NULL, 0, NULL, &col_res->data_size); 1014 | check_stmt_error(rc, "SQLColAttribute"); 1015 | /* 1016 | * Make sure we get a name properly. If the name is too long for our 1017 | * buffer (which in theory should never happen), allocate a longer one 1018 | * and ask for the information again. 1019 | */ 1020 | if (col_res->namelen <= 0) { 1021 | col_res->name = estrdup(""); 1022 | check_stmt_allocation(col_res->name, "informix_stmt_describer", 1023 | "Unable to allocate column name"); 1024 | } else if (col_res->namelen >= BUFSIZ ) { 1025 | /* column name is longer than BUFSIZ */ 1026 | col_res->name = emalloc(col_res->namelen + 1); 1027 | check_stmt_allocation(col_res->name, "informix_stmt_describer", "Unable to allocate column name"); 1028 | rc = SQLDescribeCol((SQLHSTMT)stmt_res->hstmt, (SQLSMALLINT)(colno + 1 ), col_res->name, 1029 | BUFSIZ, &col_res->namelen, &col_res->data_type, &col_res->data_size, &col_res->scale, 1030 | &col_res->nullable); 1031 | check_stmt_error(rc, "SQLDescribeCol"); 1032 | } else { 1033 | col_res->name = estrdup(tmp_name); 1034 | check_stmt_allocation(col_res->name, "informix_stmt_describer", "Unable to allocate column name"); 1035 | } 1036 | col = &stmt->columns[colno]; 1037 | 1038 | /* 1039 | * Copy the information back into the PDO control block. Note that 1040 | * PDO will release the name information, so we don't have to. 1041 | */ 1042 | col->name = col_res->name; 1043 | col->namelen = col_res->namelen; 1044 | col->maxlen = col_res->data_size; 1045 | col->precision = col_res->scale; 1046 | 1047 | /* bind the columns */ 1048 | stmt_bind_column(stmt, colno TSRMLS_CC); 1049 | return TRUE; 1050 | } 1051 | 1052 | /* 1053 | * Fetch the data for a specific column. This should be sitting in our 1054 | * allocated buffer already, and easy to return. 1055 | */ 1056 | static int informix_stmt_get_col( 1057 | pdo_stmt_t *stmt, 1058 | int colno, 1059 | char **ptr, 1060 | unsigned long *len, 1061 | int *caller_frees 1062 | TSRMLS_DC) 1063 | { 1064 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 1065 | /* access our look aside data */ 1066 | column_data *col_res = &stmt_res->columns[colno]; 1067 | 1068 | if (col_res->returned_type == PDO_PARAM_LOB) { 1069 | php_stream *stream = create_lob_stream(stmt, stmt_res, colno TSRMLS_CC); /* already opened */ 1070 | if (stream != NULL) { 1071 | *ptr = (char *) stream; 1072 | } else { 1073 | *ptr = NULL; 1074 | } 1075 | *len = 0; 1076 | } 1077 | /* see if this is a null value */ 1078 | else if (col_res->out_length == SQL_NULL_DATA) { 1079 | /* return this as a real null */ 1080 | *ptr = NULL; 1081 | *len = 0; 1082 | } 1083 | /* see if length is SQL_NTS ("count the length yourself"-value) */ 1084 | else if (col_res->out_length == SQL_NTS) { 1085 | if (col_res->data.str_val && col_res->data.str_val[0] != '\0') { 1086 | /* it's not an empty string */ 1087 | *ptr = col_res->data.str_val; 1088 | *len = strlen(col_res->data.str_val); 1089 | } else if (col_res->data.str_val && col_res->data.str_val[0] == '\0') { 1090 | /* it's an empty string */ 1091 | *ptr = col_res->data.str_val; 1092 | *len = 0; 1093 | } else { 1094 | /* it's NULL */ 1095 | *ptr = NULL; 1096 | *len = 0; 1097 | } 1098 | } 1099 | /* string type...very common */ 1100 | else if (col_res->returned_type == PDO_PARAM_STR) { 1101 | /* set the info */ 1102 | switch(col_res->data_type) { 1103 | case SQL_INTEGER: 1104 | case SQL_SMALLINT: 1105 | case SQL_INFX_BIGINT: 1106 | if (col_res->out_length > 20) { 1107 | *ptr = NULL; 1108 | *len = 0; 1109 | break; 1110 | } 1111 | default: 1112 | *ptr = col_res->data.str_val; 1113 | *len = col_res->out_length; 1114 | } 1115 | } else { 1116 | /* binary numeric form */ 1117 | *ptr = (char *) &col_res->data.l_val; 1118 | *len = col_res->out_length; 1119 | } 1120 | 1121 | return TRUE; 1122 | } 1123 | 1124 | /* step to the next result set of the query. */ 1125 | static int informix_stmt_next_rowset( 1126 | pdo_stmt_t *stmt 1127 | TSRMLS_DC) 1128 | { 1129 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 1130 | 1131 | /* 1132 | * Now get the next result set. This has the side effect 1133 | * of cleaning up the current cursor, if it exists. 1134 | */ 1135 | int rc = SQLMoreResults(stmt_res->hstmt); 1136 | /* 1137 | * We don't raise errors here. A success return codes 1138 | * signals we have more result sets to process, so we 1139 | * set everything up to read that info. Otherwise, we just 1140 | * signal the main driver we're finished. 1141 | */ 1142 | if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) { 1143 | return FALSE; 1144 | } 1145 | 1146 | /* 1147 | * The next result set may have different column information, so 1148 | * we need to clear out our existing set. 1149 | */ 1150 | stmt_free_column_descriptors(stmt TSRMLS_CC); 1151 | /* Now allocate a new set of column descriptors */ 1152 | if (stmt_allocate_column_descriptors(stmt TSRMLS_CC) == FALSE) { 1153 | return FALSE; 1154 | } 1155 | /* more results to process */ 1156 | return TRUE; 1157 | } 1158 | 1159 | /* 1160 | * Return all of the meta data information that makes sense for 1161 | * this database driver. 1162 | */ 1163 | static int informix_stmt_get_column_meta( 1164 | pdo_stmt_t *stmt, 1165 | long colno, 1166 | zval *return_value 1167 | TSRMLS_DC) 1168 | { 1169 | stmt_handle *stmt_res = NULL; 1170 | column_data *col_res = NULL; 1171 | 1172 | #define ATTRIBUTEBUFFERSIZE 256 1173 | char attribute_buffer[ATTRIBUTEBUFFERSIZE]; 1174 | SQLSMALLINT length; 1175 | SQLINTEGER numericAttribute; 1176 | zval *flags; 1177 | 1178 | if (colno >= stmt->column_count) { 1179 | RAISE_INFORMIX_STMT_ERROR("HY097", "getColumnMeta", 1180 | "Column number out of range"); 1181 | return FAILURE; 1182 | } 1183 | 1184 | stmt_res = (stmt_handle *) stmt->driver_data; 1185 | /* access our look aside data */ 1186 | col_res = &stmt_res->columns[colno]; 1187 | 1188 | /* make sure the return value is initialized as an array. */ 1189 | array_init(return_value); 1190 | add_assoc_long(return_value, "scale", col_res->scale); 1191 | 1192 | /* see if we can retrieve the table name */ 1193 | if (SQLColAttribute (stmt_res->hstmt, colno + 1, SQL_DESC_BASE_TABLE_NAME, 1194 | (SQLPOINTER) attribute_buffer, ATTRIBUTEBUFFERSIZE, &length, 1195 | (SQLPOINTER) & numericAttribute) != SQL_ERROR) { 1196 | /* 1197 | * Most of the time, this seems to return a null string. only 1198 | * return this if we have something real. 1199 | */ 1200 | if (length > 0) { 1201 | add_assoc_stringl(return_value, "table", attribute_buffer, length, 1); 1202 | } 1203 | } 1204 | /* see if we can retrieve the type name */ 1205 | if (SQLColAttribute(stmt_res->hstmt, colno + 1, SQL_DESC_TYPE_NAME, 1206 | (SQLPOINTER) attribute_buffer, ATTRIBUTEBUFFERSIZE, &length, 1207 | (SQLPOINTER) & numericAttribute) != SQL_ERROR) { 1208 | add_assoc_stringl(return_value, "native_type", attribute_buffer, length, 1); 1209 | } 1210 | 1211 | MAKE_STD_ZVAL(flags); 1212 | array_init(flags); 1213 | add_assoc_bool(flags, "not_null", !col_res->nullable); 1214 | 1215 | /* see if we can retrieve the unsigned attribute */ 1216 | if (SQLColAttribute(stmt_res->hstmt, colno + 1, SQL_DESC_UNSIGNED, 1217 | (SQLPOINTER) attribute_buffer, ATTRIBUTEBUFFERSIZE, &length, 1218 | (SQLPOINTER) & numericAttribute) != SQL_ERROR) { 1219 | add_assoc_bool(flags, "unsigned", numericAttribute == SQL_TRUE); 1220 | } 1221 | 1222 | /* see if we can retrieve the autoincrement attribute */ 1223 | if (SQLColAttribute (stmt_res->hstmt, colno + 1, SQL_DESC_AUTO_UNIQUE_VALUE, 1224 | (SQLPOINTER) attribute_buffer, ATTRIBUTEBUFFERSIZE, &length, 1225 | (SQLPOINTER) & numericAttribute) != SQL_ERROR) { 1226 | add_assoc_bool(flags, "auto_increment", 1227 | numericAttribute == SQL_TRUE); 1228 | } 1229 | 1230 | /* add the flags to the result bundle. */ 1231 | add_assoc_zval(return_value, "flags", flags); 1232 | 1233 | return SUCCESS; 1234 | } 1235 | 1236 | #define CURSOR_NAME_BUFFER_LENGTH 256 1237 | 1238 | /* get driver specific attributes. We only support CURSOR_NAME. */ 1239 | static int informix_stmt_get_attribute( 1240 | pdo_stmt_t *stmt, 1241 | long attr, 1242 | zval *return_value 1243 | TSRMLS_DC) 1244 | { 1245 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 1246 | 1247 | /* anything we can't handle is an error */ 1248 | switch (attr) { 1249 | case PDO_ATTR_CURSOR_NAME: 1250 | { 1251 | char buffer[CURSOR_NAME_BUFFER_LENGTH]; 1252 | SQLSMALLINT length; 1253 | 1254 | int rc = SQLGetCursorName(stmt_res->hstmt, buffer, 1255 | CURSOR_NAME_BUFFER_LENGTH, &length); 1256 | check_stmt_error(rc, "SQLGetCursorName"); 1257 | 1258 | /* this is a string value */ 1259 | ZVAL_STRINGL(return_value, buffer, length, 1); 1260 | return TRUE; 1261 | } 1262 | /* unknown attribute */ 1263 | default: 1264 | { 1265 | /* raise a driver error, and give the special -1 return. */ 1266 | RAISE_INFORMIX_STMT_ERROR("IM001", "getAttribute", "Unknown attribute"); 1267 | return -1; 1268 | /* the -1 return does not raise an error immediately. */ 1269 | } 1270 | } 1271 | } 1272 | 1273 | /* set a driver-specific attribute. We only support CURSOR_NAME. */ 1274 | static int informix_stmt_set_attribute( 1275 | pdo_stmt_t *stmt, 1276 | long attr, 1277 | zval *value 1278 | TSRMLS_DC) 1279 | { 1280 | stmt_handle *stmt_res = (stmt_handle *) stmt->driver_data; 1281 | int rc = 0; 1282 | 1283 | switch (attr) { 1284 | case PDO_ATTR_CURSOR_NAME: 1285 | { 1286 | /* we need to force this to a string value */ 1287 | convert_to_string(value); 1288 | /* set the cursor value */ 1289 | rc = SQLSetCursorName(stmt_res->hstmt, Z_STRVAL_P(value), Z_STRLEN_P(value)); 1290 | check_stmt_error(rc, "SQLSetCursorName"); 1291 | return TRUE; 1292 | } 1293 | default: 1294 | { 1295 | /* raise a driver error, and give the special -1 return. */ 1296 | RAISE_INFORMIX_STMT_ERROR("IM001", "getAttribute", "Unknown attribute"); 1297 | return -1; 1298 | /* the -1 return does not raise an error immediately. */ 1299 | } 1300 | } 1301 | } 1302 | 1303 | 1304 | int record_last_insert_id(pdo_dbh_t * dbh, SQLHANDLE hstmt TSRMLS_DC) 1305 | { 1306 | SQLINTEGER diag_func_type; 1307 | int rc; 1308 | conn_handle *conn_res = (conn_handle *) dbh->driver_data; 1309 | 1310 | rc = SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0, SQL_DIAG_DYNAMIC_FUNCTION_CODE, &diag_func_type, 0, NULL); 1311 | 1312 | if(rc == SQL_ERROR) { 1313 | conn_res->last_insert_id = 0; 1314 | return SQL_ERROR; 1315 | } 1316 | if (diag_func_type == SQL_DIAG_INSERT) { 1317 | rc = SQLGetStmtAttr(hstmt, SQL_GET_SERIAL_VALUE, &conn_res->last_insert_id, SQL_IS_INTEGER, NULL); 1318 | 1319 | if(rc == SQL_ERROR) { 1320 | conn_res->last_insert_id = 0; 1321 | return SQL_ERROR; 1322 | } 1323 | } 1324 | return TRUE; 1325 | } 1326 | 1327 | struct pdo_stmt_methods informix_stmt_methods = { 1328 | informix_stmt_dtor, 1329 | informix_stmt_executer, 1330 | informix_stmt_fetcher, 1331 | informix_stmt_describer, 1332 | informix_stmt_get_col, 1333 | informix_stmt_param_hook, 1334 | informix_stmt_set_attribute, 1335 | informix_stmt_get_attribute, 1336 | informix_stmt_get_column_meta, 1337 | informix_stmt_next_rowset 1338 | }; 1339 | --------------------------------------------------------------------------------