├── 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 |
--------------------------------------------------------------------------------