b96ae661a8b12bd1a256d4775535163c0a25dfed
[m6w6/pq-gateway] / lib / pq / Gateway / Table / Relations.php
1 <?php
2
3 namespace pq\Gateway\Table;
4
5 use \pq\Gateway\Table;
6
7 const RELATION_SQL = <<<SQL
8 select
9 cl1.relname as "foreignTable"
10 ,array(
11 select
12 attname
13 from pg_attribute,
14 generate_subscripts(conkey,1) index
15 where
16 attrelid = cl1.oid
17 and attnum = any(conkey)
18 and conkey[index] = attnum
19 order by
20 index
21 ) as "foreignColumns"
22 ,cl2.relname as "referencedTable"
23 ,array(
24 select
25 attname
26 from pg_attribute,
27 generate_subscripts(confkey,1) index
28 where
29 attrelid = cl2.oid
30 and attnum = any(confkey)
31 and confkey[index] = attnum
32 order by
33 index
34 ) as "referencedColumns"
35 from pg_constraint co
36 join pg_class cl1 on cl1.oid = co.conrelid
37 join pg_class cl2 on cl2.oid = co.confrelid
38 where
39 cl1.relname = \$1
40 and co.contype = 'f'
41 and co.confrelid != 0
42 SQL;
43
44 /**
45 * Foreign key list
46 */
47 class Relations implements \Countable, \IteratorAggregate
48 {
49 /**
50 * @var array
51 */
52 protected $references;
53
54 /**
55 * @param \pq\Gateway\Table $table
56 */
57 function __construct(Table $table) {
58 $cache = $table->getMetadataCache();
59 if (!($this->references = $cache->get("$table:relations"))) {
60 $table->getQueryExecutor()->execute(
61 new \pq\Query\Writer(RELATION_SQL, array($table->getName())),
62 function($result) use($table, $cache) {
63 $rel = $result->map([1,2], null, \pq\Result::FETCH_ASSOC);
64 foreach ($rel as $ref) {
65 foreach ($ref as $table => $key) {
66 $reference = new Reference($key);
67 $this->references[$table][$reference->name] = $reference;
68 }
69 }
70 $cache->set("$table:relations", $this->references);
71 }
72 );
73 }
74 }
75
76 function __isset($r) {
77 return isset($this->references[$r]);
78 }
79
80 function __get($r) {
81 return $this->references[$r];
82 }
83
84 function __set($r, $v) {
85 $this->references[$r] = $v;
86 }
87
88 function __unset($r){
89 unset($this->references[$r]);
90 }
91
92 /**
93 * Get a reference to a table
94 * @param string $table
95 * @param string $ref
96 * @return \pq\Gateway\Table\Reference
97 */
98 function getReference($table, $ref = null) {
99 if (isset($this->references[$table])) {
100 if (!strlen($ref)) {
101 return current($this->references[$table]);
102 }
103 if (isset($this->references[$table][$ref])) {
104 return $this->references[$table][$ref];
105 }
106 }
107 }
108
109 /**
110 * Implements \Countable
111 * @return int
112 */
113 function count() {
114 return array_sum(array_map("count", $this->references));
115 }
116
117 /**
118 * Implements \IteratorAggregate
119 * @return \ArrayIterator
120 */
121 function getIterator() {
122 return new \ArrayIterator($this->references);
123 }
124 }