Skip to content. | Skip to navigation

Sections
Personal tools
You are here: Home Accelerate Articles U2 PDO Driver, Part 1: Write a PHP Data Objects driver for U2

U2 PDO Driver, Part 1: Write a PHP Data Objects Driver for U2

The PHP Data Objects (PDO) extension provides a lightweight, convenient means for accessing databases in PHP. However, you must use a database-specific PDO driver to access a database server. Currently there is no PDO driver for the Rocket U2 data servers, UniData® and UniVerse®. In this article, you'll learn how to write a PDO driver for U2 using the U2 native interface, InterCall. With this PDO driver, U2 users can develop PHP applications that access U2 data quickly and easily.

PHP U2 data access using InterCall

Level: Advanced

Double Xia ( sxia@rs.com), Software Engineer, Rocket Software

07 Dec 2006


Introduction

PHP is a widely used open source general-purpose scripting language that is especially well-suited for Web development and can be embedded into HTML. According to a survey by www.nexen.net for April 2006, on worldwide Internet Web sites, PHP is found on 35.44% of Web sites. PHP is the fastest growing server-side language.

A number of factors have contributed to PHP's success:

  • Open source
  • Multi-platform support
  • Raw 3x to 4x performance advantage over JSP (source: eWeek), which translates directly to hardware savings
  • 2x to 5x development time advantage over JSP (source: PerlMonth), which translates directly to software development resource savings
  • Integration with Java EJBs and servlets, as well as database access, SOAP, and XML

However, there's no direct way to access data on U2 data servers from PHP. Luckily, the PHP PDO extension provides a means to accomplish U2 data access. We will first discuss PDO objects and how to use them to access a database, followed by a specific example of building a U2 PDO driver in C language using U2's InterCall interface.

 

PHP Data Objects

The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP. Each database driver that implements the PDO interface can expose database-specific features as regular extension functions. PDO provides a data-access abstraction layer, which means that you use the same functions to issue queries and fetch data regardless of which database you're using.

To use PDO to connect to a database, you need to instantiate the PDO class with parameters of data source name (DSN), user name, and password for the user name. The DSN specifies the PDO driver and other driver-specific information. For example, the following DSN uses U2 PDO driver, and logs on to a demo account of UniData server running on machine localhost:

u2:dbtype=ud;host=localhost;acct=demo
 

The following statements connect to a U2 server and return a database handle $dbh:

try {
       $dbh = new PDO("u2:dbtype=ud;host=localhost;acct=demo", "my_name", "my_pwd");
} catch (PDOException $e) {
       $ dbh = null;
       echo 'Connection failed: ' . $e->getMessage();
}
 

When the driver cannot be loaded, or the U2 server cannot be connected, a PDOException is thrown so you can decide how to handle the failure.

Currently PDO has no connection management of its own. So each call to "new PDO()" creates a new connection to the database. The connection is released when the database handle variable goes out of scope, or when the handle is assigned to a NULL value. So this statement:

$dbh = NULL;
 

releases the connection established earlier.

After the connection has been created, you can prepare the statement by calling the prepare() method of the database handle, and get a statement handle. After this, you can bind parameters and execute the statement. In this example, we're calling a U2 Basic subroutine and using four parameter placeholders: ":code", ":params", ":outdata", and ":outcode".

$stmt = $dbh->prepare("CALL MYSUB :code :params :outdata :outcode");
 

Having prepared the statement, we can associate the named parameters and PHP variables by using the bingParam() method of the statement handle. For example, we define the parameter ":outdata" as INPUT/OUTPUT and associate it with a PHP variable, $outdata, whose maximum length is 100KB:

$stmt->bindParam(':code', $xcode);
$stmt->bindParam(':params', $xparams);
$stmt->bindParam(':outdata', $outdata, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 102400);
$stmt->bindParam(':outcode', $outcode, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 12);
$xcode = 14;
$xparams = $rec;
 

Use the execute() method of the statement handle to execute the prepared statement:

if ($stmt->execute()) {
    echo "outdata is:" . $outdata;
}
 

If the statement yields a result set, you can repeatedly call the fetch() method of the statement handle to get the next row of the result set:

if ($stmt->execute()) {
    while ($row = $stmt->fetch()) {
        print_r($row);
    }
}

U2 InterCall interface

InterCall is an application programming interface (API) that enables a UNIX® or Windows® client to access data on U2 servers. With InterCall, your applications can:

  • Connect to one or more servers
  • Access files and records
  • Execute database commands
  • Run U2 Basic programs

InterCall uses UniRPC to communicate with U2 servers. Using InterCall function: ic_opensession, ic_unidata_session, or ic_universe_session, the client program initializes InterCall, logs on to a host system over TCP/IP, and runs a server.

As the client program runs, InterCall functions send requests to the server to be executed. The program can access files, records, commands, and BASIC programs that are available in the server database environment. When it finishes, it calls ic_quit or ic_quitall to terminate the server program.

...
session_id = ic_opensession(server_name, user_name, password, account, &code, NULL);

if (code != 0)
        fprintf(stderr, "Failed to open session. Code = %d\n", code);
else {
        printf("Session open!\n");

        dict_flag = IK_DATA;
        filename  = "VOC";
        file_len  = strlen(filename);

        ic_open(&file_id, &dict_flag, filename, &file_len, &status_func, &code);

        if (code != 0)
            fprintf(stderr, "Failed to open VOC, code = %d\n", code);
        else {
            printf("Open of VOC returned status = %d\n", status_func);

            lock         = IK_READ;
            recordid     = "COMPUTE";
               id_len       = strlen(recordid);
            max_rec_size = MAX_REC_SIZE;

            ic_read(&file_id, &lock, recordid, &id_len, record,
                    &max_rec_size, &record_len, &status_func, &code);

            if (code != 0)
                fprintf(stderr, "Read of record failed. code = %d", code);
            else {
                int i;
                int field = 1;

                printf("Read of record returned status %d\n", status_func);
                printf("Size of record = %d\n", record_len);

                printf("Record contents:\n");

                printf("Field %02d: ", field);
                for (i = 0; i < record_len; i++) {
            unsigned char ch = record[i];

                    if (isprint(ch))
                        putchar(ch);
                    else if (ch == I_FM)
                    {
                        field++;
                       printf("\nField %02d: ", field);
                    }
                    else
                        printf("\n%02x\n", ch);
                }
                putchar('\n');
            }

            ic_close(&file_id, &code);
            if (code != 0)
                fprintf(stderr, "Failed to close VOC, code = %d\n", code);
        }
}
ic_quit(&code);
 

This program prints out something like this if the connection is created successfully:

Open of VOC returned status = 18
Read of record returned status 0
Size of record = 12
Record contents:
Field 01: SQLV
Field 02: COMPUTE

Getting started

To get started, you need to set up a PHP development environment. First, download PHP 5 from the PHP site and then download and install the following packages:

After these packages have been built and installed successfully, you're ready to develop U2 PDO driver.

Suppose you install PHP source code under directory $PHP_DIR. You can use shell script $PHP_DIR/ext/ext_skel to generate skeleton code for U2 PDO driver. Go to directory $PHP_DIR/ext and run "./ext_skel --extname=pdo_u2". Directory pdo_u2 is created along with several other files, including config.m4, and pdo_u2.c, among others. Modify config.m4 to add testing code for InterCall installation and U2 PDO driver presence. Also add more source files required by the U2 PDO driver.

Back to top

 


 

Fill in InterCall accessing code

1. Register U2 driver

U2 PDO driver must be registered through standard PHP extension function PHP_MINIT_FUNCTION. This is accomplished by calling the php_pdo_register_driver() function, passing a pointer to a structure of type pdo_driver_t. The pdo_driver_t pdo_u2_driver contains a header that is generated using the PDO_DRIVER_HEADER(u2) macro and pdo_u2_handle_factory() function pointer.

pdo_driver_t pdo_u2_driver = {
        PDO_DRIVER_HEADER(u2),
        pdo_u2_handle_factory
};

 

The pdo_u2_handle_factory() function is discussed later.

PHP_MINIT_FUNCTION(pdo_u2)
{
    ...
        if (FAILURE == php_pdo_register_driver(&pdo_u2_driver)) {
                return FAILURE;
        }
    ...
        return SUCCESS;
}

 The standard PHP extension function PHP_MSHUTDOWN_FUNCTION is used to unregister your driver from the PDO layer. This is done by calling the php_pdo_unregister_driver() function, passing the same pdo_u2_driver structure that was passed in the init function above.

PHP_MSHUTDOWN_FUNCTION(pdo_u2)
{   ...
        php_pdo_unregister_driver(&pdo_u2_driver);
    ...
        return SUCCESS;
}

 

2. U2 database handle factory

The database handle factory is called by PDO to create a database handle. For example, when PHP executes following statement from the PHP script:

$dsn = 'u2: dbtype=ud;host=my_host;acct=demo';
new PDO($dsn, $user, $password);

The database handle factory is called to make an InterCall connection to UniData server running on host my_host, and to log on to account demo.

Let's take a look at this factory:

static int pdo_u2_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)

 

First, you need to extract data source information from the database handle and initialize a U2 login strcucture:

struct pdo_data_src_parser vars[] = {
    { "appname",            "PHP U2 Driver",        0 },
    { "host",               "127.0.0.1",            0 },
    { "dbtype",             NULL,                   0 },
    { "secure",             NULL,                   0 },
    { "acct",               NULL,                   0 },
};

php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, 5);

 

Function php_pdo_parse_data_source() parses the input data source and stores respective fields into the array vars. Using the example above, vars would have following fields:

{ 
    { "appname",            "PHP U2 Driver",        0 },
    { "host",               "my_host",              0 },
    { "dbtype",             "ud",                   0 },
    { "secure",             NULL,                   0 },
    { "acct",               "demo",                 0 },
}

 

Use the following function to initialize a U2 login structure:

 

Function to set U2 login structure

 

void setdblogin(LOGINREC *login, pdo_dbh_t *dbh, pdo_data_src_parser vars[])
{
        if (dbh->username) {
                DBsetuser(login, dbh->username);
        }
        if (dbh->password) {
                DBsetpwd(login, dbh->password);
        }


        DBsetapp(login, vars[0].optval);
        DBsetserver(login, vars[1].optval);
        DBsetdbtype(login, vars[2].optval);
        DBsetsecure(login, vars[3].optval);
        DBsetaccount(login, vars[4].optval);


        return;
}

 

Next, call dbopen(pdo_u2_db_handle *H) to make a connection to the specified U2 server and store the session id ID in a U2SESSION structure using one of following functions: ic_opensession, ic_universe_session, or ic_unidata_session.

 

Make U2 connection

 

U2SESSION *dbopen(pdo_u2_db_handle *H)
{
        ...

        if (login->dbtype == NULL)
                session_id = ic_opensession(login->svr, login->usr, login->pwd,
login->acct, &code, NULL);
        else if (!strcasecmp(login->dbtype, "uv") )
                session_id = ic_universe_session(login->svr, login->usr, 
login->pwd, login->acct, &code, NULL);
        else
                session_id = ic_unidata_session(login->svr, login->usr, 
login->pwd, login->acct, &code, NULL, "");

        ...
        sess = (U2SESSION *)emalloc(sizeof(U2SESSION));
        sess->session_id = session_id;

        return sess;
}

 

If the session was created successfully, the database handle should be filled with the U2 driver method table and U2 driver data along with the connection:

dbh->methods = &u2_dbh_methods;
dbh->driver_data = H;

 

3. U2 driver method table

For each U2 database handle, you must install a driver method table. A U2 driver method table is a structure of type pdo_dbh_methods:

 

U2 driver method table

 

static struct pdo_dbh_methods u2_dbh_methods = {
        u2_handle_closer,
        u2_handle_preparer,
        u2_handle_doer,
        u2_handle_quoter,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL, /* last insert */
        u2_fetch_error, /* fetch error */
        NULL, /* get attr */
        NULL, /* check aliveness */
};

 

Right now, we define the following driver methods:

  • u2_handle_closer

    This function is called by PDO to close a U2 database connection. It calls dbclose(), which in turn calls InterCall ic_quit() to close the connection.

  • u2_handle_preparer

    This function is called by PDO in response to PDO::query() and PDO::prepare() calls from the PHP script. It's essentially the constructor for a pdo_stmt_t object preparing the raw statement and statement options and storing them in the statement object.

    One important responsibility of this function is to process the statement parameters. The following statements are used to achieve this:



    U2 prepare function
    int u2_prepare(pdo_u2_stmt *S, const char *sql, long sql_len)
    {
        stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
        ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len TSRMLS_CC);
        ...
    
        ret = u2_prepare(S, sql, sql_len);
        ...
    }
    

    Function u2_prepare() determines what kind of command the input is, puts its parameters into a u2_cmd_param structure and stores bound parameters in a pdo_u2_bound_param structure. Presently, u2_prepare() recognizes following commands:

    • GETMARKS: get current mark values and NULL value
    • READ filename recordid: read a record from a U2 file
    • CALL subname parameterlist: call a U2 Basic subroutine

    When u2_prepare() returns, the pdo_u2_stmt object S should have enough information about the statement. Pdo_u2_stmt is defined as follows:



    U2 statement structure
    typedef struct {
            pdo_u2_db_handle *H;
            int prepared;
            int cmdtype;    /* specify the command type */
    
            int n_params;   /* number of parameters */
            u2_cmd_param *params;   /* structure to store parameters */
    
    
            FILEID  *fileid;
            char    *record;
            long    rec_len;
    
            int n_bound_params;     /* number of bound paramters */
            pdo_u2_bound_param *bound_params; /* structure stores bound parameters */
    
            int ncols;
            pdo_u2_col *cols;
    
            pdo_u2_colval *rows;
            int nrows;
    
            int current;
    
            pdo_u2_err err;
    } pdo_u2_stmt;
    

    U2_prepare() also installs the U2 statement handling method table in the prepared statement object.

  • u2_handle_doer

    This function is called by PDO to execute a raw U2 statement. In the current implementation, this function creates a temporary pdo_stmt_t object, prepares the statement, and executes the statement.

  • u2_handle_quoter

    This function is called in response to a call to PDO::quote() from the PHP script. It turns an unquoted string into a quoted string.

  • u2_fetch_error

    This function is called in response to a call to PDO::errorInfo() from the PHP script. Essentially, this function composes a human-readable message string from the last error that was triggered. The message is in this format:

    SQLSTATE[a sql code] u2_database_message  (error code u2_database_error_code) 
    [statement that triggered the error]
    

4. U2 statement handling method table

For each U2 statement, you must assign a statement method table. A U2 statement table is a structure of type pdo_stmt_methods:

 

U2 statement table

 

struct pdo_stmt_methods u2_stmt_methods = {
        pdo_u2_stmt_dtor,
        pdo_u2_stmt_execute,
        pdo_u2_stmt_fetch,
        pdo_u2_stmt_describe,
        pdo_u2_stmt_get_col,
        pdo_u2_stmt_param_hook,
        NULL, /* set attr */
        NULL, /* get attr */
        NULL, /* meta */
};

 

Define following statement methods:

  • pdo_u2_stmt_dtor

    This function is called by PDO to destroy a previously constructed statement object.

  • pdo_u2_stmt_execute

    This function is called by PDO to execute the prepared U2 statement in the passed statement object. It calls dbcmd() to actually perform the specified command, and stores all data in pdo_u2_colval in the structure of pdo_u2_stmt.

    dbcmd() is actually the dispatcher for U2 commands:



    Function dbcmd()
    Int dbcmd(pdo_u2_stmt *S, U2SESSION *link, char *strquery, int strlen)
    {
            int ret = 0;
            switch(S->cmdtype) {
            case U2_CMD_GETMARKS:
                    ret = dbcmd_getmarks(S);
                    break;
            case U2_CMD_READ:
                    ret = dbcmd_read(S, link, strquery, strlen);
                    break;
            case U2_CMD_CALL:
                    ret = dbcmd_call(S, link, strquery, strlen);
                    break;
            default:
                    return -1;
            }
    
            return ret;
    }
    

    Function dbcmd_getmarks() retrieves U2 marks and stores them in the record member of the statement object.

    Function dbcmd_read() opens a U2 file, reads a record, and stores it in the statement object:



    Implementation of read command
    int
    dbcmd_read(pdo_u2_stmt *S, U2SESSION *link, char *strquery, int strlen)
    {
        ...
        /* first filename */
        filename = get_param_value(S, 0, &file_len);
    
        /* then record id */
        recordid = get_param_value(S, 1, &id_len);
    
    
        dict_flag = IK_DATA;
    
        ic_open(&file_id, &dict_flag, filename, &file_len, &status_func, &code);
        ...
        ic_read(&file_id, &lock, recordid, &id_len, record,
                        &max_rec_size, &record_len, &status_func, &code);
    ...
    }
    

    For example, the following statements in PHP script would retrieve the "COMPUTE" record from the "VOC" file in the account on the server that $dsn specifies:

    $dbh = new u2dbh($dsn, $user, $pwd);
    
    $stmt = $dbh->prepare("READ VOC COMPUTE");
    $stmt->execute();
    

    Function dbcmd_call() calls to a U2 Basic subroutine using InterCall method ic_subcall().



    Implementation of call command
    int
    dbcmd_call(pdo_u2_stmt *S, U2SESSION *link, char *strquery, int strlen)
    {
        ...
        /* get call parameters */
        /* first the subroutine name */
        subname = get_param_value(S, 0, &subname_len);
        /* then arguments */
        args[0].text = get_param_value(S, 1, &args[0].len);
        args[1].text = get_param_value(S, 2, &args[1].len);
        args[2].len = 0;
        args[3].len = 0;
    
    
        ic_subcall(subname, &subname_len, &code, &numargs, &args[0], 
            &args[1], &args[2], &args[3]);
    
        /* args[2] and args[3] will have the return values */
        ...
    }
    

    In PHP script, the following statements can be used to call a U2 subroutine:



    Example to call subroutine MYSUB
    $stmt = $dbh->prepare("CALL MYSUB :code :params :outdata :outcode");
    $stmt->bindParam(':code', $xcode);
    $stmt->bindParam(':params', $xparams);
    $stmt->bindParam(':outdata', $outdata, PDO::PARAM_STR|PDO:
         :PARAM_INPUT_OUTPUT, 102400);
    $stmt->bindParam(':outcode', $outcode, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 12);
    $xcode = 14;
    $xparams = $rec;
    $outdata="";
    $outcode="";
    $stmt->execute();
    
  • pdo_u2_stmt_fetch

    This function is called by PDO to retrieve a row from a previously executed statement object. The data is stored in the driver_data member of pdo_stmt_t object.

  • pdo_u2_stmt_describe

    This function is called by PDO to query meta information about a particular column. In this implementation, we treat all columns as string type.

  • pdo_u2_stmt_get_col

    This function is called by PDO to get data for the specified column in the current row. It returns the resultant data and the length of the data.



    Get data from statement handle
    static int pdo_u2_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
             unsigned long *len, int *caller_frees TSRMLS_DC)
    {
            pdo_u2_stmt *S = (pdo_u2_stmt*)stmt->driver_data;
            pdo_u2_colval *val = &S->rows[S->current * S->ncols + colno];
    
            *ptr = val->data;
            *len = val->len;
            return 1;
    }
    

    Pointer ptr and len should have the data and the length of the data, respectively.

  • pdo_u2_stmt_param_hook

    This function is called by PDO to handle parameter hooking. Depending on the event type, this function handles tasks such as binding allocation, binding cleanup, pre-execution action, and post-execution action.

    Event PDO_PARAM_EVT_ALLOC occurs as part of PDOStatement::bindParam(), PDOStatement::bindValue() or as part of an implicit bind when calling PDOStatement::execute(). In this implementation, we treat all parameters as strings, and set their minimum sizes to 32KB. By calling to pdo_u2_bingParameter(), the parameter information is updated in the bound parameter structure in the statement object.



    Implementation of binding parameters
    static int pdo_u2_bindParameter(pdo_u2_stmt *S, int paramno, const char *name, 
        long namelen, int paramtype, int ctype, int u2type, int precision, 
        int scale, pdo_u2_param *param, int len, int *retlen)
    {
            pdo_u2_bound_param *bp;
            if (paramno == -1)
                    paramno = pdo_u2_findParamNo(S, name, namelen);
    
            if (paramno == -1)
                    return -1;
    
            if (paramno >= S->n_bound_params)
                    return -1;
    
            bp = &S->bound_params[paramno];
            bp->paramtype = paramtype;
            bp->ctype = ctype;
            bp->u2type = u2type;
            bp->precision = precision;
            bp->scale = scale;
            bp->param = param;
            bp->len = len;
    
            return 0;
    }
    

    Event PDO_PARAM_EXEC_PRE is called once for each parameter immediately before calling pdo_u2_stmt_execute. This function adjusts the buffer for the parameter, and copies the parameter value to that buffer.

    Event PDO_PARAM_EXEC_POST is called once for each parameter immediately after calling pdo_u2_stmt_execute. This function copies the value to the parameter if the parameter is an output.

Back to top

 


 Compile PHP

Now it's time to compile PHP to include U2 PDO driver. Go to $PHP_DIR, and run the following commands:

  1. ./buildconf
  2. ./configure -prefix=$myprefix -with-pdo_u2 -with-libxml-dir=$myprefix
  3. make

where $myprefix should point to where the downloaded packages are installed.

This creates the PHP CLI executable $PHP_DIR/sapi/cli/php.

Back to top

 


Test U2 PDO driver

Under the pdo_u2 extension directory, there's a test file that checks whether the U2 PDO driver has been built successfully. If the U2 PDO driver has been built in PHP, the output of "php pdo_u2_extension_directory/tests/001.phpt" should be: 

Output of 001.phpt

 

--TEST--
Check for pdo_u2 presence
--SKIPIF--
--FILE--
pdo_u2 extension is available--EXPECT--
pdo_u2 extension is available

 

Back to top

 


More examples

Now we are ready to do more testing. First, let's define a PHP class for U2 marks. In this class, a private array member $mkarray is defined. The class constructor assigns marks to this array.

 

U2 mark class u2mark.cls

 

<?php
class u2marks {
        . . .
        private $mkarray;
        . . .

      /* the marks should be separate by a space */
        public function __construct($str) {
                $ary = explode(" ", $str);

                $this->mkarray = $ary;
                . . .
        }

        public function getMark($nm) {
                return $this->mkarray[$nm];
        }

        public function getMaxMarkNum() {
                return 4;
        }
}
?>

 

Another class used in the following examples is u2dbh. This class is used to make connection to U2 server and to compose U2 marks. The class constructor has three parameters: data source name, user name, and password to the user name.

 

U2 database handle class u2dbh.cls

 

<?php

require "u2marks.cls";

class u2dbh {
        private $dbh;
        private $marks;

        public function __construct($dsn, $user, $password) {
                $this->marks = null;

                try {
                   $this->dbh = new PDO($dsn, $user, $password);
                   $stmt = $this->dbh->prepare("GETMARKS");
                   if ($stmt->execute()) {
                        while ($row = $stmt->fetch()) {
                                $this->marks = new u2marks($row[0]);
                        }

                   } else {
                        echo "Failed to execute GETMARKS\n";
                   }

                } catch (PDOException $e) {
                   $this->dbh = null;
                   $this->marks = null;
                   echo 'Connection failed: ' . $e->getMessage();
                }
        }

        public function prepare($str) {
                return $this->dbh->prepare($str);
        }

       . . .
}
?>

 

Also, a public member function prepare() is defined in the u2dbh class. This function is used to prepare a U2 command for execution.

The first example tests the U2 connection using the PDO driver and prints out the U2 marks.

 

U2 connection test script conn.php

 

<?php
require "u2dbh.cls";

/* Connect to a U2 server using driver invocation */
$dsn = 'u2:dbtype=ud;host=myhost;acct=demo';
$user = 'my_user_id';
$pwd = 'my_password';

$dbh = new u2dbh($dsn, $user, $pwd);

print_r( $dbh->getMarks());

?>

 

This script tries to connect to UniData on host myhost and logs on to the demo account by default. Using the PHP command line interface, which is located under $PHP_DIR/sapi/cli, you can run this script:

$PHP_DIR/sapi/cli/php conn.php

 

The script produces the following output if the connection is created successfully:

 

Output of conn.php

 

u2marks Object
(
    [mkstr:private] => IM_char FM_char VM_char SM_char TM_char SQLNULL_char
    [mkarray:private] => Array
        (
            [0] => IM_char
            [1] => FM_char 
            [2] => VM_char 
            [3] => SM_char 
            [4] => TM_char
            [5] => SQLNULL_char
        )

    [mkarrayWithName:private] => Array
        (
            [IM] => IM_char 
            [FM] => FM_char 
            [VM] => VM_char 
            [SM] => SM_char 
            [TM] => TM_char
            [SQLNULL] => SQLNULL_char
        )

)

 

Otherwise, an error message is displayed on the screen. For example, if the password is wrong, the message would be:

Connection failed: SQLSTATE[HY000] Failed to connect to server (error code 80011)

 

Where where 80011 is a UniRPC error, meaning an incorrect user name or password was provided.

If the account doesn't exist, the following message would be shown:

Connection failed: SQLSTATE[HY000] Failed to connect to server (error code 39129)

 

Here, error code 39129 stands for the error "Account name given is not an account."

The following example reads the "COMPUTE" record from the VOC file.

 

Read U2 record script read.php

 

<?php
require "u2dbh.cls";

/* Connect to a U2 server using driver invocation */
$dsn = 'u2:dbtype=ud;host=myhost;acct=demo';
$user = 'my_user_id';
$pwd = 'my_password';

$dbh = new u2dbh($dsn, $user, $pwd);

$stmt = $dbh->prepare("READ VOC COMPUTE ");
if ($stmt->execute()) {
        while ($row = $stmt->fetch()) {
            print_r($row);
        }
} else {
        echo "Failed to execute. Error message:";
        echo $dbh->errorInfo();
        echo "\n";

}
?>

 

The output of command "$PHP_DIR/sapi/cli/php read.php" would look like this:

 

Output of read.php

 

Array
(
    [F1] => SQLV VM_char COMPUTE
    [0] => SQLV VM_char COMPUTE
)

 

It shows that COMPUTE is an SQL verb.

Back to top

 


Conclusion

In this article, we have covered how you should write a PHP PDO driver for U2 using the U2 InterCall APIs. With this driver, your PHP applications can easily access U2 data. In the second part of this series, we'll explore the usage of this driver thru a Web application as an example.

Back to top

 


Special thanks

Special thanks to technical reviewers: Shelley Thompson and Helen Beylkin.


Downloads

Description Name Size Download method
U2 PDO driver source code u2pdo_src.zip 17KB HTTP
Examples to use U2 PDO driver u2pdo_use.zip 2KB HTTP

 

Resources

Learn

 

 

Get products and technologies

 

About the author

Double Xia photo

Double Xia works for Rocket Software U2 in Denver, Colorado. He has more than ten years of experience in developing U2 data servers. He covers an array of development areas, including locking mechanisms, XML, Web Services, and NLS. Most recently, he has focused on developing Eclipse-based tools for U2.

 

 

Document Actions