PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/Erfurt/Store/Adapter/EfZendDb.php

http://github.com/AKSW/Erfurt
PHP | 1741 lines | 1217 code | 303 blank | 221 comment | 176 complexity | 9e1260e8e062b09510b8bb794905e2b5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * This file is part of the {@link http://erfurt-framework.org Erfurt} project.
  4. *
  5. * @copyright Copyright (c) 2012, {@link http://aksw.org AKSW}
  6. * @license http://opensource.org/licenses/gpl-license.php GNU General Public License (GPL)
  7. */
  8. require_once 'Erfurt/Store.php';
  9. require_once 'Erfurt/Store/Adapter/Interface.php';
  10. require_once 'Erfurt/Store/Sql/Interface.php';
  11. /**
  12. * Erfurt RDF Store - Adapter for the {@link http://www4.wiwiss.fu-berlin.de/bizer/rdfapi/ RAP} schema (modified) with
  13. * Zend_Db database abstraction layer.
  14. *
  15. * @package Erfurt_Store_Adapter
  16. * @author Philipp Frischmuth <pfrischmuth@googlemail.com>
  17. */
  18. class Erfurt_Store_Adapter_EfZendDb implements Erfurt_Store_Adapter_Interface, Erfurt_Store_Sql_Interface
  19. {
  20. // ------------------------------------------------------------------------
  21. // --- Private properties -------------------------------------------------
  22. // ------------------------------------------------------------------------
  23. private $_modelCache = array();
  24. private $_modelInfoCache = null;
  25. private $_dbConn = false;
  26. /** @var array */
  27. private $_titleProperties = array(
  28. 'http://www.w3.org/2000/01/rdf-schema#label',
  29. 'http://purl.org/dc/elements/1.1/title'
  30. );
  31. // ------------------------------------------------------------------------
  32. // --- Magic methods ------------------------------------------------------
  33. // ------------------------------------------------------------------------
  34. private $_adapterOptions = array();
  35. /**
  36. * Constructor
  37. *
  38. * @param array $adapterOptions This adapter class needs the following parameters:
  39. * - 'host'
  40. * - 'username'
  41. * - 'password'
  42. * - 'dbname'
  43. */
  44. public function __construct($adapterOptions = array())
  45. {
  46. $adapterOptions = array_merge(array('host' => 'localhost', 'profiler' => false), $adapterOptions);
  47. $this->_adapterOptions = $adapterOptions;
  48. $this->_connect();
  49. // we want indexed results
  50. //$this->_dbConn->setFetchMode(Zend_Db::FETCH_NUM);
  51. // load title properties for model titles
  52. $config = Erfurt_App::getInstance()->getConfig();
  53. if (isset($config->properties->title)) {
  54. $this->_titleProperties = $config->properties->title->toArray();
  55. }
  56. }
  57. protected function _connect(){
  58. switch (strtolower($this->_adapterOptions['dbtype'])) {
  59. case 'mysql':
  60. if (extension_loaded('mysqli')) {
  61. require_once 'Zend/Db/Adapter/Mysqli.php';
  62. $this->_dbConn = new Zend_Db_Adapter_Mysqli($this->_adapterOptions);
  63. } else if (extension_loaded('pdo') && extension_loaded('pdo_mysql')) {
  64. require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
  65. $this->_dbConn = new Zend_Db_Adapter_Pdo_Mysql($this->_adapterOptions);
  66. } else {
  67. require_once 'Erfurt/Exception.php';
  68. throw new Erfurt_Exception('Neither "mysqli" nor "pdo_mysql" extension found.', -1);
  69. }
  70. break;
  71. case 'sqlsrv':
  72. if (extension_loaded('sqlsrv')) {
  73. require_once 'Zend/Db/Adapter/Sqlsrv.php';
  74. $this->_dbConn = new Zend_Db_Adapter_Sqlsrv($this->_adapterOptions);
  75. } else {
  76. require_once 'Erfurt/Exception.php';
  77. throw new Erfurt_Exception('Sqlsrv extension not found.', -1);
  78. }
  79. break;
  80. default:
  81. require_once 'Erfurt/Exception.php';
  82. throw new Erfurt_Exception('Given database adapter is not supported.', -1);
  83. }
  84. try {
  85. // try to initialize the connection
  86. $this->_dbConn->getConnection();
  87. } catch (Zend_Db_Adapter_Exception $e) {
  88. // maybe wrong login credentials or db-server not running?!
  89. require_once 'Erfurt/Exception.php';
  90. throw new Erfurt_Exception(
  91. 'Could not connect to database with name: "' . $this->_adapterOptions['dbname'] .
  92. '". Please check your credentials and whether the database exists and the server is running.', -1
  93. );
  94. } catch (Zend_Exception $e) {
  95. // maybe a needed php extension is not loaded?!
  96. require_once 'Erfurt/Exception.php';
  97. throw new Erfurt_Exception('An error with the specified database adapter occured.', -1);
  98. }
  99. // we want indexed results
  100. //$this->_dbConn->setFetchMode(Zend_Db::FETCH_NUM);
  101. }
  102. /**
  103. * save all but except the db connection
  104. * @return array keys to save
  105. */
  106. function __sleep(){
  107. $vars = get_object_vars($this);
  108. unset($vars['_dbConn']);
  109. return array_keys($vars);
  110. }
  111. function __wakeUp(){
  112. $this->_connect();
  113. }
  114. public function __destruct()
  115. {
  116. #$log = Erfurt_App::getInstance()->getLog();
  117. #$profiles = $this->_dbConn->getProfiler()->getQueryProfiles();
  118. #foreach ($profiles as $profile) {
  119. # $debugStr = 'Query: ' . $profile->getQuery() . PHP_EOL;
  120. # $debugStr .= 'Time: ' . $profile->getElapsedSecs() . PHP_EOL;
  121. #
  122. # $log->debug($debugStr);
  123. #}
  124. }
  125. // ------------------------------------------------------------------------
  126. // --- Public methods (derived from Erfurt_Store_Adapter_Abstract) --------
  127. // ------------------------------------------------------------------------
  128. /** @see Erfurt_Store_Adapter_Interface */
  129. public function addMultipleStatements($graphUri, array $statementsArray, array $options = array())
  130. {
  131. $modelInfoCache = $this->_getModelInfos();
  132. $graphId = $modelInfoCache[$graphUri]['modelId'];
  133. $sqlQuery = 'INSERT IGNORE INTO ef_stmt (g,s,p,o,s_r,p_r,o_r,st,ot,ol,od,od_r) VALUES ';
  134. $insertArray = array();
  135. $counter = 0;
  136. foreach ($statementsArray as $subject => $predicatesArray) {
  137. foreach ($predicatesArray as $predicate => $objectsArray) {
  138. foreach ($objectsArray as $object) {
  139. $sqlString = '';
  140. $s = $subject;
  141. $p = $predicate;
  142. $o = $object;
  143. // check whether the subject is a blank node
  144. if (substr((string)$s, 0, 2) === '_:') {
  145. $s = substr((string)$s, 2);
  146. $subjectIs = '1';
  147. } else {
  148. $subjectIs = '0';
  149. }
  150. // check the type of the object
  151. if ($o['type'] === 'uri') {
  152. $objectIs = '0';
  153. $lang = false;
  154. $dType = false;
  155. } else if ($o['type'] === 'bnode') {
  156. if (substr((string)$o['value'], 0, 2) === '_:') {
  157. $o['value'] = substr((string)$o['value'], 2);
  158. }
  159. $objectIs = '1';
  160. $lang = false;
  161. $dType = false;
  162. } else {
  163. $objectIs = '2';
  164. $lang = isset($o['lang']) ? $o['lang'] : '';
  165. $dType = isset($o['datatype']) ? $o['datatype'] : '';
  166. }
  167. $sRef = false;
  168. if (strlen((string)$s) > $this->_getSchemaRefThreshold()) {
  169. $subjectHash = md5((string)$s);
  170. try {
  171. $sRef = $this->_insertValueInto('ef_uri', $graphId, $s, $subjectHash);
  172. } catch (Erfurt_Store_Adapter_Exception $e) {
  173. $this->_dbConn->rollback();
  174. require_once 'Erfurt/Store/Adapter/Exception.php';
  175. throw new Erfurt_Store_Adapter_Exception($e->getMessage());
  176. }
  177. $s = substr((string)$s, 0, 128) . $subjectHash;
  178. }
  179. $pRef = false;
  180. if (strlen((string)$p) > $this->_getSchemaRefThreshold()) {
  181. $predicateHash = md5((string)$p);
  182. try {
  183. $pRef = $this->_insertValueInto('ef_uri', $graphId, $p, $predicateHash);
  184. } catch (Erfurt_Store_Adapter_Exception $e) {
  185. $this->_dbConn->rollback();
  186. require_once 'Erfurt/Store/Adapter/Exception.php';
  187. throw new Erfurt_Store_Adapter_Exception($e->getMessage());
  188. }
  189. $p = substr((string)$p, 0, 128) . $predicateHash;
  190. }
  191. $oRef = false;
  192. if (strlen((string)$o['value']) > $this->_getSchemaRefThreshold()) {
  193. $objectHash = md5((string)$o['value']);
  194. if ($o['type'] === 'literal') {
  195. $tableName = 'ef_lit';
  196. } else {
  197. $tableName = 'ef_uri';
  198. }
  199. try {
  200. $oRef = $this->_insertValueInto($tableName, $graphId, $o['value'], $objectHash);
  201. } catch (Erfurt_Store_Adapter_Exception $e) {
  202. $this->_dbConn->rollback();
  203. require_once 'Erfurt/Store/Adapter/Exception.php';
  204. throw new Erfurt_Store_Adapter_Exception($e->getMessage());
  205. }
  206. $o['value'] = substr((string)$o['value'], 0, 128) . $objectHash;
  207. }
  208. $oValue = $this->_dbConn->quote($o['value']);
  209. $sqlString .= "($graphId, '$s', '$p', $oValue,";
  210. #$data = array(
  211. # 'g' => $graphId,
  212. # 's' => $subject,
  213. # 'p' => $predicate,
  214. # 'o' => $object['value'],
  215. # 'st' => $subjectIs,
  216. # 'ot' => $objectIs
  217. #);
  218. if ($sRef !== false) {
  219. $sqlString .= "$sRef,";
  220. } else {
  221. $sqlString .= "\N,";
  222. }
  223. if ($pRef !== false) {
  224. $sqlString .= "$pRef,";
  225. } else {
  226. $sqlString .= "\N,";
  227. }
  228. if ($oRef !== false) {
  229. $sqlString .= "$oRef,";
  230. } else {
  231. $sqlString .= "\N,";
  232. }
  233. $sqlString .= "$subjectIs,$objectIs,'$lang',";
  234. #$data['ol'] = $lang;
  235. if (strlen((string)$dType) > $this->_getSchemaRefThreshold()) {
  236. $dTypeHash = md5((string)$dType);
  237. try {
  238. $dtRef = $this->_insertValueInto('ef_uri', $graphId, $dType, $dTypeHash);
  239. } catch (Erfurt_Store_Adapter_Exception $e) {
  240. $this->_dbConn->rollback();
  241. require_once 'Erfurt/Store/Adapter/Exception.php';
  242. throw new Erfurt_Store_Adapter_Exception($e->getMessage());
  243. }
  244. $dType = substr((string)$data['od'], 0, 128) . $dTypeHash;
  245. $data['od_r'] = $dtRef;
  246. $sqlString .= "'$dType',$dtRef)";
  247. } else {
  248. #$data['od'] = $dType;
  249. $sqlString .= "'$dType',\N)";
  250. }
  251. $insertArray[] = $sqlString;
  252. $counter++;
  253. #try {
  254. # $this->_dbConn->insert('ef_stmt', $data);
  255. # $counter++;
  256. #} catch (Exception $e) {
  257. # if ($this->_getNormalizedErrorCode() === 1000) {
  258. # continue;
  259. # } else {
  260. # $this->_dbConn->rollback();
  261. # require_once 'Erfurt/Store/Adapter/Exception.php';
  262. # throw new Erfurt_Store_Adapter_Exception('Bulk insertion of statements failed: ' .
  263. # $this->_dbConn->getConnection()->error);
  264. # }
  265. #}
  266. }
  267. }
  268. }
  269. $sqlQuery .= implode(',', $insertArray);
  270. if (defined('_EFDEBUG')) {
  271. $logger = Erfurt_App::getInstance()->getLog();
  272. $logger->info('ZendDb multiple statements added: ' . $counter);
  273. }
  274. if ($counter > 0) {
  275. $this->sqlQuery($sqlQuery);
  276. }
  277. if ($counter > 100) {
  278. $this->_optimizeTables();
  279. }
  280. }
  281. protected function _getNormalizedErrorCode()
  282. {
  283. if ($this->_dbConn instanceof Zend_Db_Adapter_Mysqli) {
  284. switch($this->_dbConn->getConnection()->errno) {
  285. case 1062:
  286. // duplicate entry
  287. return 1000;
  288. }
  289. } else {
  290. return -1;
  291. }
  292. }
  293. /** @see Erfurt_Store_Adapter_Interface */
  294. public function addStatement($graphUri, $subject, $predicate, $object, array $options = array())
  295. {
  296. $statementArray = array();
  297. $statementArray["$subject"] = array();
  298. $statementArray["$subject"]["$predicate"] = array();
  299. $statementArray["$subject"]["$predicate"][] = $object;
  300. try {
  301. $this->addMultipleStatements($graphUri, $statementArray);
  302. } catch (Erfurt_Store_Adapter_Exception $e) {
  303. require_once 'Erfurt/Store/Adapter/Exception.php';
  304. throw new Erfurt_Store_Adapter_Exception(
  305. 'Insertion of statement failed:' . $e->getMessage()
  306. );
  307. }
  308. }
  309. /** @see Erfurt_Store_Adapter_Interface */
  310. public function countWhereMatches($graphIris, $whereSpec, $countSpec, $distinct = false)
  311. {
  312. $query = new Erfurt_Sparql_SimpleQuery();
  313. if (!$distinct) {
  314. // old way: distinct has no effect !!!
  315. $query->setProloguePart("COUNT DISTINCT $countSpec");
  316. } else {
  317. // i made a (uncool) hack to fix this, the "-" is there because i didnt want to change tokenization
  318. $query->setProloguePart("COUNT-DISTINCT $countSpec");
  319. }
  320. $query->setFrom($graphIris)
  321. ->setWherePart($whereSpec);
  322. $result = $this->sparqlQuery($query);
  323. if ($result) {
  324. return $result;
  325. }
  326. return 0;
  327. }
  328. /** @see Erfurt_Store_Sql_Interface */
  329. public function createTable($tableName, array $columns)
  330. {
  331. if ($this->_dbConn instanceof Zend_Db_Adapter_Mysqli) {
  332. return $this->_createTableMysql($tableName, $columns);
  333. }
  334. }
  335. /** @see Erfurt_Store_Adapter_Interface */
  336. public function createModel($graphUri, $type = Erfurt_Store::MODEL_TYPE_OWL)
  337. {
  338. $data = array(
  339. 'uri' => &$graphUri
  340. );
  341. $baseUri = $graphUri;
  342. if ($baseUri !== '') {
  343. $data['base'] = $baseUri;
  344. }
  345. // insert the new model into the database
  346. $this->_dbConn->insert('ef_graph', $data);
  347. $graphId = $this->lastInsertId();
  348. $uriRef = false;
  349. if (strlen($graphUri) > $this->_getSchemaRefThreshold()) {
  350. $uriHash = md5($uri);
  351. $uriData = array(
  352. 'g' => $graphid,
  353. 'v' => $uri,
  354. 'vh' => $uriHash);
  355. $uriRef = $this->_insertValueInto('ef_uri', $uriData);
  356. $updateData = array(
  357. 'uri' => $uriHash,
  358. 'uri_r' => $uriRef);
  359. $this->_dbConn->update('ef_graph', $updateData, "id = graphId");
  360. }
  361. $baseRef = false;
  362. if (strlen($baseUri) > $this->_getSchemaRefThreshold()) {
  363. $baseHash = md5($baseUri);
  364. $baseData = array(
  365. 'g' => $graphid,
  366. 'v' => $baseUri,
  367. 'vh' => $baseHash);
  368. $baseRef = $this->_insertValueInto('ef_uri', $baseData);
  369. $updateData = array(
  370. 'base' => $baseHash,
  371. 'base_r' => $baseRef);
  372. $this->_dbConn->update('ef_graph', $updateData, "id = graphId");
  373. }
  374. // invalidate the cache and fetch model infos again
  375. require_once 'Erfurt/App.php';
  376. $cache = Erfurt_App::getInstance()->getCache();
  377. $cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('model_info'));
  378. $this->_modelInfoCache = null;
  379. if ($type === Erfurt_Store::MODEL_TYPE_OWL) {
  380. $this->addStatement($graphUri, $graphUri, EF_RDF_TYPE, array('type' => 'uri', 'value' => EF_OWL_ONTOLOGY));
  381. $this->_modelInfoCache = null;
  382. }
  383. }
  384. /** @see Erfurt_Store_Adapter_Interface */
  385. public function deleteMatchingStatements($graphUri, $subject, $predicate, $object, array $options = array())
  386. {
  387. $modelInfoCache = $this->_getModelInfos();
  388. $modelId = $modelInfoCache[$graphUri]['modelId'];
  389. if ($subject !== null && strlen($subject) > $this->_getSchemaRefThreshold()) {
  390. $subject = substr($subject, 0, 128) . md5($subject);
  391. }
  392. if ($predicate !== null && strlen($predicate) > $this->_getSchemaRefThreshold()) {
  393. $predicate = substr($predicate, 0, 128) . md5($predicate);
  394. }
  395. if ($object !== null && strlen($object['value']) > $this->_getSchemaRefThreshold()) {
  396. $object = substr($object['value'], 0, 128) . md5($object['value']);
  397. }
  398. $whereString = '1';
  399. // determine the rows, which should be deleted by the given parameters
  400. if ($subject !== null) {
  401. $whereString .= " AND s = '$subject'";
  402. }
  403. if ($predicate !== null) {
  404. $whereString .= " AND p = '$predicate'";
  405. }
  406. if (null !== $subject) {
  407. if (substr($subject, 0, 2) === '_:') {
  408. $whereString .= ' AND st = 1';
  409. } else {
  410. $whereString .= ' AND st = 0';
  411. }
  412. }
  413. if (null !== $object) {
  414. if (isset($object['value'])) {
  415. $escapedObject = $this->_dbConn->quote($object['value']);
  416. $whereString .= ' AND o = ' . $escapedObject . ' ';
  417. }
  418. if (isset($object['type'])) {
  419. switch ($object['type']) {
  420. case 'uri':
  421. $whereString .= ' AND ot = 0';
  422. break;
  423. case 'literal':
  424. $whereString .= ' AND ot = 2';
  425. break;
  426. case 'bnode':
  427. $whereString .= ' AND ot = 1';
  428. break;
  429. }
  430. }
  431. if (isset($object['lang'])) {
  432. $whereString .= ' AND ol = "' . $object['lang'] . '"';
  433. }
  434. if (isset($object['datatype'])) {
  435. if (strlen($object['datatype']) > $this->_getSchemaRefThreshold()) {
  436. $whereString .= ' AND od = "' . substr($object['datatype'], 0, 128) .
  437. md5($object['datatype']) . '"';
  438. } else {
  439. $whereString .= ' AND od = "' . $object['datatype'] . '"';
  440. }
  441. }
  442. }
  443. // remove the specified statements from the database
  444. $ret = $this->_dbConn->delete('ef_stmt', $whereString);
  445. // Clean up ef_uri and ef_lit table
  446. $this->_cleanUpValueTables($graphUri);
  447. // return number of affected rows (>0 means there were triples deleted)
  448. return $ret;
  449. }
  450. /** @see Erfurt_Store_Adapter_Interface */
  451. public function deleteMultipleStatements($graphUri, array $statementsArray)
  452. {
  453. $modelInfoCache = $this->_getModelInfos();
  454. $modelId = $modelInfoCache[$graphUri]['modelId'];
  455. $this->_dbConn->beginTransaction();
  456. try {
  457. foreach ($statementsArray as $subject => $predicatesArray) {
  458. foreach ($predicatesArray as $predicate => $objectsArray) {
  459. foreach ($objectsArray as $object) {
  460. $whereString = 'g = ' . $modelId . ' ';
  461. // check whether the subject is a blank node
  462. if (substr($subject, 0, 2) === '_:') {
  463. $subject = substr($subject, 2);
  464. $whereString .= 'AND st = 1 ';
  465. } else {
  466. $whereString .= 'AND st = 0 ';
  467. }
  468. // check the type of the object
  469. if ($object['type'] === 'uri') {
  470. $whereString .= 'AND ot = 0 ';
  471. } else if ($object['type'] === 'bnode') {
  472. $whereString .= 'AND ot = 1 ';
  473. } else {
  474. //literal
  475. $whereString .= 'AND ot = 2 ';
  476. $whereString .= isset($object['lang']) ? 'AND ol = \'' . $object['lang'] . '\' ' : '';
  477. $whereString .= isset($object['datatype']) ? 'AND od = \'' . $object['datatype'] .
  478. '\' ' : '';
  479. }
  480. if (strlen((string)$subject) > $this->_getSchemaRefThreshold()) {
  481. $subjectHash = md5((string)$subject);
  482. $subject = substr((string)$subject, 0, 128) . $subjectHash;
  483. }
  484. if (strlen((string)$predicate) > $this->_getSchemaRefThreshold()) {
  485. $predicateHash = md5((string)$predicate);
  486. $predicate = substr((string)$predicate, 0, 128) . $predicateHash;
  487. }
  488. if (strlen((string)$object['value']) > $this->_getSchemaRefThreshold()) {
  489. $objectHash = md5((string)$object['value']);
  490. $object = substr((string)$object['value'], 0, 128) . $objectHash;
  491. } else {
  492. $object = $object['value'];
  493. }
  494. $whereString .= 'AND s = \'' . $subject . '\' ';
  495. $whereString .= 'AND p = \'' . $predicate . '\' ';
  496. //escaping
  497. $escapedObject = $this->_dbConn->quote($object); //also wraps the quotes around
  498. $whereString .= 'AND o = ' . $escapedObject . ' ';
  499. $this->_dbConn->delete('ef_stmt', $whereString);
  500. }
  501. }
  502. }
  503. // if everything went ok... commit the changes to the database
  504. $this->_dbConn->commit();
  505. $this->_cleanUpValueTables($graphUri);
  506. } catch (Exception $e) {
  507. // something went wrong... rollback
  508. $this->_dbConn->rollback();
  509. require_once 'Erfurt/Store/Adapter/Exception.php';
  510. throw new Erfurt_Store_Adapter_Exception('Bulk deletion of statements failed.'.$e->getMessage());
  511. }
  512. }
  513. /** @see Erfurt_Store_Adapter_Interface */
  514. public function deleteModel($graphUri)
  515. {
  516. $modelInfoCache = $this->_getModelInfos();
  517. if (isset($modelInfoCache[$graphUri]['modelId'])) {
  518. $graphId = $modelInfoCache[$graphUri]['modelId'];
  519. } else {
  520. require_once 'Erfurt/Store/Adapter/Exception.php';
  521. throw new Erfurt_Store_Adapter_Exception('Model deletion failed: No db id found for model URL.');
  522. }
  523. // remove all rows with the specified modelID from the models, statements and namespaces tables
  524. $this->_dbConn->delete('ef_graph', "id = $graphId");
  525. $this->_dbConn->delete('ef_stmt', "g = $graphId");
  526. $this->_dbConn->delete('ef_uri', "g = $graphId");
  527. $this->_dbConn->delete('ef_lit', "g = $graphId");
  528. // invalidate the cache and fetch model infos again
  529. // Note: we invalidate the complete model info here
  530. $queryCache = Erfurt_App::getInstance()->getQueryCache();
  531. $queryCache->invalidateWithModelIri((string) $graphUri);
  532. $cache = Erfurt_App::getInstance()->getCache();
  533. $cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('model_info'));
  534. $this->_modelCache = array();
  535. $this->_modelInfoCache = null;
  536. }
  537. /** @see Erfurt_Store_Adapter_Interface */
  538. public function exportRdf($modelIri, $serializationType = 'xml', $filename = false)
  539. {
  540. require_once 'Erfurt/Store/Adapter/Exception.php';
  541. throw new Erfurt_Store_Adapter_Exception('Not implemented yet.');
  542. }
  543. /** @see Erfurt_Store_Adapter_Interface */
  544. public function getAvailableModels()
  545. {
  546. $modelInfoCache = $this->_getModelInfos();
  547. $models = array();
  548. foreach ($modelInfoCache as $mInfo) {
  549. $models[$mInfo['modelIri']] = true;
  550. }
  551. return $models;
  552. }
  553. public function getBackendName()
  554. {
  555. return 'ZendDb';
  556. }
  557. /** @see Erfurt_Store_Adapter_Interface */
  558. public function getBlankNodePrefix()
  559. {
  560. return 'bNode';
  561. }
  562. /**
  563. * Returns a list of graph uris, where each graph in the list contains at least
  564. * one statement where the given resource uri is subject.
  565. *
  566. * @param string $resourceUri
  567. * @return array
  568. */
  569. public function getGraphsUsingResource($resourceUri)
  570. {
  571. $sqlQuery = 'SELECT DISTINCT g.uri FROM ef_stmt s
  572. LEFT JOIN ef_graph g ON ( g.id = s.g)
  573. WHERE s.s = \'' . $resourceUri . '\'';
  574. $sqlResult = $this->sqlQuery($sqlQuery);
  575. $result = array();
  576. foreach ($sqlResult as $row) {
  577. $result[] = $row['uri'];
  578. }
  579. return $result;
  580. }
  581. /**
  582. * Recursively gets owl:imported model IRIs starting with $modelIri as root.
  583. *
  584. * @param string $modelIri
  585. */
  586. public function getImportsClosure($modelIri)
  587. {
  588. $modelInfoCache = $this->_getModelInfos();
  589. if (isset($modelInfoCache["$modelIri"]['imports'])) {
  590. return $modelInfoCache["$modelIri"]['imports'];
  591. } else {
  592. return array();
  593. }
  594. }
  595. /** @see Erfurt_Store_Adapter_Interface */
  596. public function getModel($modelIri)
  597. {
  598. // if model is already in cache return the cached value
  599. if (isset($this->_modelCache[$modelIri])) {
  600. return clone $this->_modelCache[$modelIri];
  601. }
  602. $modelInfoCache = $this->_getModelInfos();
  603. $baseUri = $modelInfoCache[$modelIri]['baseIri'];
  604. if ($baseUri === '') {
  605. $baseUri = null;
  606. }
  607. // choose the right type for the model instance and instanciate it
  608. if ($modelInfoCache[$modelIri]['type'] === 'owl') {
  609. require_once 'Erfurt/Owl/Model.php';
  610. $m = new Erfurt_Owl_Model($modelIri, $baseUri);
  611. } else if ($this->_modelInfoCache[$modelIri]['type'] === 'rdfs') {
  612. require_once 'Erfurt/Rdfs/Model.php';
  613. $m = new Erfurt_Rdfs_Model($modelIri, $baseUri);
  614. } else {
  615. require_once 'Erfurt/Rdf/Model.php';
  616. $m = new Erfurt_Rdf_Model($modelIri, $baseUri);
  617. }
  618. $this->_modelCache[$modelIri] = $m;
  619. return $m;
  620. }
  621. /** @see Erfurt_Store_Adapter_Interface */
  622. public function getNewModel($graphUri, $baseUri = '', $type = 'owl')
  623. {
  624. $data = array(
  625. 'uri' => &$graphUri
  626. );
  627. if ($baseUri !== '') {
  628. $data['base'] = $baseUri;
  629. }
  630. // insert the new model into the database
  631. $this->_dbConn->insert('ef_graph', $data);
  632. $graphId = $this->lastInsertId();
  633. $uriRef = false;
  634. if (strlen($graphUri) > $this->_getSchemaRefThreshold()) {
  635. $uriHash = md5($uri);
  636. $uriData = array(
  637. 'g' => $graphid,
  638. 'v' => $uri,
  639. 'vh' => $uriHash);
  640. $uriRef = $this->_insertValueInto('ef_uri', $uriData);
  641. $updateData = array(
  642. 'uri' => $uriHash,
  643. 'uri_r' => $uriRef);
  644. $this->_dbConn->update('ef_graph', $updateData, "id = graphId");
  645. }
  646. $baseRef = false;
  647. if (strlen($baseUri) > $this->_getSchemaRefThreshold()) {
  648. $baseHash = md5($baseUri);
  649. $baseData = array(
  650. 'g' => $graphid,
  651. 'v' => $baseUri,
  652. 'vh' => $baseHash);
  653. $baseRef = $this->_insertValueInto('ef_uri', $baseData);
  654. $updateData = array(
  655. 'base' => $baseHash,
  656. 'base_r' => $baseRef);
  657. $this->_dbConn->update('ef_graph', $updateData, "id = graphId");
  658. }
  659. // invalidate the cache and fetch model infos again
  660. require_once 'Erfurt/App.php';
  661. $cache = Erfurt_App::getInstance()->getCache();
  662. $cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('model_info'));
  663. $this->_modelInfoCache = null;
  664. if ($type === 'owl') {
  665. $this->addStatement($graphUri, $graphUri, EF_RDF_TYPE, array('type' => 'uri', 'value' => EF_OWL_ONTOLOGY));
  666. $this->_modelInfoCache = null;
  667. }
  668. // instanciate the model
  669. $m = $this->getModel($graphUri);
  670. return $m;
  671. }
  672. /** @see Erfurt_Store_Adapter_Interface */
  673. public function getSupportedExportFormats()
  674. {
  675. return array();
  676. }
  677. /** @see Erfurt_Store_Adapter_Interface */
  678. public function getSupportedImportFormats()
  679. {
  680. return array();
  681. }
  682. /** @see Erfurt_Store_Adapter_Interface */
  683. public function importRdf($modelUri, $data, $type, $locator)
  684. {
  685. // TODO fix or remove
  686. if ($this->_dbConn instanceof Zend_Db_Adapter_Mysqli) {
  687. require_once 'Erfurt/Syntax/RdfParser.php';
  688. $parser = Erfurt_Syntax_RdfParser::rdfParserWithFormat($type);
  689. $parsedArray = $parser->parse($data, $locator, $modelUri, false);
  690. $modelInfoCache = $this->_getModelInfos();
  691. $modelId = $modelInfoCache["$modelUri"]['modelId'];
  692. // create file
  693. $tmpDir = Erfurt_App::getInstance()->getTmpDir();
  694. $filename = $tmpDir . '/import' . md5((string)time()) . '.csv';
  695. $fileHandle = fopen($filename, 'w');
  696. $count = 0;
  697. $longStatements = array();
  698. foreach ($parsedArray as $s => $pArray) {
  699. if (substr($s, 0, 2) === '_:') {
  700. $s = substr($s, 2);
  701. $sType = '1';
  702. } else {
  703. $sType = '0';
  704. }
  705. foreach ($pArray as $p => $oArray) {
  706. foreach ($oArray as $o) {
  707. // to long values need to be put in a different table, so we can't bulk insert these
  708. // values, for they need a foreign key
  709. if (strlen($s) > $this->_getSchemaRefThreshold() ||
  710. strlen($p) > $this->_getSchemaRefThreshold() ||
  711. strlen($o['value']) > $this->_getSchemaRefThreshold() ||
  712. (isset($o['datatype']) && strlen($o['datatype']) > $this->_getSchemaRefThreshold())) {
  713. $longStatements[] = array(
  714. 's' => $s,
  715. 'p' => $p,
  716. 'o' => $o
  717. );
  718. continue;
  719. }
  720. if ($o['type'] === 'literal') {
  721. $oType = '2';
  722. } else if ($o['type'] === 'bnode') {
  723. if (substr($o['value'], 0, 2) === '_:') {
  724. $o['value'] = substr($o['value'], 2);
  725. }
  726. $oType = '1';
  727. } else {
  728. $oType = '0';
  729. }
  730. $lineString = $modelId . ';' . $s . ';' . $p . ';' . $o['value'] . ';';
  731. $lineString .= "\N;\N;\N;";
  732. $lineString .= $sType . ';' . $oType . ';';
  733. if (isset($o['lang'])) {
  734. $lineString .= $o['lang'];
  735. } else {
  736. $lineString .= "\N";
  737. }
  738. $lineString .= ';';
  739. if (isset($o['datatype'])) {
  740. $lineString .= $o['datatype'] . ";\N";
  741. } else {
  742. $lineString .= "\N;\N";
  743. }
  744. $lineString .= PHP_EOL;
  745. $count++;
  746. fputs($fileHandle, $lineString);
  747. }
  748. }
  749. }
  750. fclose($fileHandle);
  751. if ($count > 10000) {
  752. $this->_dbConn->getConnection()->query('ALTER TABLE ef_stmt DISABLE KEYS');
  753. }
  754. $sql = "LOAD DATA INFILE '$filename' IGNORE INTO TABLE ef_stmt
  755. FIELDS TERMINATED BY ';'
  756. (g, s, p, o, s_r, p_r, o_r, st, ot, ol, od, od_r);";
  757. $this->_dbConn->getConnection()->query('START TRANSACTION;');
  758. $this->_dbConn->getConnection()->query($sql);
  759. $this->_dbConn->getConnection()->query('COMMIT');
  760. // Delete the temp file
  761. unlink($filename);
  762. // Now add the long-value-statements
  763. foreach ($longStatements as $stm) {
  764. $sId = false;
  765. $pId = false;
  766. $oId = false;
  767. $dtId = false;
  768. $s = $stm['s'];
  769. $p = $stm['p'];
  770. $o = $stm['o']['value'];
  771. if (strlen($s) > $this->_getSchemaRefThreshold()) {
  772. $sHash = md5($s);
  773. $sId = $this->_insertValueInto('ef_uri', $modelId, $s, $sHash);
  774. $s = substr($s, 0, 128) . $sHash;
  775. }
  776. if (strlen($p) > $this->_getSchemaRefThreshold()) {
  777. $pHash = md5($p);
  778. $pId = $this->_insertValueInto('ef_uri', $modelId, $p, $pHash);
  779. $p = substr($p, 0, 128) . $pHash;
  780. }
  781. if (strlen($o) > $this->_getSchemaRefThreshold()) {
  782. $oHash = md5($o);
  783. if ($stm['o']['type'] === 'literal') {
  784. $oId = $this->_insertValueInto('ef_lit', $modelId, $o, $oHash);
  785. } else {
  786. $oId = $this->_insertValueInto('ef_uri', $modelId, $o, $oHash);
  787. }
  788. $o = substr($o, 0, 128) . $oHash;
  789. }
  790. if (isset($stm['o']['datatype']) && strlen($stm['o']['datatype']) > $this->_getSchemaRefThreshold()) {
  791. $oDtHash = md5($stm['o']['datatype']);
  792. $dtId = $this->_insertValueInto('ef_uri', $modelId, $stm['o']['datatype'], $oDtHash);
  793. $oDt = substr($oDt, 0, 128) . $oDtHash;
  794. }
  795. $sql = "INSERT INTO ef_stmt
  796. (g,s,p,o,s_r,p_r,o_r,st,ot,ol,od,od_r)
  797. VALUES ($modelId,'$s','$p','$o',";
  798. if ($sId !== false) {
  799. $sql .= $sId . ',';
  800. } else {
  801. $sql .= "\N,";
  802. }
  803. if ($pId !== false) {
  804. $sql .= $pId . ',';
  805. } else {
  806. $sql .= "\N,";
  807. }
  808. if ($oId !== false) {
  809. $sql .= $oId . ',';
  810. } else {
  811. $sql .= "\N,";
  812. }
  813. if (substr($stm['s'], 0, 2) === '_:') {
  814. $sql .= '1,';
  815. } else {
  816. $sql .= '0,';
  817. }
  818. if ($stm['o']['type'] === 'literal') {
  819. $sql .= '2,';
  820. } else if ($stm['o']['type'] === 'uri') {
  821. $sql .= '0,';
  822. } else {
  823. $sql .= '1,';
  824. }
  825. if (isset($stm['o']['lang'])) {
  826. $sql .= '"' . $stm['o']['lang'] . '",';
  827. } else {
  828. $sql .= "\N,";
  829. }
  830. if (isset($stm['o']['datatype'])) {
  831. if ($dtId !== false) {
  832. $sql .= '"' . $oDt . '",' . $dtId . ')';
  833. } else {
  834. $sql .= '"' . $stm['o']['datatype'] . '",' . "\N)";
  835. }
  836. } else {
  837. $sql .= "\N,\N)";
  838. }
  839. //$this->_dbConn->getConnection()->query($sql);
  840. }
  841. if ($count > 10000) {
  842. $this->_dbConn->getConnection()->query('ALTER TABLE ef_stmt ENABLE KEYS');
  843. }
  844. $this->_optimizeTables();
  845. } else {
  846. require_once 'Erfurt/Store/Adapter/Exception.php';
  847. throw new Erfurt_Store_Adapter_Exception('CSV import not supported for this database server.');
  848. }
  849. }
  850. public function init()
  851. {
  852. $this->_modelInfoCache = null;
  853. }
  854. /** @see Erfurt_Store_Adapter_Interface */
  855. public function isModelAvailable($modelIri)
  856. {
  857. $modelInfoCache = $this->_getModelInfos();
  858. if (isset($modelInfoCache[$modelIri])) {
  859. return true;
  860. } else {
  861. return false;
  862. }
  863. }
  864. /** @see Erfurt_Store_Sql_Interface */
  865. public function lastInsertId()
  866. {
  867. return $this->_dbConn->lastInsertId();
  868. }
  869. /** @see Erfurt_Store_Sql_Interface */
  870. public function listTables($prefix = '')
  871. {
  872. return $this->_dbConn->listTables();
  873. }
  874. /** @see Erfurt_Store_Adapter_Interface */
  875. public function sparqlAsk($query)
  876. {
  877. //TODO works for me...., why hasnt this be enabled earlier? is the same as sparqlQuery...
  878. //looks like the engine supports it. but there is probably a reason for this not to be supported
  879. $start = microtime(true);
  880. require_once 'Erfurt/Sparql/EngineDb/Adapter/EfZendDb.php';
  881. $engine = new Erfurt_Sparql_EngineDb_Adapter_EfZendDb($this->_dbConn, $this->_getModelInfos());
  882. require_once 'Erfurt/Sparql/Parser.php';
  883. $parser = new Erfurt_Sparql_Parser();
  884. if(!($query instanceof Erfurt_Sparql_Query))
  885. $query = $parser->parse((string)$query);
  886. $result = $engine->queryModel($query);
  887. // Debug executed SPARQL queries in debug mode (7)
  888. $logger = Erfurt_App::getInstance()->getLog();
  889. $time = (microtime(true) - $start)*1000;
  890. $debugText = 'SPARQL Query (' . $time . ' ms)';
  891. $logger->debug($debugText);
  892. return $result;
  893. }
  894. /** @see Erfurt_Store_Adapter_Interface */
  895. public function sparqlQuery($query, $options=array())
  896. {
  897. $resultform =(isset($options[Erfurt_Store::RESULTFORMAT]))?$options[Erfurt_Store::RESULTFORMAT]:Erfurt_Store::RESULTFORMAT_PLAIN;
  898. $start = microtime(true);
  899. require_once 'Erfurt/Sparql/EngineDb/Adapter/EfZendDb.php';
  900. $engine = new Erfurt_Sparql_EngineDb_Adapter_EfZendDb($this->_dbConn, $this->_getModelInfos());
  901. require_once 'Erfurt/Sparql/Parser.php';
  902. $parser = new Erfurt_Sparql_Parser();
  903. if ( !( $query instanceof Erfurt_Sparql_Query ) ) {
  904. $query = $parser->parse((string)$query);
  905. }
  906. $result = $engine->queryModel($query, $resultform);
  907. // Debug executed SPARQL queries in debug mode (7)
  908. $logger = Erfurt_App::getInstance()->getLog();
  909. $time = (microtime(true) - $start)*1000;
  910. $debugText = 'SPARQL Query (' . $time . ' ms)';
  911. $logger->debug($debugText);
  912. return $result;
  913. }
  914. /** @see Erfurt_Store_Sql_Interface */
  915. public function sqlQuery($sqlQuery, $limit = PHP_INT_MAX, $offset = 0)
  916. {
  917. $start = microtime(true);
  918. // add limit/offset
  919. if ($limit < PHP_INT_MAX) {
  920. $sqlQuery = sprintf('%s LIMIT %d OFFSET %d', (string)$sqlQuery, (int)$limit, (int)$offset);
  921. }
  922. $queryType = strtolower(substr($sqlQuery, 0, 6));
  923. if ( $queryType === 'insert' ||
  924. $queryType === 'update' ||
  925. $queryType === 'create' ||
  926. $queryType === 'delete') {
  927. // Handle without ZendDb
  928. $this->_config = Erfurt_App::getInstance()->getConfig();
  929. if ( $this->_config->store->zenddb->dbtype=='sqlsrv' ) {
  930. $result = $this->_dbConn->query($sqlQuery);
  931. } else {
  932. $result = $this->_dbConn->getConnection()->query($sqlQuery);
  933. }
  934. if ( $result !== true ) {
  935. require_once 'Erfurt/Store/Adapter/Exception.php';
  936. throw new Erfurt_Store_Adapter_Exception(
  937. 'SQL query failed: ' .
  938. $this->_dbConn->getConnection()->error
  939. );
  940. }
  941. } else {
  942. try {
  943. $result = @$this->_dbConn->fetchAll($sqlQuery);
  944. } catch (Zend_Db_Exception $e) { #return false;
  945. require_once 'Erfurt/Store/Adapter/Exception.php';
  946. throw new Erfurt_Store_Adapter_Exception(
  947. $e->getMessage()
  948. );
  949. }
  950. }
  951. // Debug executed SQL queries in debug mode (7)
  952. $logger = Erfurt_App::getInstance()->getLog();
  953. $time = (microtime(true) - $start)*1000;
  954. $debugText = 'SQL Query (' . $time . ' ms)';
  955. $logger->debug($debugText);
  956. return $result;
  957. }
  958. // ------------------------------------------------------------------------
  959. // --- Private methods ----------------------------------------------------
  960. // ------------------------------------------------------------------------
  961. /**
  962. * For Zend_Db does not abstract SQL statements that can't be prepared, we need to do this by hand
  963. * for each supported db server, which can be used with the ZendDb adapter.
  964. */
  965. private function _createTableMysql($tableName, array $columns)
  966. {
  967. $createTable = 'CREATE TABLE `' . (string) $tableName . '` (';
  968. $i = 0;
  969. foreach ( $columns as $columnName => $columnSpec ) {
  970. $createTable .= PHP_EOL
  971. . '`' . $columnName . '` '
  972. . $columnSpec . (($i < count($columns)-1) ? ',' : '');
  973. ++$i;
  974. }
  975. $createTable .= PHP_EOL
  976. . ')';
  977. $success = $this->_dbConn->getConnection()->query($createTable);
  978. if ( !$success ) {
  979. // TODO dedicated exception
  980. throw new Exception('Could not create database table with name ' . $tableName . '.');
  981. } else {
  982. return $success;
  983. }
  984. }
  985. /**
  986. * @throws Erfurt_Exception Throws exception if something goes wrong while initialization of database.
  987. */
  988. private function _createTables()
  989. {
  990. if ( $this->_dbConn instanceof Zend_Db_Adapter_Mysqli ) {
  991. return $this->_createTablesMysql();
  992. } else if ( $this->_dbConn instanceof Zend_Db_Adapter_Sqlsrv ) {
  993. return $this->_createTablesSqlsrv();
  994. }
  995. }
  996. /**
  997. * This internal function creates the table structure for MySQL databases.
  998. */
  999. private function _createTablesMysql()
  1000. {
  1001. // Create ef_info table.
  1002. $sql = 'CREATE TABLE IF NOT EXISTS ef_info (
  1003. id TINYINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  1004. schema_id VARCHAR(10) COLLATE ascii_bin NOT NULL
  1005. ) ENGINE = MyISAM DEFAULT CHARSET = ascii;';
  1006. $success = false;
  1007. $success = $this->_dbConn->getConnection()->query($sql);
  1008. if ( !$success ) {
  1009. require_once 'Erfurt/Store/Adapter/Exception.php';
  1010. throw new Erfurt_Store_Adapter_Exception(
  1011. 'Creation of table "ef_info" failed:' .
  1012. $this->_dbConn->getConnection()->error
  1013. );
  1014. }
  1015. // Insert id of the current schema into the ef_info table.
  1016. $sql = 'INSERT INTO ef_info (schema_id) VALUES ("1.0")';
  1017. $success = false;
  1018. $success = $this->_dbConn->getConnection()->query($sql);
  1019. if ( !$success ) {
  1020. require_once 'Erfurt/Store/Adapter/Exception.php';
  1021. throw new Erfurt_Store_Adapter_Exception(
  1022. 'Insertion of "schema_id" into "ef_info" failed: ' .
  1023. $this->_dbConn->getConnection()->error
  1024. );
  1025. }
  1026. // Create ef_graph table.
  1027. $sql = 'CREATE TABLE IF NOT EXISTS ef_graph (
  1028. id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  1029. uri VARCHAR(160) COLLATE ascii_bin NOT NULL,
  1030. uri_r INT UNSIGNED DEFAULT NULL,
  1031. base VARCHAR(160) COLLATE ascii_bin DEFAULT NULL,
  1032. base_r INT UNSIGNED DEFAULT NULL,
  1033. UNIQUE unique_graph (uri)
  1034. ) ENGINE = MyISAM DEFAULT CHARSET = ascii;';
  1035. $success = false;
  1036. $success = $this->_dbConn->getConnection()->query($sql);
  1037. if ( !$success ) {
  1038. require_once 'Erfurt/Store/Adapter/Exception.php';
  1039. throw new Erfurt_Store_Adapter_Exception(
  1040. 'Creation of table "ef_graph" failed: ' .
  1041. $this->_dbConn->getConnection()->error
  1042. );
  1043. }
  1044. // INT means, we could store up to 4.294.967.295 statements
  1045. // Create ef_stmt table.
  1046. $sql = 'CREATE TABLE IF NOT EXISTS ef_stmt (
  1047. id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  1048. g INT UNSIGNED NOT NULL, # foreign key to ef_graph
  1049. s VARCHAR(160) COLLATE ascii_bin NOT NULL, # subject or subject hash
  1050. p VARCHAR(160) COLLATE ascii_bin NOT NULL, # predicate or predicate hash
  1051. o VARCHAR(160) COLLATE utf8_bin NOT NULL, # object or object hash
  1052. s_r INT UNSIGNED DEFAULT NULL, # foreign key to ef_uri
  1053. p_r INT UNSIGNED DEFAULT NULL, # foreign key to ef_uri
  1054. o_r INT UNSIGNED DEFAULT NULL, # foreign key to ef_uri or ef_lit
  1055. st TINYINT(1) UNSIGNED NOT NULL, # 0 - uri, 1 - bnode
  1056. ot TINYINT(1) UNSIGNED NOT NULL, # 0 - uri, 1 - bnode, 2 - literal
  1057. ol VARCHAR(10) COLLATE ascii_bin NOT NULL,
  1058. od VARCHAR(160) COLLATE ascii_bin NOT NULL,
  1059. od_r INT UNSIGNED DEFAULT NULL,
  1060. UNIQUE unique_stmt (g, s, p, o, st, ot, ol, od),
  1061. INDEX idx_g_p_o_ot (g, p, o, ot),
  1062. INDEX idx_g_o_ot (g, o, ot)
  1063. #INDEX idx_o_g_p_ot (o, g, p, ot)
  1064. #INDEX idx_s_g_p_st (s, g, p, st)
  1065. ) ENGINE = MyISAM DEFAULT CHARSET = ascii;';
  1066. $success = false;
  1067. $success = $this->_dbConn->getConnection()->query($sql);
  1068. if (!$success) {
  1069. require_once 'Erfurt/Store/Adapter/Exception.php';
  1070. throw new Erfurt_Store_Adapter_Exception(
  1071. 'Creation of table "ef_stmt" failed: ' .
  1072. $this->_dbConn->getConnection()->error
  1073. );
  1074. }
  1075. /*
  1076. // Create ef_ns table.
  1077. $sql = 'CREATE TABLE IF NOT EXISTS ef_ns (
  1078. id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  1079. g INT UNSIGNED NOT NULL,
  1080. ns VARCHAR(160) COLLATE ascii_bin NOT NULL,
  1081. ns_r INT UNSIGNED DEFAULT NULL,
  1082. prefix VARCHAR(160) COLLATE ascii_bin NOT NULL,
  1083. UNIQUE unique_ns (g, ns, prefix)
  1084. ) ENGINE = MyISAM DEFAULT CHARSET = ascii;';
  1085. $success = false;
  1086. $success = $this->_dbConn->getConnection()->query($sql);
  1087. if (!$success) {
  1088. require_once 'Erfurt/Store/Adapter/Exception.php';
  1089. throw new Erfurt_Store_Adapter_Exception('Creation of table "ef_ns" failed: ' .
  1090. $this->_dbConn->getConnection()->error);
  1091. }
  1092. */
  1093. // Create ef_uri table.
  1094. $sql = 'CREATE TABLE IF NOT EXISTS ef_uri (
  1095. id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
  1096. g INT UNSIGNED NOT NULL,
  1097. v LONGTEXT COLLATE ascii_bin NOT NULL,
  1098. vh CHAR(32) COLLATE ascii_bin NOT NULL,
  1099. UNIQUE unique_uri (g, vh)

Large files files are truncated, but you can click here to view the full file