autoload; cache; tests;
authorMichael Wallner <mike@php.net>
Fri, 15 Mar 2013 08:16:37 +0000 (09:16 +0100)
committerMichael Wallner <mike@php.net>
Fri, 15 Mar 2013 08:16:37 +0000 (09:16 +0100)
lib/autoload.php [new file with mode: 0644]
lib/pq/Gateway/Table.php
lib/pq/Gateway/Table/CacheInterface.php [new file with mode: 0644]
lib/pq/Gateway/Table/Relations.php
lib/pq/Gateway/Table/StaticCache.php [new file with mode: 0644]
tests/lib/pq/Gateway/CellTest.php
tests/lib/pq/Gateway/RowTest.php
tests/lib/pq/Gateway/RowsetTest.php
tests/lib/pq/Gateway/TableTest.php
tests/setup.inc

diff --git a/lib/autoload.php b/lib/autoload.php
new file mode 100644 (file)
index 0000000..d7b0cd8
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+
+spl_autoload_register(function($c) {
+       if (substr($c, 0, 10) === "pq\\Gateway" || susbtr($c, 0, 8) === "pq\\Query") {
+               return include __DIR__ . "/" . strtr($c, "\\", "/") . ".php";
+       }
+});
index af84e7f5eb59ed5c0e59c054a48c86bcb6f52620..8fc85d7ad748ff68d816aa607afdf9fdfbc8cec1 100644 (file)
@@ -17,6 +17,11 @@ class Table
         */
        public static $defaultResolver;
        
         */
        public static $defaultResolver;
        
+       /**
+        * @var \pq\Gateway\Table\CacheInterface
+        */
+       public static $defaultMetadataCache;
+       
        /**
         * @var \pq\Connection
         */
        /**
         * @var \pq\Connection
         */
@@ -47,6 +52,11 @@ class Table
         */
        protected $relations;
        
         */
        protected $relations;
        
+       /**
+        * @var \pq\Gateway\Table\CacheInterface
+        */
+       protected $metadataCache;
+       
        /**
         * @param string $table
         * @return \pq\Gateway\Table
        /**
         * @param string $table
         * @return \pq\Gateway\Table
@@ -73,6 +83,22 @@ class Table
                $this->conn = $conn ?: static::$defaultConnection ?: new \pq\Connection;
        }
        
                $this->conn = $conn ?: static::$defaultConnection ?: new \pq\Connection;
        }
        
+       /**
+        * Get the complete PostgreSQL connection string
+        * @return string
+        */
+       function __toString() {
+               return sprintf("postgresql://%s:%s@%s:%d/%s?%s#%s",
+                       $this->conn->user,
+                       $this->conn->pass,
+                       $this->conn->host,
+                       $this->conn->port,
+                       $this->conn->db,
+                       $this->conn->options,
+                       $this->getName()
+               );
+       }
+       
        /**
         * Set the rowset prototype
         * @param mixed $rowset
        /**
         * Set the rowset prototype
         * @param mixed $rowset
@@ -133,6 +159,26 @@ class Table
                return $this->exec;
        }
        
                return $this->exec;
        }
        
+       /**
+        * Get the metadata cache
+        * @return \pq\Gateway\Table\CacheInterface
+        */
+       function getMetadataCache() {
+               if (!isset($this->metadatCache)) {
+                       $this->metadataCache = static::$defaultMetadataCache ?: new Table\StaticCache;
+               }
+               return $this->metadataCache;
+       }
+       
+       /**
+        * Set the metadata cache
+        * @param \pq\Gateway\Table\CacheInterface $cache
+        */
+       function setMetadataCache(Table\CacheInterface $cache) {
+               $this->metadataCache = $cache;
+               return $this;
+       }
+       
        /**
         * Get foreign key relations
         * @param string $to fkey
        /**
         * Get foreign key relations
         * @param string $to fkey
@@ -187,7 +233,6 @@ class Table
         * @return mixed
         */
        protected function execute(QueryWriter $query) {
         * @return mixed
         */
        protected function execute(QueryWriter $query) {
-               echo $query,"\n",json_encode($query->getParams()),"\n";
                return $this->getQueryExecutor()->execute($query, array($this, "onResult"));
        }
 
                return $this->getQueryExecutor()->execute($query, array($this, "onResult"));
        }
 
diff --git a/lib/pq/Gateway/Table/CacheInterface.php b/lib/pq/Gateway/Table/CacheInterface.php
new file mode 100644 (file)
index 0000000..c06b11b
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+
+namespace pq\Gateway\Table;
+
+interface CacheInterface
+{
+       /**
+        * Set an item
+        * @param string $key
+        * @param mixed $val
+        * @param int $ttl
+        * @return \pq\Gateway\Table\CacheInterface
+        */
+       function set($key, $val, $ttl = 0);
+       
+       /**
+        * Get an item
+        * @param string $key
+        * @param bool $exists
+        * @return mixed
+        */
+       function get($key, &$exists = null);
+       
+       /**
+        * Delete an item
+        * @param string $key
+        * @return \pq\Gateway\Table\CacheInterface
+        */
+       function del($key);
+}
index 0f946fa1154feca0dc0ac84be3a65b9f1caa3a73..128dca7ebb53aae950c8059bce4add4a1cd73859 100644 (file)
@@ -13,18 +13,18 @@ select
     ,att2.attname                                               as "referencedColumn"
 from
      pg_constraint co
     ,att2.attname                                               as "referencedColumn"
 from
      pg_constraint co
-    ,pg_class      cl2
     ,pg_class      cl1
     ,pg_class      cl1
-    ,pg_attribute  att2
+    ,pg_class      cl2
     ,pg_attribute  att1
     ,pg_attribute  att1
+    ,pg_attribute  att2
 where
        (       cl1.relname = \$1
        or      cl2.relname = \$1)
 and co.confrelid != 0
 where
        (       cl1.relname = \$1
        or      cl2.relname = \$1)
 and co.confrelid != 0
-and co.confrelid  = cl2.oid
 and co.conrelid   = cl1.oid
 and co.conrelid   = cl1.oid
-and co.confkey[1] = att2.attnum and cl2.oid = att2.attrelid
 and co.conkey[1]  = att1.attnum and cl1.oid = att1.attrelid
 and co.conkey[1]  = att1.attnum and cl1.oid = att1.attrelid
+and co.confrelid  = cl2.oid
+and co.confkey[1] = att2.attnum and cl2.oid = att2.attrelid
 order by 
         cl1.relname
        ,att1.attnum
 order by 
         cl1.relname
        ,att1.attnum
@@ -35,10 +35,13 @@ class Relations
        public $references;
        
        function __construct(Table $table) {
        public $references;
        
        function __construct(Table $table) {
-               // FIXME cache
-               $this->references = $table->getConnection()
-                       ->execParams(RELATION_SQL, array($table->getName()))
-                       ->map(array(0,1), array(2,3,4), \pq\Result::FETCH_OBJECT);
+               $cache = $table->getMetadataCache();
+               if (!($this->references = $cache->get("$table:references"))) {
+                       $this->references = $table->getConnection()
+                               ->execParams(RELATION_SQL, array($table->getName()))
+                               ->map(array(0,1), array(2,3,4), \pq\Result::FETCH_OBJECT);
+                       $cache->set("$table:references", $this->references);
+               }
        }
        
        function __isset($r) {
        }
        
        function __isset($r) {
diff --git a/lib/pq/Gateway/Table/StaticCache.php b/lib/pq/Gateway/Table/StaticCache.php
new file mode 100644 (file)
index 0000000..7f31346
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+namespace pq\Gateway\Table;
+
+class StaticCache implements CacheInterface
+{
+       protected static $cache = array();
+       
+       /**
+        * @inheritdoc
+        * @param string $key
+        * @param bool $exists
+        * @return mixed
+        */
+       function get($key, &$exists = null) {
+               if (($exists = array_key_exists($key, static::$cache))) {
+                       list($ttl, $data) = static::$cache[$key];
+                       if ($ttl && $ttl < time()) {
+                               unset(static::$cache[$key]);
+                               $exists = false;
+                               return null;
+                       }
+                       return $data;
+               }
+       }
+       
+       /**
+        * @inheritdoc
+        * @param string $key
+        * @param mixed $val
+        * @param int $ttl
+        * @return \pq\Gateway\Table\StaticCache
+        */
+       function set($key, $val, $ttl = 0) {
+               static::$cache[$key] = array(
+                       $ttl ? $ttl + time() : 0,
+                       $val
+               );
+               return $this;
+       }
+       
+       /**
+        * @inheritdoc
+        * @param string $key
+        * @return \pq\Gateway\Table\StaticCache
+        */
+       function del($key) {
+               unset(static::$cache[$key]);
+               return $this;
+       }
+}
index 0afd0e3f4f2207bf91690341d780e796094c55b6..d7a8fc624c414a4a1b92bf44bbc4fd5862459fd4 100644 (file)
@@ -17,19 +17,21 @@ class CellTest extends \PHPUnit_Framework_TestCase {
        protected $table;
 
        protected function setUp() {
        protected $table;
 
        protected function setUp() {
-               $this->conn = new \pq\Connection(PQ_DSN);
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_DATA);
-               $this->table = new Table(PQ_TEST_TABLE_NAME, $this->conn);
+               $this->conn = new \pq\Connection(PQ_TEST_DSN);
+               $this->conn->exec(PQ_TEST_TABLE_CREATE);
+               $this->conn->exec(PQ_TEST_REFTABLE_CREATE);
+               $this->conn->exec(PQ_TEST_DATA);
+               Table::$defaultConnection = $this->conn;
+               $this->table = new Table("test");
        }
 
        protected function tearDown() {
        }
 
        protected function tearDown() {
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
+               $this->conn->exec(PQ_TEST_REFTABLE_DROP);
+               $this->conn->exec(PQ_TEST_TABLE_DROP);
        }
 
        /**
        }
 
        /**
-        * This is very bad test…
+        * This is very bad test…
         */
        public function testBasic() {
                $row = $this->table->find(null, "id desc", 1)->current();
         */
        public function testBasic() {
                $row = $this->table->find(null, "id desc", 1)->current();
index 28d2728c006817ad09e59470d492ed8abf93d666..fc0809468ea0a7aa2f804de834263ab8c410e5ab 100644 (file)
@@ -17,16 +17,17 @@ class RowTest extends \PHPUnit_Framework_TestCase {
        protected $table;
 
        protected function setUp() {
        protected $table;
 
        protected function setUp() {
-               $this->conn = new \pq\Connection(PQ_DSN);
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_DATA);
-               
-               $this->table = new Table(PQ_TEST_TABLE_NAME, $this->conn);
+               $this->conn = new \pq\Connection(PQ_TEST_DSN);
+               $this->conn->exec(PQ_TEST_TABLE_CREATE);
+               $this->conn->exec(PQ_TEST_REFTABLE_CREATE);
+               $this->conn->exec(PQ_TEST_DATA);
+               Table::$defaultConnection = $this->conn;
+               $this->table = new Table("test");
        }
 
        protected function tearDown() {
        }
 
        protected function tearDown() {
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
+               $this->conn->exec(PQ_TEST_REFTABLE_DROP);
+               $this->conn->exec(PQ_TEST_TABLE_DROP);
        }
 
        function testBasic() {
        }
 
        function testBasic() {
index 7ef1a0eb21721a374ba36b41c59108197b08b387..48ac624574615cc366a655835c34cfc56350b72e 100644 (file)
@@ -17,16 +17,17 @@ class RowsetTest extends \PHPUnit_Framework_TestCase {
        protected $table;
 
        protected function setUp() {
        protected $table;
 
        protected function setUp() {
-               $this->conn = new \pq\Connection(PQ_DSN);
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_DATA);
-               
-               $this->table = new Table(PQ_TEST_TABLE_NAME, $this->conn);
+               $this->conn = new \pq\Connection(PQ_TEST_DSN);
+               $this->conn->exec(PQ_TEST_TABLE_CREATE);
+               $this->conn->exec(PQ_TEST_REFTABLE_CREATE);
+               $this->conn->exec(PQ_TEST_DATA);
+               Table::$defaultConnection = $this->conn;
+               $this->table = new Table("test");
        }
 
        protected function tearDown() {
        }
 
        protected function tearDown() {
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
+               $this->conn->exec(PQ_TEST_REFTABLE_DROP);
+               $this->conn->exec(PQ_TEST_TABLE_DROP);
        }
 
        public function test__invoke() {
        }
 
        public function test__invoke() {
index 65c93f717b483923d5bd87c935165ff528f5b8f2..a5fb56f6acb39cb3485b1d03b1ac14c53d4e284b 100644 (file)
@@ -17,21 +17,19 @@ class TableTest extends \PHPUnit_Framework_TestCase {
        protected $table;
 
        protected function setUp() {
        protected $table;
 
        protected function setUp() {
-               $this->conn = new \pq\Connection(PQ_DSN);
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
-               $this->conn->exec(PQ_TEST_CREATE_TABLE);
+               $this->conn = new \pq\Connection(PQ_TEST_DSN);
+               $this->conn->exec(PQ_TEST_TABLE_CREATE);
+               $this->conn->exec(PQ_TEST_REFTABLE_CREATE);
+               $this->conn->exec(PQ_TEST_DATA);
                Table::$defaultConnection = $this->conn;
                Table::$defaultConnection = $this->conn;
-               $this->table = new Table(PQ_TEST_TABLE_NAME);
+               $this->table = new Table("test");
        }
 
        protected function tearDown() {
        }
 
        protected function tearDown() {
-               $this->conn->exec(PQ_TEST_DROP_TABLE);
+               $this->conn->exec(PQ_TEST_REFTABLE_DROP);
+               $this->conn->exec(PQ_TEST_TABLE_DROP);
        }
        
        }
        
-       protected function createTestData() {
-               $this->conn->exec(PQ_TEST_CREATE_DATA);
-       }
-
        public function testSetRowsetPrototype() {
                $prop = new \ReflectionProperty("\\pq\\Gateway\\Table", "rowset");
                $prop->setAccessible(true);
        public function testSetRowsetPrototype() {
                $prop = new \ReflectionProperty("\\pq\\Gateway\\Table", "rowset");
                $prop->setAccessible(true);
@@ -48,7 +46,7 @@ class TableTest extends \PHPUnit_Framework_TestCase {
        }
 
        public function testGetName() {
        }
 
        public function testGetName() {
-               $this->assertSame(PQ_TEST_TABLE_NAME, $this->table->getName());
+               $this->assertSame("test", $this->table->getName());
        }
 
        public function testFind() {
        }
 
        public function testFind() {
index 798d4a4824ad8eba9213e97e64ab5b593cb5d645..ee9733c12bb975238d16c5044f0754498a8b471e 100644 (file)
@@ -1,27 +1,43 @@
 <?php
 
 <?php
 
-define("PQ_DSN", "");
-define("PQ_TEST_TABLE_NAME", "test");
-define("PQ_TEST_CREATE_TABLE", sprintf(
-<<<SQL
-       create table %s (
+const PQ_TEST_DSN = "";
+
+const PQ_TEST_TABLE_CREATE = <<<SQL
+       drop table if exists test cascade;
+       create table test (
                id serial primary key, 
                created timestamp, 
                counter int, 
                number decimal, 
                data text
        )
                id serial primary key, 
                created timestamp, 
                counter int, 
                number decimal, 
                data text
        )
-SQL
-       , PQ_TEST_TABLE_NAME));
-define("PQ_TEST_DROP_TABLE", sprintf("drop table if exists %s", PQ_TEST_TABLE_NAME));
-define("PQ_TEST_CREATE_DATA", sprintf(
-<<<SQL
-       insert into %1\$s values (default, 'yesterday', -1, -1.1, 'yesterday');
-       insert into %1\$s values (default, 'today', 0, 0, 'today');
-       insert into %1\$s values (default, 'tomorrow', 1, 1.1, 'tomorrow');
-SQL
-       , PQ_TEST_TABLE_NAME
-));
+SQL;
+
+const PQ_TEST_TABLE_DROP = <<<SQL
+       drop table if exists test cascade;
+SQL;
+
+const PQ_TEST_REFTABLE_CREATE = <<<SQL
+       drop table if exists reftest cascade;
+       create table reftest (
+               test_id integer not null references test on delete cascade,
+               another_test_id integer not null references test on delete cascade
+       );
+SQL;
+
+const PQ_TEST_REFTABLE_DROP = <<<SQL
+       drop table if exists reftest cascade;
+SQL;
+
+const PQ_TEST_DATA = <<<SQL
+       insert into test values (default, 'yesterday', -1, -1.1, 'yesterday');
+       insert into test values (default, 'today', 0, 0, 'today');
+       insert into test values (default, 'tomorrow', 1, 1.1, 'tomorrow');
+       
+       insert into reftest values (1,3);
+       insert into reftest values (2,2);
+       insert into reftest values (3,1);
+SQL;
 
 spl_autoload_register(function($c) {
        if (substr($c,0,3) == "pq\\") return require_once sprintf("%s/../lib/%s.php", __DIR__, strtr($c, "\\", "/"));
 
 spl_autoload_register(function($c) {
        if (substr($c,0,3) == "pq\\") return require_once sprintf("%s/../lib/%s.php", __DIR__, strtr($c, "\\", "/"));