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