/arc/store/ARC2_StoreDeleteQueryHandler.php

https://github.com/AramZS/thematicnightmare · PHP · 237 lines · 182 code · 19 blank · 36 comment · 32 complexity · 87e388b75210a5b592bb77f62a0054bd MD5 · raw file

  1. <?php
  2. /**
  3. * ARC2 RDF Store DELETE Query Handler
  4. *
  5. * @author Benjamin Nowack <bnowack@semsol.com>
  6. * @license http://arc.semsol.org/license
  7. * @homepage <http://arc.semsol.org/>
  8. * @package ARC2
  9. * @version 2010-04-11
  10. */
  11. ARC2::inc('StoreQueryHandler');
  12. class ARC2_StoreDeleteQueryHandler extends ARC2_StoreQueryHandler {
  13. function __construct($a = '', &$caller) {/* caller has to be a store */
  14. parent::__construct($a, $caller);
  15. }
  16. function ARC2_StoreDeleteQueryHandler($a = '', &$caller) {
  17. $this->__construct($a, $caller);
  18. }
  19. function __init() {/* db_con */
  20. parent::__init();
  21. $this->store =& $this->caller;
  22. $this->handler_type = 'delete';
  23. }
  24. /* */
  25. function runQuery($infos) {
  26. $this->infos = $infos;
  27. $con = $this->store->getDBCon();
  28. $t1 = ARC2::mtime();
  29. /* delete */
  30. $this->refs_deleted = false;
  31. /* graph(s) only */
  32. if (!$this->v('construct_triples', array(), $this->infos['query'])) {
  33. $tc = $this->deleteTargetGraphs();
  34. }
  35. /* graph(s) + explicit triples */
  36. elseif (!$this->v('pattern', array(), $this->infos['query'])) {
  37. $tc = $this->deleteTriples();
  38. }
  39. /* graph(s) + constructed triples */
  40. else {
  41. $tc = $this->deleteConstructedGraph();
  42. }
  43. $t2 = ARC2::mtime();
  44. /* clean up */
  45. if ($tc && ($this->refs_deleted || (rand(1, 100) == 1))) $this->cleanTableReferences();
  46. if ($tc && (rand(1, 50) == 1)) $this->store->optimizeTables();
  47. if ($tc && (rand(1, 500) == 1)) $this->cleanValueTables();
  48. $t3 = ARC2::mtime();
  49. $index_dur = round($t3 - $t2, 4);
  50. $dur = round($t3 - $t1, 4);
  51. return array(
  52. 't_count' => $tc,
  53. 'delete_time' => $dur,
  54. 'index_update_time' => $index_dur,
  55. );
  56. }
  57. /* */
  58. function deleteTargetGraphs() {
  59. $tbl_prefix = $this->store->getTablePrefix();
  60. $r = 0;
  61. $con = $this->store->getDBCon();
  62. foreach ($this->infos['query']['target_graphs'] as $g) {
  63. if ($g_id = $this->getTermID($g, 'g')) {
  64. $rs = mysql_query('DELETE FROM ' . $tbl_prefix . 'g2t WHERE g = ' .$g_id, $con);
  65. $r += mysql_affected_rows($con);
  66. }
  67. }
  68. $this->refs_deleted = $r ? 1 : 0;
  69. return $r;
  70. }
  71. /* */
  72. function deleteTriples() {
  73. $r = 0;
  74. $dbv = $this->store->getDBVersion();
  75. $tbl_prefix = $this->store->getTablePrefix();
  76. $con = $this->store->getDBCon();
  77. /* graph restriction */
  78. $tgs = $this->infos['query']['target_graphs'];
  79. $gq = '';
  80. foreach ($tgs as $g) {
  81. if ($g_id = $this->getTermID($g, 'g')) {
  82. $gq .= $gq ? ', ' . $g_id : $g_id;
  83. }
  84. }
  85. $gq = $gq ? ' AND G.g IN (' . $gq . ')' : '';
  86. /* triples */
  87. foreach ($this->infos['query']['construct_triples'] as $t) {
  88. $q = '';
  89. $skip = 0;
  90. foreach (array('s', 'p', 'o') as $term) {
  91. if (isset($t[$term . '_type']) && preg_match('/(var)/', $t[$term . '_type'])) {
  92. //$skip = 1;
  93. }
  94. else {
  95. $term_id = $this->getTermID($t[$term], $term);
  96. $q .= ($q ? ' AND ' : '') . 'T.' . $term . '=' . $term_id;
  97. /* explicit lang/dt restricts the matching */
  98. if ($term == 'o') {
  99. $o_lang = $this->v1('o_lang', '', $t);
  100. $o_lang_dt = $this->v1('o_datatype', $o_lang, $t);
  101. if ($o_lang_dt) {
  102. $q .= ($q ? ' AND ' : '') . 'T.o_lang_dt=' . $this->getTermID($o_lang_dt, 'lang_dt');
  103. }
  104. }
  105. }
  106. }
  107. if ($skip) {
  108. continue;
  109. }
  110. if ($gq) {
  111. $sql = ($dbv < '04-01') ? 'DELETE ' . $tbl_prefix . 'g2t' : 'DELETE G';
  112. $sql .= '
  113. FROM ' . $tbl_prefix . 'g2t G
  114. JOIN ' . $this->getTripleTable() . ' T ON (T.t = G.t' . $gq . ')
  115. WHERE ' . $q . '
  116. ';
  117. $this->refs_deleted = 1;
  118. }
  119. else {/* triples only */
  120. $sql = ($dbv < '04-01') ? 'DELETE ' . $this->getTripleTable() : 'DELETE T';
  121. $sql .= ' FROM ' . $this->getTripleTable() . ' T WHERE ' . $q;
  122. }
  123. $rs = mysql_query($sql, $con);
  124. if ($er = mysql_error($con)) {
  125. $this->addError($er .' in ' . $sql);
  126. }
  127. $r += mysql_affected_rows($con);
  128. }
  129. return $r;
  130. }
  131. /* */
  132. function deleteConstructedGraph() {
  133. ARC2::inc('StoreConstructQueryHandler');
  134. $h =& new ARC2_StoreConstructQueryHandler($this->a, $this->store);
  135. $sub_r = $h->runQuery($this->infos);
  136. $triples = ARC2::getTriplesFromIndex($sub_r);
  137. $tgs = $this->infos['query']['target_graphs'];
  138. $this->infos = array('query' => array('construct_triples' => $triples, 'target_graphs' => $tgs));
  139. return $this->deleteTriples();
  140. }
  141. /* */
  142. function cleanTableReferences() {
  143. /* lock */
  144. if (!$this->store->getLock()) return $this->addError('Could not get lock in "cleanTableReferences"');
  145. $con = $this->store->getDBCon();
  146. $tbl_prefix = $this->store->getTablePrefix();
  147. $dbv = $this->store->getDBVersion();
  148. /* check for unconnected triples */
  149. $sql = '
  150. SELECT T.t FROM '. $tbl_prefix . 'triple T LEFT JOIN '. $tbl_prefix . 'g2t G ON ( G.t = T.t )
  151. WHERE G.t IS NULL LIMIT 1
  152. ';
  153. if (($rs = mysql_query($sql, $con)) && mysql_num_rows($rs)) {
  154. /* delete unconnected triples */
  155. $sql = ($dbv < '04-01') ? 'DELETE ' . $tbl_prefix . 'triple' : 'DELETE T';
  156. $sql .= '
  157. FROM ' . $tbl_prefix . 'triple T
  158. LEFT JOIN ' . $tbl_prefix . 'g2t G ON (G.t = T.t)
  159. WHERE G.t IS NULL
  160. ';
  161. mysql_query($sql, $con);
  162. }
  163. /* check for unconnected graph refs */
  164. if ((rand(1, 10) == 1)) {
  165. $sql = '
  166. SELECT G.g FROM '. $tbl_prefix . 'g2t G LEFT JOIN '. $tbl_prefix . 'triple T ON ( T.t = G.t )
  167. WHERE T.t IS NULL LIMIT 1
  168. ';
  169. if (($rs = mysql_query($sql, $con)) && mysql_num_rows($rs)) {
  170. /* delete unconnected graph refs */
  171. $sql = ($dbv < '04-01') ? 'DELETE ' . $tbl_prefix . 'g2t' : 'DELETE G';
  172. $sql .= '
  173. FROM ' . $tbl_prefix . 'g2t G
  174. LEFT JOIN ' . $tbl_prefix . 'triple T ON (T.t = G.t)
  175. WHERE T.t IS NULL
  176. ';
  177. mysql_query($sql, $con);
  178. }
  179. }
  180. /* release lock */
  181. $this->store->releaseLock();
  182. }
  183. /* */
  184. function cleanValueTables() {
  185. /* lock */
  186. if (!$this->store->getLock()) return $this->addError('Could not get lock in "cleanValueTables"');
  187. $con = $this->store->getDBCon();
  188. $tbl_prefix = $this->store->getTablePrefix();
  189. $dbv = $this->store->getDBVersion();
  190. /* o2val */
  191. $sql = ($dbv < '04-01') ? 'DELETE ' . $tbl_prefix . 'o2val' : 'DELETE V';
  192. $sql .= '
  193. FROM ' . $tbl_prefix . 'o2val V
  194. LEFT JOIN ' . $tbl_prefix . 'triple T ON (T.o = V.id)
  195. WHERE T.t IS NULL
  196. ';
  197. mysql_query($sql, $con);
  198. /* s2val */
  199. $sql = ($dbv < '04-01') ? 'DELETE ' . $tbl_prefix . 's2val' : 'DELETE V';
  200. $sql .= '
  201. FROM ' . $tbl_prefix . 's2val V
  202. LEFT JOIN ' . $tbl_prefix . 'triple T ON (T.s = V.id)
  203. WHERE T.t IS NULL
  204. ';
  205. mysql_query($sql, $con);
  206. /* id2val */
  207. $sql = ($dbv < '04-01') ? 'DELETE ' . $tbl_prefix . 'id2val' : 'DELETE V';
  208. $sql .= '
  209. FROM ' . $tbl_prefix . 'id2val V
  210. LEFT JOIN ' . $tbl_prefix . 'g2t G ON (G.g = V.id)
  211. LEFT JOIN ' . $tbl_prefix . 'triple T1 ON (T1.p = V.id)
  212. LEFT JOIN ' . $tbl_prefix . 'triple T2 ON (T2.o_lang_dt = V.id)
  213. WHERE G.g IS NULL AND T1.t IS NULL AND T2.t IS NULL
  214. ';
  215. //mysql_query($sql, $con);
  216. }
  217. /* */
  218. }