danielebarchiesi@4
|
1 <?php
|
danielebarchiesi@4
|
2 /**
|
danielebarchiesi@4
|
3 * ARC2 RDF Store Table Manager
|
danielebarchiesi@4
|
4 *
|
danielebarchiesi@4
|
5 * @license http://arc.semsol.org/license
|
danielebarchiesi@4
|
6 * @author Benjamin Nowack
|
danielebarchiesi@4
|
7 * @version 2010-11-16
|
danielebarchiesi@4
|
8 *
|
danielebarchiesi@4
|
9 */
|
danielebarchiesi@4
|
10
|
danielebarchiesi@4
|
11 ARC2::inc('Store');
|
danielebarchiesi@4
|
12
|
danielebarchiesi@4
|
13 class ARC2_StoreTableManager extends ARC2_Store {
|
danielebarchiesi@4
|
14
|
danielebarchiesi@4
|
15 function __construct($a, &$caller) {
|
danielebarchiesi@4
|
16 parent::__construct($a, $caller);
|
danielebarchiesi@4
|
17 }
|
danielebarchiesi@4
|
18
|
danielebarchiesi@4
|
19 function __init() {/* db_con */
|
danielebarchiesi@4
|
20 parent::__init();
|
danielebarchiesi@4
|
21 $this->engine_type = $this->v('store_engine_type', 'MyISAM', $this->a);
|
danielebarchiesi@4
|
22 }
|
danielebarchiesi@4
|
23
|
danielebarchiesi@4
|
24 /* */
|
danielebarchiesi@4
|
25
|
danielebarchiesi@4
|
26 function getTableOptionsCode() {
|
danielebarchiesi@4
|
27 $v = $this->getDBVersion();
|
danielebarchiesi@4
|
28 $r = "";
|
danielebarchiesi@4
|
29 $r .= (($v < '04-01-00') && ($v >= '04-00-18')) ? 'ENGINE' : (($v >= '04-01-02') ? 'ENGINE' : 'TYPE');
|
danielebarchiesi@4
|
30 $r .= "=" . $this->engine_type;
|
danielebarchiesi@4
|
31 $r .= ($v >= '04-00-00') ? " CHARACTER SET utf8" : "";
|
danielebarchiesi@4
|
32 $r .= ($v >= '04-01-00') ? " COLLATE utf8_unicode_ci" : "";
|
danielebarchiesi@4
|
33 $r .= " DELAY_KEY_WRITE = 1";
|
danielebarchiesi@4
|
34 return $r;
|
danielebarchiesi@4
|
35 }
|
danielebarchiesi@4
|
36
|
danielebarchiesi@4
|
37 /* */
|
danielebarchiesi@4
|
38
|
danielebarchiesi@4
|
39 function createTables() {
|
danielebarchiesi@4
|
40 $con = $this->getDBCon();
|
danielebarchiesi@4
|
41 if(!$this->createTripleTable()) {
|
danielebarchiesi@4
|
42 return $this->addError('Could not create "triple" table (' . mysql_error($con) . ').');
|
danielebarchiesi@4
|
43 }
|
danielebarchiesi@4
|
44 if(!$this->createG2TTable()) {
|
danielebarchiesi@4
|
45 return $this->addError('Could not create "g2t" table (' . mysql_error($con) . ').');
|
danielebarchiesi@4
|
46 }
|
danielebarchiesi@4
|
47 if(!$this->createID2ValTable()) {
|
danielebarchiesi@4
|
48 return $this->addError('Could not create "id2val" table (' . mysql_error($con) . ').');
|
danielebarchiesi@4
|
49 }
|
danielebarchiesi@4
|
50 if(!$this->createS2ValTable()) {
|
danielebarchiesi@4
|
51 return $this->addError('Could not create "s2val" table (' . mysql_error($con) . ').');
|
danielebarchiesi@4
|
52 }
|
danielebarchiesi@4
|
53 if(!$this->createO2ValTable()) {
|
danielebarchiesi@4
|
54 return $this->addError('Could not create "o2val" table (' . mysql_error($con) . ').');
|
danielebarchiesi@4
|
55 }
|
danielebarchiesi@4
|
56 if(!$this->createSettingTable()) {
|
danielebarchiesi@4
|
57 return $this->addError('Could not create "setting" table (' . mysql_error($con) . ').');
|
danielebarchiesi@4
|
58 }
|
danielebarchiesi@4
|
59 return 1;
|
danielebarchiesi@4
|
60 }
|
danielebarchiesi@4
|
61
|
danielebarchiesi@4
|
62 /* */
|
danielebarchiesi@4
|
63
|
danielebarchiesi@4
|
64 function createTripleTable($suffix = 'triple') {
|
danielebarchiesi@4
|
65 /* keep in sync with merge def in StoreQueryHandler ! */
|
danielebarchiesi@4
|
66 $indexes = $this->v('store_indexes', array('sp (s,p)', 'os (o,s)', 'po (p,o)'), $this->a);
|
danielebarchiesi@4
|
67 $index_code = $indexes ? 'KEY ' . join(', KEY ', $indexes) . ', ' : '';
|
danielebarchiesi@4
|
68 $sql = "
|
danielebarchiesi@4
|
69 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . $suffix . " (
|
danielebarchiesi@4
|
70 t mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
71 s mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
72 p mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
73 o mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
74 o_lang_dt mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
75 o_comp char(35) NOT NULL, /* normalized value for ORDER BY operations */
|
danielebarchiesi@4
|
76 s_type tinyint(1) NOT NULL default 0, /* uri/bnode => 0/1 */
|
danielebarchiesi@4
|
77 o_type tinyint(1) NOT NULL default 0, /* uri/bnode/literal => 0/1/2 */
|
danielebarchiesi@4
|
78 misc tinyint(1) NOT NULL default 0, /* temporary flags */
|
danielebarchiesi@4
|
79 UNIQUE KEY (t), " . $index_code . " KEY (misc)
|
danielebarchiesi@4
|
80 ) ". $this->getTableOptionsCode() . "
|
danielebarchiesi@4
|
81 ";
|
danielebarchiesi@4
|
82 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
83 }
|
danielebarchiesi@4
|
84
|
danielebarchiesi@4
|
85 function extendTripleTableColumns($suffix = 'triple') {
|
danielebarchiesi@4
|
86 $sql = "
|
danielebarchiesi@4
|
87 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
|
danielebarchiesi@4
|
88 MODIFY t int(10) UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
89 MODIFY s int(10) UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
90 MODIFY p int(10) UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
91 MODIFY o int(10) UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
92 MODIFY o_lang_dt int(10) UNSIGNED NOT NULL
|
danielebarchiesi@4
|
93 ";
|
danielebarchiesi@4
|
94 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
95 }
|
danielebarchiesi@4
|
96
|
danielebarchiesi@4
|
97 /* */
|
danielebarchiesi@4
|
98
|
danielebarchiesi@4
|
99 function createG2TTable() {
|
danielebarchiesi@4
|
100 $sql = "
|
danielebarchiesi@4
|
101 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "g2t (
|
danielebarchiesi@4
|
102 g mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
103 t mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
104 UNIQUE KEY gt (g,t), KEY tg (t,g)
|
danielebarchiesi@4
|
105 ) ". $this->getTableOptionsCode() . "
|
danielebarchiesi@4
|
106 ";
|
danielebarchiesi@4
|
107 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
108 }
|
danielebarchiesi@4
|
109
|
danielebarchiesi@4
|
110 function extendG2tTableColumns($suffix = 'g2t') {
|
danielebarchiesi@4
|
111 $sql = "
|
danielebarchiesi@4
|
112 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
|
danielebarchiesi@4
|
113 MODIFY g int(10) UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
114 MODIFY t int(10) UNSIGNED NOT NULL
|
danielebarchiesi@4
|
115 ";
|
danielebarchiesi@4
|
116 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
117 }
|
danielebarchiesi@4
|
118
|
danielebarchiesi@4
|
119 /* */
|
danielebarchiesi@4
|
120
|
danielebarchiesi@4
|
121 function createID2ValTable() {
|
danielebarchiesi@4
|
122 $sql = "
|
danielebarchiesi@4
|
123 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "id2val (
|
danielebarchiesi@4
|
124 id mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
125 misc tinyint(1) NOT NULL default 0,
|
danielebarchiesi@4
|
126 val text NOT NULL,
|
danielebarchiesi@4
|
127 val_type tinyint(1) NOT NULL default 0, /* uri/bnode/literal => 0/1/2 */
|
danielebarchiesi@4
|
128 UNIQUE KEY (id,val_type), KEY v (val(64))
|
danielebarchiesi@4
|
129 ) ". $this->getTableOptionsCode() . "
|
danielebarchiesi@4
|
130 ";
|
danielebarchiesi@4
|
131 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
132 }
|
danielebarchiesi@4
|
133
|
danielebarchiesi@4
|
134 function extendId2valTableColumns($suffix = 'id2val') {
|
danielebarchiesi@4
|
135 $sql = "
|
danielebarchiesi@4
|
136 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
|
danielebarchiesi@4
|
137 MODIFY id int(10) UNSIGNED NOT NULL
|
danielebarchiesi@4
|
138 ";
|
danielebarchiesi@4
|
139 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
140 }
|
danielebarchiesi@4
|
141
|
danielebarchiesi@4
|
142 /* */
|
danielebarchiesi@4
|
143
|
danielebarchiesi@4
|
144 function createS2ValTable() {
|
danielebarchiesi@4
|
145 //$indexes = 'UNIQUE KEY (id), KEY vh (val_hash), KEY v (val(64))';
|
danielebarchiesi@4
|
146 $indexes = 'UNIQUE KEY (id), KEY vh (val_hash)';
|
danielebarchiesi@4
|
147 $sql = "
|
danielebarchiesi@4
|
148 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "s2val (
|
danielebarchiesi@4
|
149 id mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
150 misc tinyint(1) NOT NULL default 0,
|
danielebarchiesi@4
|
151 val_hash char(32) NOT NULL,
|
danielebarchiesi@4
|
152 val text NOT NULL,
|
danielebarchiesi@4
|
153 " . $indexes . "
|
danielebarchiesi@4
|
154 ) " . $this->getTableOptionsCode() . "
|
danielebarchiesi@4
|
155 ";
|
danielebarchiesi@4
|
156 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
157 }
|
danielebarchiesi@4
|
158
|
danielebarchiesi@4
|
159 function extendS2valTableColumns($suffix = 's2val') {
|
danielebarchiesi@4
|
160 $sql = "
|
danielebarchiesi@4
|
161 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
|
danielebarchiesi@4
|
162 MODIFY id int(10) UNSIGNED NOT NULL
|
danielebarchiesi@4
|
163 ";
|
danielebarchiesi@4
|
164 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
165 }
|
danielebarchiesi@4
|
166
|
danielebarchiesi@4
|
167 /* */
|
danielebarchiesi@4
|
168
|
danielebarchiesi@4
|
169 function createO2ValTable() {
|
danielebarchiesi@4
|
170 /* object value index, e.g. "KEY v (val(64))" and/or "FULLTEXT KEY vft (val)" */
|
danielebarchiesi@4
|
171 $val_index = $this->v('store_object_index', 'KEY v (val(64))', $this->a);
|
danielebarchiesi@4
|
172 if ($val_index) $val_index = ', ' . ltrim($val_index, ',');
|
danielebarchiesi@4
|
173 $sql = "
|
danielebarchiesi@4
|
174 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "o2val (
|
danielebarchiesi@4
|
175 id mediumint UNSIGNED NOT NULL,
|
danielebarchiesi@4
|
176 misc tinyint(1) NOT NULL default 0,
|
danielebarchiesi@4
|
177 val_hash char(32) NOT NULL,
|
danielebarchiesi@4
|
178 val text NOT NULL,
|
danielebarchiesi@4
|
179 UNIQUE KEY (id), KEY vh (val_hash)" . $val_index . "
|
danielebarchiesi@4
|
180 ) ". $this->getTableOptionsCode() . "
|
danielebarchiesi@4
|
181 ";
|
danielebarchiesi@4
|
182 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
183 }
|
danielebarchiesi@4
|
184
|
danielebarchiesi@4
|
185 function extendO2valTableColumns($suffix = 'o2val') {
|
danielebarchiesi@4
|
186 $sql = "
|
danielebarchiesi@4
|
187 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
|
danielebarchiesi@4
|
188 MODIFY id int(10) UNSIGNED NOT NULL
|
danielebarchiesi@4
|
189 ";
|
danielebarchiesi@4
|
190 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
191 }
|
danielebarchiesi@4
|
192
|
danielebarchiesi@4
|
193 /* */
|
danielebarchiesi@4
|
194
|
danielebarchiesi@4
|
195 function createSettingTable() {
|
danielebarchiesi@4
|
196 $sql = "
|
danielebarchiesi@4
|
197 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "setting (
|
danielebarchiesi@4
|
198 k char(32) NOT NULL,
|
danielebarchiesi@4
|
199 val text NOT NULL,
|
danielebarchiesi@4
|
200 UNIQUE KEY (k)
|
danielebarchiesi@4
|
201 ) ". $this->getTableOptionsCode() . "
|
danielebarchiesi@4
|
202 ";
|
danielebarchiesi@4
|
203 return mysql_query($sql, $this->getDBCon());
|
danielebarchiesi@4
|
204 }
|
danielebarchiesi@4
|
205
|
danielebarchiesi@4
|
206 /* */
|
danielebarchiesi@4
|
207
|
danielebarchiesi@4
|
208 function extendColumns() {
|
danielebarchiesi@4
|
209 $con = $this->getDBCon();
|
danielebarchiesi@4
|
210 $tbl_prefix = $this->getTablePrefix();
|
danielebarchiesi@4
|
211 $tbls = $this->getTables();
|
danielebarchiesi@4
|
212 foreach ($tbls as $suffix) {
|
danielebarchiesi@4
|
213 if (preg_match('/^(triple|g2t|id2val|s2val|o2val)/', $suffix, $m)) {
|
danielebarchiesi@4
|
214 $mthd = 'extend' . ucfirst($m[1]) . 'TableColumns';
|
danielebarchiesi@4
|
215 $this->$mthd($suffix);
|
danielebarchiesi@4
|
216 }
|
danielebarchiesi@4
|
217 }
|
danielebarchiesi@4
|
218 }
|
danielebarchiesi@4
|
219
|
danielebarchiesi@4
|
220 /* */
|
danielebarchiesi@4
|
221
|
danielebarchiesi@4
|
222 function splitTables() {
|
danielebarchiesi@4
|
223 $old_ps = $this->getSetting('split_predicates', array());
|
danielebarchiesi@4
|
224 $new_ps = $this->retrieveSplitPredicates();
|
danielebarchiesi@4
|
225 $add_ps = array_diff($new_ps, $old_ps);
|
danielebarchiesi@4
|
226 $del_ps = array_diff($old_ps, $new_ps);
|
danielebarchiesi@4
|
227 $final_ps = array();
|
danielebarchiesi@4
|
228 foreach ($del_ps as $p) {
|
danielebarchiesi@4
|
229 if (!$this->unsplitPredicate($p)) $final_ps[] = $p;
|
danielebarchiesi@4
|
230 }
|
danielebarchiesi@4
|
231 foreach ($add_ps as $p) {
|
danielebarchiesi@4
|
232 if ($this->splitPredicate($p)) $final_ps[] = $p;
|
danielebarchiesi@4
|
233 }
|
danielebarchiesi@4
|
234 $this->setSetting('split_predicates', $new_ps);
|
danielebarchiesi@4
|
235 }
|
danielebarchiesi@4
|
236
|
danielebarchiesi@4
|
237 function unsplitPredicate($p) {
|
danielebarchiesi@4
|
238 $suffix = 'triple_' . abs(crc32($p));
|
danielebarchiesi@4
|
239 $old_tbl = $this->getTablePrefix() . $suffix;
|
danielebarchiesi@4
|
240 $new_tbl = $this->getTablePrefix() . 'triple';
|
danielebarchiesi@4
|
241 $p_id = $this->getTermID($p, 'p');
|
danielebarchiesi@4
|
242 $con = $this->getDBCon();
|
danielebarchiesi@4
|
243 $sql = '
|
danielebarchiesi@4
|
244 INSERT IGNORE INTO ' . $new_tbl .'
|
danielebarchiesi@4
|
245 SELECT * FROM ' . $old_tbl . ' WHERE ' . $old_tbl . '.p = ' . $p_id . '
|
danielebarchiesi@4
|
246 ';
|
danielebarchiesi@4
|
247 if ($rs = mysql_query($sql, $con)) {
|
danielebarchiesi@4
|
248 mysql_query('DROP TABLE ' . $old_tbl, $con);
|
danielebarchiesi@4
|
249 return 1;
|
danielebarchiesi@4
|
250 }
|
danielebarchiesi@4
|
251 else {
|
danielebarchiesi@4
|
252 return 0;
|
danielebarchiesi@4
|
253 }
|
danielebarchiesi@4
|
254 }
|
danielebarchiesi@4
|
255
|
danielebarchiesi@4
|
256 function splitPredicate($p) {
|
danielebarchiesi@4
|
257 $suffix = 'triple_' . abs(crc32($p));
|
danielebarchiesi@4
|
258 $this->createTripleTable($suffix);
|
danielebarchiesi@4
|
259 $old_tbl = $this->getTablePrefix() . 'triple';
|
danielebarchiesi@4
|
260 $new_tbl = $this->getTablePrefix() . $suffix;
|
danielebarchiesi@4
|
261 $p_id = $this->getTermID($p, 'p');
|
danielebarchiesi@4
|
262 $con = $this->getDBCon();
|
danielebarchiesi@4
|
263 $sql = '
|
danielebarchiesi@4
|
264 INSERT IGNORE INTO ' . $new_tbl .'
|
danielebarchiesi@4
|
265 SELECT * FROM ' . $old_tbl . ' WHERE ' . $old_tbl . '.p = ' . $p_id . '
|
danielebarchiesi@4
|
266 ';
|
danielebarchiesi@4
|
267 if ($rs = mysql_query($sql, $con)) {
|
danielebarchiesi@4
|
268 mysql_query('DELETE FROM ' . $old_tbl . ' WHERE ' . $old_tbl . '.p = ' . $p_id, $con);
|
danielebarchiesi@4
|
269 return 1;
|
danielebarchiesi@4
|
270 }
|
danielebarchiesi@4
|
271 else {
|
danielebarchiesi@4
|
272 mysql_query('DROP TABLE ' . $new_tbl, $con);
|
danielebarchiesi@4
|
273 return 0;
|
danielebarchiesi@4
|
274 }
|
danielebarchiesi@4
|
275 }
|
danielebarchiesi@4
|
276
|
danielebarchiesi@4
|
277 function retrieveSplitPredicates() {
|
danielebarchiesi@4
|
278 $r = $this->split_predicates;
|
danielebarchiesi@4
|
279 $limit = $this->max_split_tables - count($r);
|
danielebarchiesi@4
|
280 $q = 'SELECT ?p COUNT(?p) AS ?pc WHERE { ?s ?p ?o } GROUP BY ?p ORDER BY DESC(?pc) LIMIT ' . $limit;
|
danielebarchiesi@4
|
281 $rows = $this->query($q, 'rows');
|
danielebarchiesi@4
|
282 foreach ($rows as $row) {
|
danielebarchiesi@4
|
283 $r[] = $row['p'];
|
danielebarchiesi@4
|
284 }
|
danielebarchiesi@4
|
285 return $r;
|
danielebarchiesi@4
|
286 }
|
danielebarchiesi@4
|
287
|
danielebarchiesi@4
|
288 /* */
|
danielebarchiesi@4
|
289
|
danielebarchiesi@4
|
290 }
|