3 * ARC2 RDF Store Table Manager
5 * @license http://arc.semsol.org/license
6 * @author Benjamin Nowack
13 class ARC2_StoreTableManager extends ARC2_Store {
15 function __construct($a = '', &$caller) {
16 parent::__construct($a, $caller);
19 function ARC2_StoreTableManager($a = '', &$caller) {
20 $this->__construct($a, $caller);
23 function __init() {/* db_con */
25 $this->engine_type = $this->v('store_engine_type', 'MyISAM', $this->a);
30 function getTableOptionsCode() {
31 $v = $this->getDBVersion();
33 $r .= (($v < '04-01-00') && ($v >= '04-00-18')) ? 'ENGINE' : (($v >= '04-01-02') ? 'ENGINE' : 'TYPE');
34 $r .= "=" . $this->engine_type;
35 $r .= ($v >= '04-00-00') ? " CHARACTER SET utf8" : "";
36 $r .= ($v >= '04-01-00') ? " COLLATE utf8_unicode_ci" : "";
37 $r .= " DELAY_KEY_WRITE = 1";
43 function createTables() {
44 $con = $this->getDBCon();
45 if(!$this->createTripleTable()) {
46 return $this->addError('Could not create "triple" table (' . mysql_error($con) . ').');
48 if(!$this->createG2TTable()) {
49 return $this->addError('Could not create "g2t" table (' . mysql_error($con) . ').');
51 if(!$this->createID2ValTable()) {
52 return $this->addError('Could not create "id2val" table (' . mysql_error($con) . ').');
54 if(!$this->createS2ValTable()) {
55 return $this->addError('Could not create "s2val" table (' . mysql_error($con) . ').');
57 if(!$this->createO2ValTable()) {
58 return $this->addError('Could not create "o2val" table (' . mysql_error($con) . ').');
60 if(!$this->createSettingTable()) {
61 return $this->addError('Could not create "setting" table (' . mysql_error($con) . ').');
68 function createTripleTable($suffix = 'triple') {
69 /* keep in sync with merge def in StoreQueryHandler ! */
70 $indexes = $this->v('store_indexes', array('sp (s,p)', 'os (o,s)', 'po (p,o)'), $this->a);
71 $index_code = $indexes ? 'KEY ' . join(', KEY ', $indexes) . ', ' : '';
73 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . $suffix . " (
74 t mediumint UNSIGNED NOT NULL,
75 s mediumint UNSIGNED NOT NULL,
76 p mediumint UNSIGNED NOT NULL,
77 o mediumint UNSIGNED NOT NULL,
78 o_lang_dt mediumint UNSIGNED NOT NULL,
79 o_comp char(35) NOT NULL, /* normalized value for ORDER BY operations */
80 s_type tinyint(1) NOT NULL default 0, /* uri/bnode => 0/1 */
81 o_type tinyint(1) NOT NULL default 0, /* uri/bnode/literal => 0/1/2 */
82 misc tinyint(1) NOT NULL default 0, /* temporary flags */
83 UNIQUE KEY (t), " . $index_code . " KEY (misc)
84 ) ". $this->getTableOptionsCode() . "
86 return mysql_query($sql, $this->getDBCon());
89 function extendTripleTableColumns($suffix = 'triple') {
91 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
92 MODIFY t int(10) UNSIGNED NOT NULL,
93 MODIFY s int(10) UNSIGNED NOT NULL,
94 MODIFY p int(10) UNSIGNED NOT NULL,
95 MODIFY o int(10) UNSIGNED NOT NULL,
96 MODIFY o_lang_dt int(10) UNSIGNED NOT NULL
98 return mysql_query($sql, $this->getDBCon());
103 function createG2TTable() {
105 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "g2t (
106 g mediumint UNSIGNED NOT NULL,
107 t mediumint UNSIGNED NOT NULL,
108 UNIQUE KEY gt (g,t), KEY tg (t,g)
109 ) ". $this->getTableOptionsCode() . "
111 return mysql_query($sql, $this->getDBCon());
114 function extendG2tTableColumns($suffix = 'g2t') {
116 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
117 MODIFY g int(10) UNSIGNED NOT NULL,
118 MODIFY t int(10) UNSIGNED NOT NULL
120 return mysql_query($sql, $this->getDBCon());
125 function createID2ValTable() {
127 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "id2val (
128 id mediumint UNSIGNED NOT NULL,
129 misc tinyint(1) NOT NULL default 0,
131 val_type tinyint(1) NOT NULL default 0, /* uri/bnode/literal => 0/1/2 */
132 UNIQUE KEY (id,val_type), KEY v (val(64))
133 ) ". $this->getTableOptionsCode() . "
135 return mysql_query($sql, $this->getDBCon());
138 function extendId2valTableColumns($suffix = 'id2val') {
140 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
141 MODIFY id int(10) UNSIGNED NOT NULL
143 return mysql_query($sql, $this->getDBCon());
148 function createS2ValTable() {
149 //$indexes = 'UNIQUE KEY (id), KEY vh (val_hash), KEY v (val(64))';
150 $indexes = 'UNIQUE KEY (id), KEY vh (val_hash)';
152 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "s2val (
153 id mediumint UNSIGNED NOT NULL,
154 misc tinyint(1) NOT NULL default 0,
155 val_hash char(32) NOT NULL,
158 ) " . $this->getTableOptionsCode() . "
160 return mysql_query($sql, $this->getDBCon());
163 function extendS2valTableColumns($suffix = 's2val') {
165 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
166 MODIFY id int(10) UNSIGNED NOT NULL
168 return mysql_query($sql, $this->getDBCon());
173 function createO2ValTable() {
174 /* object value index, e.g. "KEY v (val(64))" and/or "FULLTEXT KEY vft (val)" */
175 $val_index = $this->v('store_object_index', 'KEY v (val(64))', $this->a);
176 if ($val_index) $val_index = ', ' . ltrim($val_index, ',');
178 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "o2val (
179 id mediumint UNSIGNED NOT NULL,
180 misc tinyint(1) NOT NULL default 0,
181 val_hash char(32) NOT NULL,
183 UNIQUE KEY (id), KEY vh (val_hash)" . $val_index . "
184 ) ". $this->getTableOptionsCode() . "
186 return mysql_query($sql, $this->getDBCon());
189 function extendO2valTableColumns($suffix = 'o2val') {
191 ALTER TABLE " . $this->getTablePrefix() . $suffix . "
192 MODIFY id int(10) UNSIGNED NOT NULL
194 return mysql_query($sql, $this->getDBCon());
199 function createSettingTable() {
201 CREATE TABLE IF NOT EXISTS " . $this->getTablePrefix() . "setting (
205 ) ". $this->getTableOptionsCode() . "
207 return mysql_query($sql, $this->getDBCon());
212 function extendColumns() {
213 $con = $this->getDBCon();
214 $tbl_prefix = $this->getTablePrefix();
215 $tbls = $this->getTables();
216 foreach ($tbls as $suffix) {
217 if (preg_match('/^(triple|g2t|id2val|s2val|o2val)/', $suffix, $m)) {
218 $mthd = 'extend' . ucfirst($m[1]) . 'TableColumns';
219 $this->$mthd($suffix);
226 function splitTables() {
227 $old_ps = $this->getSetting('split_predicates', array());
228 $new_ps = $this->retrieveSplitPredicates();
229 $add_ps = array_diff($new_ps, $old_ps);
230 $del_ps = array_diff($old_ps, $new_ps);
232 foreach ($del_ps as $p) {
233 if (!$this->unsplitPredicate($p)) $final_ps[] = $p;
235 foreach ($add_ps as $p) {
236 if ($this->splitPredicate($p)) $final_ps[] = $p;
238 $this->setSetting('split_predicates', $new_ps);
241 function unsplitPredicate($p) {
242 $suffix = 'triple_' . abs(crc32($p));
243 $old_tbl = $this->getTablePrefix() . $suffix;
244 $new_tbl = $this->getTablePrefix() . 'triple';
245 $p_id = $this->getTermID($p, 'p');
246 $con = $this->getDBCon();
248 INSERT IGNORE INTO ' . $new_tbl .'
249 SELECT * FROM ' . $old_tbl . ' WHERE ' . $old_tbl . '.p = ' . $p_id . '
251 if ($rs = mysql_query($sql, $con)) {
252 mysql_query('DROP TABLE ' . $old_tbl, $con);
260 function splitPredicate($p) {
261 $suffix = 'triple_' . abs(crc32($p));
262 $this->createTripleTable($suffix);
263 $old_tbl = $this->getTablePrefix() . 'triple';
264 $new_tbl = $this->getTablePrefix() . $suffix;
265 $p_id = $this->getTermID($p, 'p');
266 $con = $this->getDBCon();
268 INSERT IGNORE INTO ' . $new_tbl .'
269 SELECT * FROM ' . $old_tbl . ' WHERE ' . $old_tbl . '.p = ' . $p_id . '
271 if ($rs = mysql_query($sql, $con)) {
272 mysql_query('DELETE FROM ' . $old_tbl . ' WHERE ' . $old_tbl . '.p = ' . $p_id, $con);
276 mysql_query('DROP TABLE ' . $new_tbl, $con);
281 function retrieveSplitPredicates() {
282 $r = $this->split_predicates;
283 $limit = $this->max_split_tables - count($r);
284 $q = 'SELECT ?p COUNT(?p) AS ?pc WHERE { ?s ?p ?o } GROUP BY ?p ORDER BY DESC(?pc) LIMIT ' . $limit;
285 $rows = $this->query($q, 'rows');
286 foreach ($rows as $row) {