`

How to connect to rare databases in PHP (informix, oracle, db2)

 
阅读更多

Recently I took part in integration project and faced interesting problem. PHP application that I deploy must communicate with Informix database for data selecte. This php application aims to corporate market, so its not a extraordinary case. I see that it may require connecto to Oracle or DB2 in near future.

 

Yes, PHP itself has wide choose of database connectors, which is a good option to have native database support. The only problem is that most of them are used so rare that are usualy not compiled in all modern Linux destributos. For example in Ubuntu server 12.04 there are five most pupular php5-sybase php5-interbase php5-mssql php5-mysql php5-pgsql.

 

Thinking of it, I found one interesting solution.

 

 

 

The right way

 

The right way seems to compile extention you need for PHP and live happilly. Yes it will work, but has some drawbacks I do not like:

 

  1. You have to make a build environment for PHP - which takes time
  2. Include in build all extension PHP already has - install all needed library in -dev versions
  3. Download SDK from database vendor, install it and tell PHP where to look for files - time consuming.
  4. Build PHP install it and manually add to apache, check and rebuild again to add missing extentions
  5. Keep upgrading PHP manually after security patched are out
  6. Document all work done, so somebody later can do this on another server to match your application specification

 

You see, it does not look so simple after analysis. So what is another way?

 

JDBC - Java DataBase Connectivity

 

Some years ago I was quite deep in Java world. One thing I like the best is that how Java works with databases though JDBC. You only need one *.jar file with database driver written by the vendor. This file is usually small in size and has no other dependency.

 

In my case, for Informix, I found ifxjdbc.jar, which is 800Kb in size and that was all I need.

 

I imagine next setup:

 

PHP  (calls---->) JAVA program (DB exchange)  ----->  PHP (receive results)

 

Java program will be a very simple program to get query on input, connect to database, execute the query and pass results to PHP.

 

Looks like not a right way, but has almost no negative side effects:

 

  1. Java is easy to install on every linux distribution, just type apt-get install java, or yum install java and you are done
  2. Any Java version will work, since task is very simple (openjdk, jdk, icetea, etc..)
  3. Java program can be distributed with your PHP application
  4. JDBC driver in sinlge .jar file and  as well, can be distributed with PHP application
  5. Simple to support

 

So why I love JSON?

 

Next step is communication with Java program. There is need to pass something and get something back.

First that comes to mind is to re-invent the wheel, like this:

 

java Program --query "query here" --db-server "server" etc

 

output result like this

 

Field1|Field2|Field3
 data1|data1|data1

 

That means parsing, parsing and catch unpredictable errors. Not good.

 

What PHP and Java can do well? Yes, its JSON serialization/deserialization. Lets use it, php will run external java program and pass json data on standard input. Java will do it's work and pass json on standard output, were PHP will catch it.

 

For PHP its simple json_encode/json_decode

 

For Java I used json-simple-1.1.1.jar library (20KB).

 

Below are sources that can give you an idea how it works.

 

PHP Source

 

// Put in classpath all needed librararies
$classpath = join(PATH_SEPARATOR, array(
   dirname(__FILE__).DIRECTORY_SEPARATOR.'.',
   dirname(__FILE__).DIRECTORY_SEPARATOR.'ifxjdbc.jar', // JDBC driver
   dirname(__FILE__).DIRECTORY_SEPARATOR.'json-simple-1.1.1.jar',
));
 
// Prepare command to run (SimpleSelect is java program name)
$cmd = sprintf("java -cp '%s' SimpleSelect", $classpath);
 
$descriptorspec = array(
   0 => array("pipe", "r"),
   1 => array("pipe", "w"),
   2 => array("file", "/tmp/error-output.txt", "a")
);
 
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
   // $pipes now looks like this:
   // 0 => writeable handle connected to child stdin
   // 1 => readable handle connected to child stdout
 
   // Send query to Java program
   $command = array(
      'dsn' => 'jdbc:informix-sqli://10.0.0.1:1526/database;username=xxx;password=yyyy',
      'query' => 'select * from table WHERE id = ?',
      'param' => array(1)
   );
   fwrite($pipes[0], json_encode($command));
   fclose($pipes[0]);
   $output = stream_get_contents($pipes[1]);
   fclose($pipes[1]);
   $return_value = proc_close($process);
 
   // Decode output
   $res = json_decode($output, true);
   if (!empty($res['error'])) throw new Exception($res['error']);
 
   return $res;

 

JAVA Source

 

To make it better, I would add passing JDBC driver name as a parameter as well as connection timeout. May be add support for INSERT, UPDATE, DELETE

 

import java.io.*;
import java.sql.*;
import java.util.*;
 
import org.json.simple.*;
 
public class SimpleSelect {
    public static Connection conn = null;
    public static JSONObject output;
 
    public static void main(String[] args) throws Exception {
        Statement  stmt = null;
 
        output = new JSONObject();
 
        // Decode jSON
        // http://code.google.com/p/json-simple/wiki/DecodingExamples
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        final JSONObject input = (JSONObject)JSONValue.parse(br.readLine());
        JSONArray param = (JSONArray)input.get("param");
 
        output.put("error", "");
 
        try {
            Class.forName("com.informix.jdbc.IfxDriver");
        } catch (Exception e) {
            SimpleSelect.fatal_error("FAILED: failed to load Informix JDBC driver.");
        }
 
        //  Connect though the thread to handle connection timeout
        Thread tc = new Thread(new Runnable() {
           public void run() {
                try {
                    SimpleSelect.conn = DriverManager.getConnection((String)input.get("dsn"));
                } catch (SQLException e) {
                    SimpleSelect.fatal_error("FAILED: failed to connect to Informix!");
                }
           }
        });
        tc.setDaemon(true);
        tc.start();
 
        // Wait 5 sec for connection
        for(int i = 0 ; i <= 500 ; i++) {
           if (conn != null) break;
           try {Thread.sleep(10);} catch(InterruptedException ex) {}
        }
        if (conn == null) {
            SimpleSelect.fatal_error("FAILED: timeout connect to Informix!");
        }
 
        try  {
               PreparedStatement pstmt = conn.prepareStatement((String)input.get("query"));
               pstmt.setQueryTimeout(10);
                for(int i = 0 ; i < param.size() ; i++)
                    pstmt.setString(i+1, (String)param.get(i));
 
                ResultSet rs = pstmt.executeQuery();
 
                // Get column name
                JSONArray jsColumn = new JSONArray();
                ResultSetMetaData rsmd = rs.getMetaData();
                for (int i = 0; i < rsmd.getColumnCount(); i++ ) {
                    jsColumn.add((String)rsmd.getColumnName(i+1));
                }
                output.put("column", jsColumn);
 
                // Get the data
                JSONArray jsData = new JSONArray();
                while(rs.next()) {
                    JSONArray jsRow = new JSONArray();
                    for (int i = 0; i < rsmd.getColumnCount(); i++ ) {
                        jsRow.add(rs.getString(i+1));
                    }
                    jsData.add(jsRow);
                }
                rs.close();
                pstmt.close();
                output.put("data", jsData);
 
        } catch (SQLException e) {
            SimpleSelect.fatal_error("FAILED: Fetch statement failed: " + e.getMessage());
        }
 
        try {
            conn.close();
        } catch (SQLException e) {
            SimpleSelect.fatal_error("FAILED: failed to close the connection!");
        }
        System.out.print(output);
    }
 
    static public void fatal_error(String str) {
        output.put("error", str);
        System.out.print(output);
        System.exit(0);
    }
 
}
分享到:
评论

相关推荐

    how-databases-work.pdf

    When it comes to relational databases, I can’t help thinking that something is missing. They’re used everywhere. There are many different databases: from the small and useful SQLite to the powerful ...

    The Cloud DBA-Oracle: Managing Oracle Database in the Cloud

    Learn how to define strategies for cloud adoption of your Oracle database landscape. Understand private cloud, public cloud, and hybrid cloud computing in order to successfully design and manage ...

    [Oracle] Expert Consolidation in Oracle Database 12c (英文版)

    Expert Consolidation in Oracle Database 12c is your key to reducing data management costs and increasing data center efficiency. Consolidation and cloud computing are converging trends sweeping the ...

    Beginning C# 2008 Databases From Novice to Professional

    A comprehensive tutorial on both SQL Server 2005 and ADO.NET 3.0, Beginning C# 2008 Databases explains and demonstrates how to create database objects and program against them in both T–SQL and C#....

    Beginning XML Databases_AppB_Oracle.zip

    总的来说,"Beginning XML Databases_AppB_Oracle.zip"提供的资源为我们提供了一个全面的学习平台,让我们能够深入了解XML在Oracle数据库中的应用,这对于开发者和数据库管理员来说是一份宝贵的参考资料。...

    Practical PHP 7, MySQL 8, and MariaDB Website Databases, Second Edition

    The PHP required is taught in context within each project so you can quickly learn how PHP integrates with MariaDB and MySQL to create powerful database-driven websites. Each project is fully ...

    Databases to Oracle Exadata

    Oracle Exadata是甲骨文公司推出的一款高性能、可扩展的数据库云服务器产品,它将数据库与计算、存储和网络资源紧密结合,旨在提供超出传统数据库架构的性能和效率。本篇文档提到了将数据库迁移到Oracle Exadata,...

    seven databases in seven weeks

    《Seven Databases in Seven Weeks》一书深入探讨了现代数据库设计与实现的多个方面,尤其聚焦于NoSQL运动中的七个数据库系统。通过一周学习一个数据库的模式,读者能够迅速掌握每个系统的特性和应用场景,从而在...

    Seven NoSQL Databases in a Week epub

    Seven NoSQL Databases in a Week 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    Pro Docker: Learn how to use Containers as a Service for development and

    In this fast-paced book on the Docker open standards platform for developing, packaging and running portable distributed applications, Deepak Vorhadiscusses how to build, ship and run applications on ...

    SQLDirect.v3.0.3.Full.Sources.For.Delphi.BCB

    It means, that access to SQLBase-databases needs SQLBase Client for Windows, to the databases on Oracle - Oracle SQL*Net, to the DB2 databases - Client Application Enabler, to the databases on SQL ...

    Oracle Database 12c Release 2 Multitenant

    Find out how to create databases, work with PDBs and CDBs, administer Oracle Net Services, and automate administrative tasks. Backup and recovery, security, and advanced multitenant options are ...

    Pro Oracle SQL

    , Karen Morton and her team help you master powerful aspects of Oracle SQL not found in competing databases. You’ll learn analytic functions, the MODEL clause, and advanced grouping syntax—...

    DB2 v11.1 DBA Certification Study Guide 2018 pdf

    Understand how to encrypt data in transit and at rest Who This Book Is For The IBM Db2 11.1 Certification Guide is an excellent choice for database administrators, architects, and application ...

    A Guide for Migrating From Oracle to MySQL

    With the rapid growth of MySQL in the database market, many corporations, government agencies, educational institutions, and others have begun to migrate away from their expensive and proprietary ...

Global site tag (gtag.js) - Google Analytics