Diffs
Net_Q4M/trunk/Net/Q4M/Connection/ResultSet.php
@@ -0,0 +1,104 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+class Net_Q4M_Connection_ResultSet
+{
+ private $_data;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->_data = false;
+ }
+
+ /**
+ * Set result records
+ *
+ * @access public
+ * @param array $data
+ */
+ public function setData($data)
+ {
+ if (is_array($data)) {
+ $this->_data = $data;
+ }
+ }
+
+ /**
+ * Add result record
+ *
+ * @access public
+ * @param array $data
+ */
+ public function addData($data)
+ {
+ if (!is_array($this->_data)) {
+ $this->_data = array();
+ }
+ $this->_data[] = $data;
+ }
+
+ /**
+ * fetch a record from result data
+ *
+ * @access public
+ * @return array
+ */
+ public function fetchRow()
+ {
+ if ($this->hasData()) {
+ return array_shift($this->_data);
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if object has any data
+ *
+ * @access public
+ * @return bool
+ */
+ public function hasData()
+ {
+ if ($this->_data) {
+ return true;
+ }
+ return false;
+ }
+}
+
+?>
Net_Q4M/trunk/Net/Q4M/Connection/MySQLi.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+require_once 'Net/Q4M/Connection/MySQL.php';
+
+class Net_Q4M_Connection_MySQLi extends Net_Q4M_Connection_MySQL
+{
+ /**
+ * Connect to MySQL server
+ *
+ * @access public
+ * @param mixed $dsn DSN string or parsed DSN array
+ * @return Net_Q4M_Connection_MySQLi
+ * @throws Net_Q4M_Exception
+ */
+ public function connect($dsn)
+ {
+ if (!is_array($dsn)) {
+ $dsn = Net_Q4M_Connection::parseDSN($dsn);
+ }
+
+ $this->_dbh = new mysqli($dsn['host'], $dsn['username'], $dsn['password'],
+ $dsn['database'], $dsn['port']);
+
+ if (mysqli_connect_errno()) {
+ throw new Net_Q4M_Exception('Connect failed: '. mysqli_connect_error(), mysqli_connect_errno());
+ }
+
+ return $this->_dbh;
+ }
+
+ /**
+ * Disconnect from MySQL server
+ *
+ * @access public
+ * @return bool
+ */
+ public function close()
+ {
+ return $this->_dbh->close();
+ }
+
+ /**
+ * Send a query
+ *
+ * @access public
+ * @param string $sql
+ * @param array $param
+ * @return Net_Q4M_Connection_ResultSet
+ * throws Net_Q4M_Exception
+ */
+ public function query($sql, $param = array())
+ {
+ $sql = $this->buildSqlString($sql, $param);
+ $result = $this->_dbh->query($sql);
+ if ($result === false) {
+ throw new Net_Q4M_Exception('query() error: '. $this->_dbh->error, $this->_dbh->errno);
+ } else if ($result === true) {
+ return $result;
+ }
+
+ $data = array();
+ while ($_data = $result->fetch_array(MYSQL_BOTH)) {
+ $data[] = $_data;
+ }
+ $result->close();
+
+ $resultSet = new Net_Q4M_Connection_ResultSet();
+ $resultSet->setData($data);
+ return $resultSet;
+ }
+
+ /**
+ * Escapes special characters in a string for use in a SQL statement
+ *
+ * @access protected
+ * @param string $str
+ * @return string Returns the escaped string
+ */
+ protected function escape($str)
+ {
+ if (is_numeric($str)) {
+ return $str;
+ }
+ return "'". $this->_dbh->real_escape_string($str) ."'";
+ }
+}
+
+?>
Net_Q4M/trunk/Net/Q4M/Connection/MySQL.php
@@ -0,0 +1,150 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+require_once 'Net/Q4M/Connection.php';
+require_once 'Net/Q4M/Connection/ResultSet.php';
+require_once 'Net/Q4M/Exception.php';
+
+class Net_Q4M_Connection_MySQL extends Net_Q4M_Connection
+{
+ /**
+ * Connect to MySQL server
+ *
+ * @access public
+ * @param mixed $dsn DSN string or parsed DSN array
+ * @return Net_Q4M_Connection_MySQL
+ * @throws Net_Q4M_Exception
+ */
+ public function connect($dsn)
+ {
+ if (!is_array($dsn)) {
+ $dsn = Net_Q4M_Connection::parseDSN($dsn);
+ }
+
+ $_host = $dsn['host'] .':'. $dsn['port'];
+ $this->_dbh = mysql_connect($_host, $dsn['username'], $dsn['password']);
+ if ($this->_dbh === false) {
+ throw new Net_Q4M_Exception('Connect failed: '. mysql_error(), mysql_errno());
+ }
+ if (!mysql_select_db($dsn['database'], $this->_dbh)) {
+ throw new Net_Q4M_Exception('Connect failed: '. mysql_error(), mysql_errno());
+ }
+
+ return $this->_dbh;
+ }
+
+ /**
+ * Disconnect from MySQL server
+ *
+ * @access public
+ * @return bool
+ */
+ public function close()
+ {
+ return mysql_close($this->_dbh);
+ }
+
+ /**
+ * Send a query
+ *
+ * @access public
+ * @param string $sql
+ * @param array $param
+ * @return Net_Q4M_Connection_ResultSet
+ * throws Net_Q4M_Exception
+ */
+ public function query($sql, $param = array())
+ {
+ $sql = $this->buildSqlString($sql, $param);
+ $result = mysql_query($sql, $this->_dbh);
+ if ($result === false) {
+ throw new Net_Q4M_Exception('query() error: '. mysql_error(), mysql_errno());
+ } else if ($result === true) {
+ return $result;
+ }
+
+ $data = array();
+ while ($_data = mysql_fetch_array($result, MYSQL_BOTH)) {
+ $data[] = $_data;
+ }
+ mysql_free_result($result);
+
+ $resultSet = new Net_Q4M_Connection_ResultSet();
+ $resultSet->setData($data);
+ return $resultSet;
+ }
+
+ /**
+ * Build sql string (binds a vale to a parameter)
+ *
+ * @access protected
+ * @param string $sql
+ * @param array $param
+ * @return string
+ */
+ protected function buildSqlString($sql, $param = array())
+ {
+ while (($pos = strpos($sql, '?')) !== false) {
+ $_value = array_shift($param);
+ if ($_value === null) break;
+
+ $_value = $this->escape($_value);
+ $_left = substr($sql, 0, $pos);
+ $_right = ($pos < strlen($sql))? substr($sql, $pos+1) : '';
+
+ $sql = $_left. $_value .$_right;
+ }
+
+ $this->debug('buildQueryString(): '. $sql);
+ return $sql;
+ }
+
+ /**
+ * Escapes special characters in a string for use in a SQL statement
+ *
+ * @access protected
+ * @param string $str
+ * @return string Returns the escaped string
+ */
+ protected function escape($str)
+ {
+ if (is_numeric($str)) {
+ return $str;
+ }
+ return "'". mysql_real_escape_string($str, $this->_dbh) ."'";
+ }
+}
+
+?>
Net_Q4M/trunk/Net/Q4M/Connection/PdoMySQL.php
@@ -0,0 +1,127 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+require_once 'Net/Q4M/Connection.php';
+require_once 'Net/Q4M/Connection/ResultSet.php';
+require_once 'Net/Q4M/Exception.php';
+
+class Net_Q4M_Connection_PdoMySQL extends Net_Q4M_Connection
+{
+ /**
+ * Connect to MySQL server
+ *
+ * @access public
+ * @param mixed $dsn DSN string or parsed DSN array
+ * @return Net_Q4M_Connection_PdoMySQL
+ * @throws Net_Q4M_Exception
+ */
+ public function connect($dsn)
+ {
+ if (!is_array($dsn)) {
+ $dsn = Net_Q4M_Connection::parseDSN($dsn);
+ }
+ $pdo_dsn = sprintf("mysql:host=%s;port=%d;dbname=%s",
+ $dsn['host'], $dsn['port'], $dsn['database']);
+
+ try {
+ $this->_dbh = new PDO($pdo_dsn, $dsn['username'], $dsn['password']);
+ $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+ } catch (PDOException $e) {
+ throw new Net_Q4M_Exception('Connect failed: '. $e->getMessage());
+ }
+
+ return $this->_dbh;
+ }
+
+ /**
+ * Disconnect from MySQL server
+ *
+ * @access public
+ * @return bool
+ */
+ public function close()
+ {
+ $this->_dbh = null;
+ return true;
+ }
+
+ /**
+ * Send a query
+ *
+ * @access public
+ * @param string $sql
+ * @param array $param
+ * @return Net_Q4M_Connection_ResultSet
+ * throws Net_Q4M_Exception
+ */
+ public function query($sql, $param = array())
+ {
+ try {
+ $sth = $this->_dbh->prepare($sql);
+ if ($param) {
+ $sth->execute($param);
+ } else {
+ $sth->execute();
+ }
+ if (!$this->isSelectQuery($sql)) {
+ return true;
+ }
+ } catch (Exception $e) {
+ throw new Net_Q4M_Exception('query() error: '. $e->getMessage());
+ }
+
+ $data = $sth->fetchAll(PDO::FETCH_BOTH);
+ $resultSet = new Net_Q4M_Connection_ResultSet();
+ $resultSet->setData($data);
+ return $resultSet;
+ }
+
+ /**
+ * Returns true if SELECT, SHOW, EXPLAIN or DESCRIBE query string
+ *
+ * @access protected
+ * @param string $sql
+ * @return bool
+ */
+ protected function isSelectQuery($sql)
+ {
+ if (preg_match('/^\s*(select|explain|show|describe)/i', $sql)) {
+ return true;
+ }
+ return false;
+ }
+}
+
+?>
Net_Q4M/trunk/Net/Q4M/Exception.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+class Net_Q4M_Exception extends Exception
+{
+}
+
+?>
Net_Q4M/trunk/Net/Q4M/Connection.php
@@ -0,0 +1,194 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+class Net_Q4M_Connection
+{
+ protected $_dbh;
+ protected $_debug;
+
+ /**
+ * Construct database connection object
+ *
+ * @access public
+ * @param string $dsn
+ */
+ public function __construct()
+ {
+ $this->_dbh = null;
+ $this->_debug = true;
+ }
+
+ /**
+ * Connect to database
+ *
+ * @access public
+ * @param mixed $dsn DSN string or parsed DSN array
+ * @return bool
+ */
+ public function connect($dsn)
+ {
+ return false;
+ }
+
+ /**
+ * Disconnect from MySQL server
+ *
+ * @access public
+ * @return bool
+ */
+ public function close()
+ {
+ return false;
+ }
+
+ /**
+ * Return database connection status
+ *
+ * @access public
+ * @return bool true if connected, false if not connected
+ */
+ public function isConnected()
+ {
+ return ($this->_dbh)? true : false;
+ }
+
+ /**
+ * Send a query
+ *
+ * @access public
+ * @param string $sql
+ * @param array $param
+ * @return Net_Q4M_Connection_ResultSet
+ */
+ public function query($sql, $param = array())
+ {
+ return false;
+ }
+
+ /**
+ * Switch debug mode
+ *
+ * @access public
+ * @param bool $debug
+ */
+ public function setDebug($debug)
+ {
+ $this->_debug = $debug;
+ }
+
+ /**
+ * Output debug message
+ *
+ * @access protected
+ * @param string $msg
+ */
+ protected function debug($msg)
+ {
+ if ($this->_debug) {
+ error_log($msg);
+ }
+ }
+
+
+ /**
+ * Create Net_Q4M_Connection Object, and connect to database
+ *
+ * @access public
+ * @param string $dsn DSN string
+ * @return Net_Q4M_Connection
+ */
+ public static function getConnection($dsn)
+ {
+ $conn = null;
+ $parsed_dsn = self::parseDSN($dsn);
+
+ switch ($parsed_dsn['phptype']) {
+ case 'mysql':
+ require_once 'Net/Q4M/Connection/MySQL.php';
+ $conn = new Net_Q4M_Connection_MySQL();
+ break;
+ case 'mysqli':
+ require_once 'Net/Q4M/Connection/MySQLi.php';
+ $conn = new Net_Q4M_Connection_MySQLi();
+ break;
+ case 'pdo_mysql':
+ require_once 'Net/Q4M/Connection/PdoMySQL.php';
+ $conn = new Net_Q4M_Connection_PdoMySQL();
+ break;
+ default:
+ $conn = new Net_Q4M_Connection();
+ }
+
+ return $conn;
+ }
+
+ /**
+ * Parse a DSN string (simplified implementation)
+ *
+ * The string format of DSN is only partly supported.
+ * (not support dbsyntax, protocol and options)
+ *
+ * @todo fully support DSN format
+ *
+ * @access private
+ * @param string $dsn
+ * @return array parsed data source value
+ */
+ protected static function parseDSN($dsn)
+ {
+ $parsed_dsn = array(
+ 'phptype' => '',
+ 'username' => '',
+ 'password' => '',
+ 'host' => '',
+ 'port' => 3306,
+ 'database' => ''
+ );
+
+ $pattern = '!^([a-z0-9_]+)://([^:@]+):?([^@]*)@([^/:]+):?(\d*)/([^\?\./\\\]+)!';
+ if (preg_match($pattern, $dsn, $matches)) {
+ $parsed_dsn['phptype'] = $matches[1];
+ $parsed_dsn['username'] = $matches[2];
+ $parsed_dsn['password'] = ($matches[3])? $matches[3] : $parsed_dsn['password'];
+ $parsed_dsn['host'] = $matches[4];
+ $parsed_dsn['port'] = ($matches[5])? $matches[5] : $parsed_dsn['port'];
+ $parsed_dsn['database'] = $matches[6];
+ }
+
+ return $parsed_dsn;
+ }
+}
+
+?>
Net_Q4M/trunk/Net/Q4M.php
@@ -0,0 +1,280 @@
+<?php
+/**
+ * Net_Q4M
+ *
+ * Q4M (Queue for MySQL)
+ * @link http://q4m.31tools.com/
+ *
+ * @category Net
+ * @package Net_Q4M
+ * @version 0.1.0
+ * @author castor <castor.4bit@gmail.com>
+ * @license http://opensource.org/licenses/mit-license.html
+ *
+ * The MIT License
+ * Copyright (c) 2008 castor <castor.4bit@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+require_once 'Net/Q4M/Connection.php';
+require_once 'Net/Q4M/Connection/ResultSet.php';
+
+class Net_Q4M
+{
+ private $_conn;
+ private $_dsn;
+
+ /**
+ * Construct a new Q4M object.
+ *
+ * @access public
+ * @param string $dsn PEAR::DB style DSN string (i.e.: mysql://user:pass@localhost:3306/database)
+ */
+ public function __construct($dsn)
+ {
+ $this->_dsn = $dsn;
+ $this->_conn = Net_Q4M_Connection::getConnection($dsn);
+ }
+
+ /**
+ * Establish connection to MySQL server
+ *
+ * @access public
+ * @return bool
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ public function connect()
+ {
+ if (!$this->_conn->isConnected()) {
+ $this->_conn->connect($this->_dsn);
+ }
+ return $this->_conn->isConnected();
+ }
+
+ /**
+ * Disconnect from MySQL server
+ *
+ * @access public
+ * @return bool
+ */
+ public function disconnect()
+ {
+ if ($this->_conn->isConnected()) {
+ return $this->_conn->close();
+ }
+ return true;
+ }
+
+ /**
+ * Returns an array contains the first queue
+ *
+ * <code>
+ * $queue = new Net_Q4M();
+ * $queue->connect('mysql://user:pass@localhost:3306/database');
+ *
+ * $row = $queue->dequeue('my_queue');
+ * //$row = $queue->dequeue('my_queue', 5); // set timeout to 5 seconds
+ * //$row = $queue->dequeue('my_queue', 'my_queue2', 'my_queue3', 10);
+ * if (process_row($row)) {
+ * $queue->abort();
+ * }
+ * $queue->end();
+ * $queue->disconnect();
+ * </code>
+ *
+ * @access public
+ * @param string $table_name1[$table_name2, $table_name3, ...]
+ * @param int $timeout
+ * @return array returns first queue row, or false if not available any data
+ * @throws Net_Q4M_Exception
+ */
+ public function dequeue()
+ {
+ $args = func_get_args();
+ $tables = $args;
+
+ if (func_num_args() == 0) {
+ throw new Net_Q4M_Exception('dequeue($table_name[, $table_name...][, $timeout]): argument error');
+ } else if (func_num_args() >= 2) {
+ array_pop($tables);
+ }
+
+ $index = $this->getTableIndex($args);
+ if (($index == 0) || ($index > count($tables))) {
+ return false;
+ }
+ return $this->receiveData($tables[$index - 1]);
+ }
+
+ /**
+ * Adds data to the queue
+ *
+ * @access public
+ * @param string $table
+ * @param array $values
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ public function enqueue($table, $values)
+ {
+ $sql_columns = '';
+ $sql_values = '';
+ $param = array();
+
+ foreach ($values as $key => $value) {
+ $sql_columns .= ($sql_columns)? ",$key": $key;
+ $sql_values .= ($sql_values)? ',?' : '?';
+ $param[] = $value;
+ }
+ $sql = 'INSERT INTO '. $table .'('
+ . $sql_columns
+ . ') VALUES ('
+ . $sql_values
+ . ')';
+
+ return $this->_conn->query($sql, $param);
+ }
+
+ /**
+ * Count items in the queue
+ *
+ * @access public
+ * @param string $table
+ * @return int
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ public function count($table)
+ {
+ $sql = 'SELECT count(*) FROM '. $table;
+
+ $result = $this->_conn->query($sql);
+ if ($result !== false) {
+ $data = $result->fetchRow();
+ if ($data !== false) {
+ return intval($data[0]);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return ithe index of the table.
+ *
+ * When any data becomes available, queue_wait function will
+ * return the index of the table. The tables are prioritized
+ * from left to right, i.e. if more than one table contains
+ * any messages, the index of the leftmost table is returned.
+ * If none of the table have any data available, 0 is returned.
+ *
+ * @access protected
+ * @param array $args
+ * @return int table index (return 0, if not available any data)
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ protected function getTableIndex($args)
+ {
+ $sql_cond = '';
+ for ($i=0; $i<count($args); ++$i) {
+ $sql_cond .= ($sql_cond)? ',?' : '?';
+ }
+ $sql = 'SELECT queue_wait('. $sql_cond .')';
+
+ $result = $this->_conn->query($sql, $args);
+ if ($data = $result->fetchRow()) {
+ return $data[0];
+ }
+ return 0;
+ }
+
+ /**
+ * Receive data
+ *
+ * only one row becomes ready at once
+ *
+ * @access protcted
+ * @param string $table table name
+ * @return array
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ protected function receiveData($table)
+ {
+ if (preg_match('/^([^:\s]+)/', trim($table), $matches)) {
+ $table = $matches[1];
+ } else {
+ throw new Net_Q4M_Exception('Invalid table name: '. $table);
+ }
+
+ $sql = 'SELECT * FROM '. $table;
+ $result = $this->_conn->query($sql);
+ return $result->fetchRow();
+ }
+
+ /**
+ * Remove owned-row from the table, and return to NON-OWNER mode
+ *
+ * @access public
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ public function end()
+ {
+ // always return 1
+ $this->_conn->query('SELECT queue_end()');
+ }
+
+ /**
+ * Returns owned-row to the table, and return to NON-OWNER mode
+ *
+ * @access public
+ * @return bool
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ public function abort()
+ {
+ // always return 1
+ $this->_conn->query('SELECT queue_abort()');
+ }
+
+ /**
+ * Returns queue status
+ *
+ * Returns parsed output of `SHOW ENGINE QUEUE STATUS`
+ *
+ * @access public
+ * @return array queue status
+ * @throws Net_Q4M_Exception Low-level errors will bubble up through this method.
+ */
+ public function status()
+ {
+ $sql = 'SHOW ENGINE QUEUE STATUS';
+ $result = $this->_conn->query($sql);
+
+ $status = array();
+ $lines = $result->fetchRow();
+ if ($lines) {
+ $lines = explode("\n", $lines[2]);
+ foreach ($lines as $line) {
+ if (preg_match('/^([^\s]+)\s+(\d+)$/', $line, $matches)) {
+ $status[$matches[1]] = $matches[2];
+ }
+ }
+ }
+ return $status;
+ }
+}
+?>