/lib/jelix-legacy/plugins/kvdb/db/db.kvdriver.php

http://github.com/jelix/jelix · PHP · 324 lines · 216 code · 57 blank · 51 comment · 32 complexity · 28ba78f8c09c60e26c1598946de99992 MD5 · raw file

  1. <?php
  2. /**
  3. * @package jelix
  4. * @subpackage kvdb_plugin
  5. *
  6. * @author Laurent Jouanneau
  7. * @copyright 2010-2021 Laurent Jouanneau
  8. * @licence http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public Licence, see LICENCE file
  9. */
  10. use function \Jelix\Core\is_resource;
  11. /**
  12. * Driver for jKVDB, that uses an SQL table to store key/value data.
  13. */
  14. class dbKVDriver extends jKVDriver implements jIKVttl, jIKVPersistent
  15. {
  16. /*
  17. MySQL:
  18. CREATE TABLE IF NOT EXISTS `mydb` (
  19. `k_key` VARCHAR( 50 ) NOT NULL ,
  20. `k_value` longblob NOT NULL ,
  21. `k_expire` DATETIME NOT NULL ,
  22. PRIMARY KEY ( `k_key` )
  23. ) ENGINE = MYISAM;
  24. pgsql:
  25. CREATE TABLE mydb (
  26. k_key character varying(255) NOT NULL ,
  27. k_value bytea NOT NULL ,
  28. k_expire time with time zone NOT NULL ,
  29. CONSTRAINT testkvdb_pkey PRIMARY KEY (k_key)
  30. );
  31. sqlite
  32. CREATE TABLE IF NOT EXISTS mydb (
  33. k_key varchar(255) NOT NULL,
  34. k_value blob NOT NULL,
  35. k_expire datetime default NULL,
  36. PRIMARY KEY (k_key)
  37. );
  38. */
  39. protected $table;
  40. protected function _connect()
  41. {
  42. if (!isset($this->_profile['table']) || !isset($this->_profile['dbprofile'])) {
  43. throw new Exception('table and dbprofile is missing for the db kvdb driver');
  44. }
  45. $this->table = $this->_profile['table'];
  46. return jDb::getConnection($this->_profile['dbprofile']);
  47. }
  48. protected function _disconnect()
  49. {
  50. $this->_connection = null;
  51. }
  52. public function get($key)
  53. {
  54. $sql = 'SELECT k_key, k_value FROM '.$this->_connection->prefixTable($this->table).
  55. ' WHERE k_expire > \''.date('Y-m-d H:i:s').'\' AND k_key ';
  56. if (is_array($key)) {
  57. $in = '';
  58. foreach ($key as $k) {
  59. $in .= ','.$this->_connection->quote($k);
  60. }
  61. $sql .= ' IN ('.substr($in, 1).')';
  62. $result = array_combine($key, array_fill(0, count($key), null));
  63. $rs = $this->_connection->query($sql);
  64. if (!$rs) {
  65. return $result;
  66. }
  67. foreach ($rs as $rec) {
  68. $result[$rec->k_key] = unserialize($rs->unescapeBin($rec->k_value));
  69. }
  70. return $result;
  71. }
  72. $sql .= ' = '.$this->_connection->quote($key);
  73. $rs = $this->_connection->query($sql);
  74. if (!$rs) {
  75. return null;
  76. }
  77. $result = $rs->fetch();
  78. if (!$result) {
  79. return null;
  80. }
  81. return unserialize($rs->unescapeBin($result->k_value));
  82. }
  83. public function set($key, $value)
  84. {
  85. if (is_resource($value)) {
  86. return false;
  87. }
  88. return $this->_set($key, $value, '2050-12-31 00:00:00');
  89. }
  90. public function _set($key, $value, $expire)
  91. {
  92. $table = $this->_connection->prefixTable($this->table);
  93. $key = $this->_connection->quote($key);
  94. $value = $this->_connection->quote2(serialize($value), false, true);
  95. $expire = $this->_connection->quote($expire);
  96. $sql = 'SELECT k_key, k_value FROM '.$table.
  97. ' WHERE k_key = '.$key;
  98. $rs = $this->_connection->query($sql);
  99. if (!$rs || !$rs->fetch()) {
  100. $sql = 'INSERT INTO '.$table.' (k_key, k_value, k_expire) VALUES ('
  101. .$key.','.$value.','.$expire.')';
  102. } else {
  103. $sql = 'UPDATE '.$table.' SET k_value= '.$value.', k_expire = '.$expire.'
  104. WHERE k_key='.$key;
  105. }
  106. return (bool) $this->_connection->exec($sql);
  107. }
  108. public function insert($key, $value)
  109. {
  110. if (is_resource($value)) {
  111. return false;
  112. }
  113. $table = $this->_connection->prefixTable($this->table);
  114. $key = $this->_connection->quote($key);
  115. $value = $this->_connection->quote2(serialize($value), false, true);
  116. try {
  117. $sql = 'INSERT INTO '.$table.' (k_key, k_value, k_expire) VALUES ('
  118. .$key.','.$value.',\'2050-12-31 00:00:00\')';
  119. return $this->_connection->exec($sql);
  120. } catch (Exception $e) {
  121. return false;
  122. }
  123. }
  124. public function replace($key, $value)
  125. {
  126. if (is_resource($value)) {
  127. return false;
  128. }
  129. $table = $this->_connection->prefixTable($this->table);
  130. $key = $this->_connection->quote($key);
  131. $value = $this->_connection->quote2(serialize($value), false, true);
  132. $sql = 'UPDATE '.$table.' SET k_value= '.$value.', k_expire = \'2050-12-31 00:00:00\'
  133. WHERE k_key='.$key;
  134. return (bool) $this->_connection->exec($sql);
  135. }
  136. public function delete($key)
  137. {
  138. $table = $this->_connection->prefixTable($this->table);
  139. $key = $this->_connection->quote($key);
  140. $sql = 'DELETE FROM '.$table.' WHERE k_key='.$key;
  141. return (bool) $this->_connection->exec($sql);
  142. }
  143. public function flush()
  144. {
  145. $table = $this->_connection->prefixTable($this->table);
  146. return (bool) $this->_connection->exec('DELETE FROM '.$table);
  147. }
  148. public function append($key, $value)
  149. {
  150. if (is_resource($value)) {
  151. return false;
  152. }
  153. $table = $this->_connection->prefixTable($this->table);
  154. $key = $this->_connection->quote($key);
  155. $sql = 'SELECT k_key, k_value FROM '.$table.' WHERE k_key = '.$key;
  156. $rs = $this->_connection->query($sql);
  157. if (!$rs || !($rec = $rs->fetch())) {
  158. return false;
  159. }
  160. $value = unserialize($rs->unescapeBin($rec->k_value)).$value;
  161. $sql = 'UPDATE '.$table.' SET k_value= '.$this->_connection->quote2(serialize($value), false, true).' WHERE k_key='.$key;
  162. if ($this->_connection->exec($sql)) {
  163. return $value;
  164. }
  165. return false;
  166. }
  167. public function prepend($key, $value)
  168. {
  169. if (is_resource($value)) {
  170. return false;
  171. }
  172. $table = $this->_connection->prefixTable($this->table);
  173. $key = $this->_connection->quote($key);
  174. $sql = 'SELECT k_key, k_value FROM '.$table.' WHERE k_key = '.$key;
  175. $rs = $this->_connection->query($sql);
  176. if (!$rs || !($rec = $rs->fetch())) {
  177. return false;
  178. }
  179. $value = $value.unserialize($rs->unescapeBin($rec->k_value));
  180. $sql = 'UPDATE '.$table.' SET k_value= '.$this->_connection->quote2(serialize($value), false, true).' WHERE k_key='.$key;
  181. if ($this->_connection->exec($sql)) {
  182. return $value;
  183. }
  184. return false;
  185. }
  186. public function increment($key, $incr = 1)
  187. {
  188. if (!is_numeric($incr)) {
  189. return false;
  190. }
  191. $table = $this->_connection->prefixTable($this->table);
  192. $key = $this->_connection->quote($key);
  193. $sql = 'SELECT k_key, k_value FROM '.$table.' WHERE k_key = '.$key;
  194. $rs = $this->_connection->query($sql);
  195. if (!$rs || !($rec = $rs->fetch())) {
  196. return false;
  197. }
  198. $value = unserialize($rec->k_value);
  199. if (!is_numeric($value)) {
  200. return false;
  201. }
  202. $value = serialize($value + $incr);
  203. $sql = 'UPDATE '.$table.' SET k_value= '.$this->_connection->quote($value).' WHERE k_key='.$key;
  204. return (bool) $this->_connection->exec($sql);
  205. }
  206. public function decrement($key, $decr = 1)
  207. {
  208. if (!is_numeric($decr)) {
  209. return false;
  210. }
  211. $table = $this->_connection->prefixTable($this->table);
  212. $key = $this->_connection->quote($key);
  213. $sql = 'SELECT k_key, k_value FROM '.$table.' WHERE k_key = '.$key;
  214. $rs = $this->_connection->query($sql);
  215. if (!$rs || !($rec = $rs->fetch())) {
  216. return false;
  217. }
  218. $value = unserialize($rec->k_value);
  219. if (!is_numeric($value)) {
  220. return false;
  221. }
  222. $value = serialize($value - $decr);
  223. $sql = 'UPDATE '.$table.' SET k_value= '.$this->_connection->quote($value).' WHERE k_key='.$key;
  224. return (bool) $this->_connection->exec($sql);
  225. }
  226. /**
  227. * set a key/value with a ttl value.
  228. *
  229. * @param string $key the key
  230. * @param string $value the value
  231. * @param int $ttl the time to live in seconds...
  232. *
  233. * @return bool false if failure, if the value is a resource...
  234. */
  235. public function setWithTtl($key, $value, $ttl)
  236. {
  237. if (is_resource($value)) {
  238. return false;
  239. }
  240. if ($ttl > 0) {
  241. if ($ttl <= 2592000) {
  242. $ttl += time();
  243. }
  244. $ttl = date('Y-m-d H:i:s', $ttl);
  245. } else {
  246. $ttl = '2050-12-31 00:00:00';
  247. }
  248. return $this->_set($key, $value, $ttl);
  249. }
  250. /**
  251. * delete all keys which are not any more valid.
  252. *
  253. * @return bool false if failure
  254. */
  255. public function garbage()
  256. {
  257. $table = $this->_connection->prefixTable($this->table);
  258. $sql = 'DELETE FROM '.$table.' WHERE k_expire < '.$this->_connection->quote(date('Y-m-d H:i:s'));
  259. return (bool) $this->_connection->exec($sql);
  260. }
  261. public function sync()
  262. {
  263. // nothing to do
  264. }
  265. }