/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
- * Copyright (c) 2001-2012 *
+ * Copyright (c) 2001-2019 *
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
\***************************************************************************/
+/**
+ * Ce fichier déclare des fonctions étendant les fonctions natives de SQLite
+ *
+ * @package SPIP\Core\SQL\SQLite\Fonctions
+ */
+
+if (!defined('_ECRIRE_INC_VERSION')) {
+ return;
+}
-if (!defined('_ECRIRE_INC_VERSION')) return;
-
-/*
- * Des fonctions pour les requetes SQL
+/**
+ * Déclarer à SQLite des fonctions spécifiques utilisables dans les requêtes SQL
+ *
+ * SQLite ne supporte nativement que certaines fonctions dans les requêtes SQL.
+ * Cependant, il permet d'étendre très facilement celles-ci en déclarant de
+ * nouvelles fonctions.
*
- * Voir la liste des fonctions natives : http://www.sqlite.org/lang_corefunc.html
- * Et la liste des evolutions pour : http://sqlite.org/changes.html
+ * C'est ce qui est fait ici, en ajoutant des fonctions qui existent aussi
+ * dans d'autres moteurs, notamment en MySQL.
*
+ * @link http://www.sqlite.org/lang_corefunc.html Liste des fonctions natives
+ * @link http://sqlite.org/changes.html Liste des évolutions
+ *
+ * @param PDO|resource $sqlite Représente la connexion Sqlite
*/
-// http://doc.spip.org/@_sqlite_init_functions
-function _sqlite_init_functions(&$sqlite){
-
- if (!$sqlite) return false;
+function _sqlite_init_functions(&$sqlite) {
+
+ if (!$sqlite) {
+ return false;
+ }
+
-
$fonctions = array(
- 'CONCAT' => array( '_sqlite_func_concat' ,-1),
- 'CEIL' => array( '_sqlite_func_ceil', 1), // absent de sqlite2
-
- 'DATE_FORMAT' => array( '_sqlite_func_strftime' ,2),
- 'DAYOFMONTH' => array( '_sqlite_func_dayofmonth' ,1),
-
- 'EXTRAIRE_MULTI' => array( '_sqlite_func_extraire_multi', 2), // specifique a SPIP/sql_multi()
- 'EXP' => array( 'exp' ,1),//exponentielle
- 'FIND_IN_SET' => array( '_sqlite_func_find_in_set' ,2),
- 'FLOOR' => array( '_sqlite_func_floor', 1), // absent de sqlite2
-
- 'IF' => array( '_sqlite_func_if' ,3),
- 'INSERT' => array( '_sqlite_func_insert' ,4),
- 'INSTR' => array( '_sqlite_func_instr' ,2),
-
- 'LEAST' => array( '_sqlite_func_least' ,3),
- '_LEFT' => array( '_sqlite_func_left' ,2),
-# 'LENGTH' => array( 'strlen' ,1), // present v1.0.4
-# 'LOWER' => array( 'strtolower' ,1), // present v2.4
-# 'LTRIM' => array( 'ltrim' ,1), // present en theorie
-
- 'NOW' => array( '_sqlite_func_now' ,0),
-
- 'MD5' => array( 'md5' ,1),
- 'MONTH' => array( '_sqlite_func_month' ,1),
-
- 'PREG_REPLACE' => array( '_sqlite_func_preg_replace' ,3),
-
- 'RAND' => array( '_sqlite_func_rand' ,0), // sinon random() v2.4
- 'REGEXP' => array( '_sqlite_func_regexp_match' ,2), // critere REGEXP supporte a partir de v3.3.2
- //'REGEXP_MATCH' => array( '_sqlite_func_regexp_match' ,2), // critere REGEXP supporte a partir de v3.3.2
-
- 'RIGHT' => array( '_sqlite_func_right' ,2),
-# 'RTRIM' => array( 'rtrim' ,1), // present en theorie
-
- 'SETTYPE' => array( 'settype' ,2), // CAST present en v3.2.3
- 'SQRT' => array( 'sqrt' ,1),
- 'SUBSTRING' => array( '_sqlite_func_substring' /*,3*/), // peut etre appelee avec 2 ou 3 arguments, index base 1 et non 0
-
- 'TO_DAYS' => array( '_sqlite_func_to_days' ,1),
-# 'TRIM' => array( 'trim' ,1), // present en theorie
-
- 'TIMESTAMPDIFF' => array('_sqlite_timestampdiff' /*,3*/),
-
- 'UNIX_TIMESTAMP'=> array( '_sqlite_func_unix_timestamp' ,1),
-# 'UPPER' => array( 'strtoupper' ,1), // present v2.4
-
- 'VIDE' => array( '_sqlite_func_vide' ,0), // du vide pour SELECT 0 as x ... ORDER BY x -> ORDER BY vide()
-
- 'YEAR' => array( '_sqlite_func_year' ,1)
+ // A
+ 'ACOS' => array('acos', 1),
+ 'ASIN' => array('asin', 1),
+ 'ATAN' => array('atan', 1), // mysql accepte 2 params comme atan2… hum ?
+ 'ATAN2' => array('atan2', 2),
+
+ // C
+ 'CEIL' => array('_sqlite_func_ceil', 1),
+ 'CONCAT' => array('_sqlite_func_concat', -1),
+ 'COS' => array('cos', 1),
+
+ // D
+ 'DATE_FORMAT' => array('_sqlite_func_strftime', 2),
+ 'DAYOFMONTH' => array('_sqlite_func_dayofmonth', 1),
+ 'DEGREES' => array('rad2deg', 1),
+
+ // E
+ 'EXTRAIRE_MULTI' => array('_sqlite_func_extraire_multi', 2), // specifique a SPIP/sql_multi()
+ 'EXP' => array('exp', 1),
+
+ // F
+ 'FIND_IN_SET' => array('_sqlite_func_find_in_set', 2),
+ 'FLOOR' => array('_sqlite_func_floor', 1),
+
+ // I
+ 'IF' => array('_sqlite_func_if', 3),
+ 'INSERT' => array('_sqlite_func_insert', 4),
+ 'INSTR' => array('_sqlite_func_instr', 2),
+
+ // L
+ 'LEAST' => array('_sqlite_func_least', 3),
+ '_LEFT' => array('_sqlite_func_left', 2),
+# 'LENGTH' => array('strlen', 1), // present v1.0.4
+# 'LOWER' => array('strtolower', 1), // present v2.4
+# 'LTRIM' => array('ltrim', 1), // present
+
+ // N
+ 'NOW' => array('_sqlite_func_now', 0),
+
+ // M
+ 'MD5' => array('md5', 1),
+ 'MONTH' => array('_sqlite_func_month', 1),
+
+ // P
+ 'PREG_REPLACE' => array('_sqlite_func_preg_replace', 3),
+
+ // R
+ 'RADIANS' => array('deg2rad', 1),
+ 'RAND' => array('_sqlite_func_rand', 0), // sinon random() v2.4
+ 'REGEXP' => array('_sqlite_func_regexp_match', 2), // critere REGEXP supporte a partir de v3.3.2
+ 'RIGHT' => array('_sqlite_func_right', 2),
+# 'RTRIM' => array('rtrim', 1), // present
+
+ // S
+ 'SETTYPE' => array('settype', 2), // CAST present en v3.2.3
+ 'SIN' => array('sin', 1),
+ 'SQRT' => array('sqrt', 1),
+ 'SUBSTRING' => array('_sqlite_func_substring' /*, 3*/), // peut etre appelee avec 2 ou 3 arguments, index base 1 et non 0
+
+ // T
+ 'TAN' => array('tan', 1),
+ 'TIMESTAMPDIFF' => array('_sqlite_timestampdiff' /*, 3*/),
+ 'TO_DAYS' => array('_sqlite_func_to_days', 1),
+# 'TRIM' => array('trim', 1), // present
+
+ // U
+ 'UNIX_TIMESTAMP' => array('_sqlite_func_unix_timestamp', 1),
+# 'UPPER' => array('strtoupper', 1), // present v2.4
+
+ // V
+ 'VIDE' => array('_sqlite_func_vide', 0), // du vide pour SELECT 0 as x ... ORDER BY x -> ORDER BY vide()
+
+ // Y
+ 'YEAR' => array('_sqlite_func_year', 1)
);
-
- foreach ($fonctions as $f=>$r){
+
+ foreach ($fonctions as $f => $r) {
_sqlite_add_function($sqlite, $f, $r);
}
#spip_log('functions sqlite chargees ','sqlite.'._LOG_DEBUG);
}
-// permet au besoin de charger des fonctions ailleurs par _sqlite_init_functions();
-// http://doc.spip.org/@_sqlite_add_function
-function _sqlite_add_function(&$sqlite, &$f, &$r){
- if (_sqlite_is_version(3, $sqlite)){
+
+/**
+ * Déclare une fonction à SQLite
+ *
+ * @note
+ * Permet au besoin de charger des fonctions
+ * ailleurs par _sqlite_init_functions();
+ *
+ * @uses _sqlite_is_version()
+ *
+ * @param PDO|resource $sqlite Représente la connexion Sqlite
+ * @param string $f Nom de la fonction à créer
+ * @param array $r Tableau indiquant :
+ * - le nom de la fonction à appeler,
+ * - le nombre de paramètres attendus de la fonction (-1 = infini, par défaut)
+ *
+**/
+function _sqlite_add_function(&$sqlite, &$f, &$r) {
+ if (_sqlite_is_version(3, $sqlite)) {
isset($r[1])
- ?$sqlite->sqliteCreateFunction($f, $r[0], $r[1])
- :$sqlite->sqliteCreateFunction($f, $r[0]);
+ ? $sqlite->sqliteCreateFunction($f, $r[0], $r[1])
+ : $sqlite->sqliteCreateFunction($f, $r[0]);
} else {
isset($r[1])
- ?sqlite_create_function($sqlite, $f, $r[0], $r[1])
- :sqlite_create_function($sqlite, $f, $r[0]);
+ ? sqlite_create_function($sqlite, $f, $r[0], $r[1])
+ : sqlite_create_function($sqlite, $f, $r[0]);
}
}
return ceil($a);
}
-// http://doc.spip.org/@_sqlite_func_concat
-function _sqlite_func_concat () {
+// http://code.spip.net/@_sqlite_func_concat
+function _sqlite_func_concat() {
$args = func_get_args();
- return join('',$args);
+
+ return join('', $args);
}
-// http://doc.spip.org/@_sqlite_func_dayofmonth
-function _sqlite_func_dayofmonth ($d) {
- return date("d",_sqlite_func_unix_timestamp($d));
+// http://code.spip.net/@_sqlite_func_dayofmonth
+function _sqlite_func_dayofmonth($d) {
+ return _sqlite_func_date("d", $d);
}
-// http://doc.spip.org/@_sqlite_func_find_in_set
+// http://code.spip.net/@_sqlite_func_find_in_set
function _sqlite_func_find_in_set($num, $set) {
- $rank=0;
- foreach (explode(",",$set) as $v) {
- if ($v == $num) return (++$rank);
- $rank++;
- }
- return 0;
+ $rank = 0;
+ foreach (explode(",", $set) as $v) {
+ if ($v == $num) {
+ return (++$rank);
+ }
+ $rank++;
+ }
+
+ return 0;
}
function _sqlite_func_floor($a) {
return floor($a);
}
-// http://doc.spip.org/@_sqlite_func_if
-function _sqlite_func_if ($bool, $oui, $non) {
- return ($bool)?$oui:$non;
+// http://code.spip.net/@_sqlite_func_if
+function _sqlite_func_if($bool, $oui, $non) {
+ return ($bool) ? $oui : $non;
}
* INSERT(chaine, index, longueur, chaine) MySQL
* Retourne une chaine de caracteres a partir d'une chaine dans laquelle "sschaine"
* a ete inseree a la position "index" en remplacant "longueur" caracteres.
- */
-// http://doc.spip.org/@_sqlite_func_insert
-function _sqlite_func_insert ($s, $index, $longueur, $chaine) {
+ */
+// http://code.spip.net/@_sqlite_func_insert
+function _sqlite_func_insert($s, $index, $longueur, $chaine) {
return
- substr($s,0, $index)
+ substr($s, 0, $index)
. $chaine
. substr(substr($s, $index), $longueur);
}
-// http://doc.spip.org/@_sqlite_func_instr
-function _sqlite_func_instr ($s, $search) {
- return strpos($s,$search);
+// http://code.spip.net/@_sqlite_func_instr
+function _sqlite_func_instr($s, $search) {
+ return strpos($s, $search);
}
-// http://doc.spip.org/@_sqlite_func_least
-function _sqlite_func_least () {
+// http://code.spip.net/@_sqlite_func_least
+function _sqlite_func_least() {
$arg_list = func_get_args();
- $least = min($arg_list);
+ $least = min($arg_list);
+
#spip_log("Passage avec LEAST : $least",'sqlite.'._LOG_DEBUG);
return $least;
}
-// http://doc.spip.org/@_sqlite_func_left
-function _sqlite_func_left ($s, $lenght) {
- return substr($s,0,$lenght);
+// http://code.spip.net/@_sqlite_func_left
+function _sqlite_func_left($s, $lenght) {
+ return substr($s, $lenght);
}
-// http://doc.spip.org/@_sqlite_func_now
-function _sqlite_func_now(){
- $result = date("Y-m-d H:i:s");
- #spip_log("Passage avec NOW : $result",'sqlite.'._LOG_DEBUG);
- return $result;
+// http://code.spip.net/@_sqlite_func_now
+function _sqlite_func_now() {
+ static $now = null;
+ if (is_null($now)) {
+ $now = date("Y-m-d H:i:s");
+ }
+
+ #spip_log("Passage avec NOW : $now",'sqlite.'._LOG_DEBUG);
+ return $now;
}
-// http://doc.spip.org/@_sqlite_func_month
-function _sqlite_func_month ($d) {
- return date("m",_sqlite_func_unix_timestamp($d));
+// http://code.spip.net/@_sqlite_func_month
+function _sqlite_func_month($d) {
+ return _sqlite_func_date("m", $d);
}
-
-// http://doc.spip.org/@_sqlite_func_preg_replace
+// http://code.spip.net/@_sqlite_func_preg_replace
function _sqlite_func_preg_replace($quoi, $cherche, $remplace) {
- $return = preg_replace('%'.$cherche.'%', $remplace, $quoi);
+ $return = preg_replace('%' . $cherche . '%', $remplace, $quoi);
+
#spip_log("preg_replace : $quoi, $cherche, $remplace, $return",'sqlite.'._LOG_DEBUG);
return $return;
}
/**
* Extrait une langue d'un texte <multi>[fr] xxx [en] yyy</multi>
- *
+ *
* @param string $quoi le texte contenant ou non un multi
* @param string $lang la langue a extraire
* @return string, l'extrait trouve.
-**/
+ **/
function _sqlite_func_extraire_multi($quoi, $lang) {
- if (!defined('_EXTRAIRE_MULTI'))
+ if (!defined('_EXTRAIRE_MULTI')) {
include_spip('inc/filtres');
- if (!function_exists('approcher_langue'))
+ }
+ if (!function_exists('approcher_langue')) {
include_spip('inc/lang');
+ }
if (preg_match_all(_EXTRAIRE_MULTI, $quoi, $regs, PREG_SET_ORDER)) {
foreach ($regs as $reg) {
// chercher la version de la langue courante
$quoi = str_replace($reg[0], $trad, $quoi);
}
}
+
return $quoi;
}
-// http://doc.spip.org/@_sqlite_func_rand
+// http://code.spip.net/@_sqlite_func_rand
function _sqlite_func_rand() {
return rand();
}
-// http://doc.spip.org/@_sqlite_func_right
-function _sqlite_func_right ($s, $length) {
- return substr($s,0 - $length);
+// http://code.spip.net/@_sqlite_func_right
+function _sqlite_func_right($s, $length) {
+ return substr($s, 0 - $length);
}
-// http://doc.spip.org/@_sqlite_func_regexp_match
+// http://code.spip.net/@_sqlite_func_regexp_match
function _sqlite_func_regexp_match($cherche, $quoi) {
- $return = preg_match('%'.$cherche.'%', $quoi);
+ // optimiser un cas tres courant avec les requetes en base
+ if (!$quoi and !strlen($quoi)) {
+ return false;
+ }
+ $u = isset($GLOBALS['meta']['pcre_u']) ? $GLOBALS['meta']['pcre_u'] : 'u';
+ $return = preg_match('%' . $cherche . '%imsS' . $u, $quoi);
+
#spip_log("regexp_replace : $quoi, $cherche, $remplace, $return",'sqlite.'._LOG_DEBUG);
return $return;
}
-// http://doc.spip.org/@_sqlite_func_strftime
-function _sqlite_func_strftime($date, $conv){
- return strftime($conv, is_int($date)?$date:strtotime($date));
+// http://code.spip.net/@_sqlite_func_strftime
+function _sqlite_func_strftime($date, $conv) {
+ return strftime($conv, is_int($date) ? $date : strtotime($date));
}
/**
* Nombre de jour entre 0000-00-00 et $d
- * http://doc.spip.org/@_sqlite_func_to_days
- * cf http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_to-days
+ *
+ * @link http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_to-days
+ *
* @param string $d
* @return int
*/
-function _sqlite_func_to_days ($d) {
- $offset = 719528; // nb de jour entre 0000-00-00 et timestamp 0=1970-01-01
- $result = $offset+(int)ceil(_sqlite_func_unix_timestamp($d)/(24*3600));
+function _sqlite_func_to_days($d) {
+ static $offset = 719528; // nb de jour entre 0000-00-00 et timestamp 0=1970-01-01
+ $result = $offset + (int)ceil(_sqlite_func_unix_timestamp($d) / (24 * 3600));
+
#spip_log("Passage avec TO_DAYS : $d, $result",'sqlite.'._LOG_DEBUG);
return $result;
}
-function _sqlite_func_substring($string,$start,$len=null){
+function _sqlite_func_substring($string, $start, $len = null) {
// SQL compte a partir de 1, php a partir de 0
- $start = ($start>0)?$start-1:$start;
- if (is_null($len))
- return substr($string,$start);
- else
- return substr($string,$start,$len);
+ $start = ($start > 0) ? $start - 1 : $start;
+ if (is_null($len)) {
+ return substr($string, $start);
+ } else {
+ return substr($string, $start, $len);
+ }
}
/**
* Calcul de la difference entre 2 timestamp, exprimes dans l'unite fournie en premier argument
- * emule https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestampdiff
+ *
+ * @link https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestampdiff
+ *
* @param string $unit
* @param string $date1
* @param string $date2
* @return int
*/
-function _sqlite_timestampdiff($unit,$date1,$date2){
+function _sqlite_timestampdiff($unit, $date1, $date2) {
// PHP >= 5.3
- if (function_exists("date_diff")){
+ if (function_exists("date_diff")) {
$d1 = date_create($date1);
$d2 = date_create($date2);
- $diff = date_diff($d1,$d2);
- $inv = $diff->invert?-1:1;
- switch($unit){
+ $diff = date_diff($d1, $d2);
+ $inv = $diff->invert ? -1 : 1;
+ switch ($unit) {
case "YEAR":
- return $inv*$diff->y;
+ return $inv * $diff->y;
case "QUARTER":
- return $inv*(4*$diff->y+intval(floor($diff->m/3)));
+ return $inv * (4 * $diff->y + intval(floor($diff->m / 3)));
case "MONTH":
- return $inv*(12*$diff->y+$diff->m);
+ return $inv * (12 * $diff->y + $diff->m);
case "WEEK":
- return $inv*intval(floor($diff->days/7));
+ return $inv * intval(floor($diff->days / 7));
case "DAY":
#var_dump($inv*$diff->days);
- return $inv*$diff->days;
+ return $inv * $diff->days;
case "HOUR":
- return $inv*(24*$diff->days+$diff->h);
+ return $inv * (24 * $diff->days + $diff->h);
case "MINUTE":
- return $inv*((24*$diff->days+$diff->h)*60+$diff->i);
+ return $inv * ((24 * $diff->days + $diff->h) * 60 + $diff->i);
case "SECOND":
- return $inv*(((24*$diff->days+$diff->h)*60+$diff->i)*60+$diff->s);
+ return $inv * (((24 * $diff->days + $diff->h) * 60 + $diff->i) * 60 + $diff->s);
case "MICROSECOND":
- return $inv*(((24*$diff->days+$diff->h)*60+$diff->i)*60+$diff->s)*1000000;
+ return $inv * (((24 * $diff->days + $diff->h) * 60 + $diff->i) * 60 + $diff->s) * 1000000;
}
+
return 0;
- }
- // PHP < 5.3
+ } // PHP < 5.3
else {
$d1 = strtotime($date1);
$d2 = strtotime($date2);
$diff = $d2 - $d1;
- $sign = ($diff<0?-1:1);
+ $sign = ($diff < 0 ? -1 : 1);
$diff = $sign * $diff;
- switch($unit){
+ switch ($unit) {
case "YEAR":
- $diff = $d2-$d1;
- return $sign*(date('Y',abs($diff))-date('Y',0));
+ $diff = $d2 - $d1;
+
+ return $sign * (date('Y', abs($diff)) - date('Y', 0));
case "QUARTER":
- return $sign*(4*(date('Y',abs($diff))-date('Y',0))+intval(floor((date('m',$diff)-1)/3)));
+ return $sign * (4 * (date('Y', abs($diff)) - date('Y', 0)) + intval(floor((date('m', $diff) - 1) / 3)));
case "MONTH":
- return $sign*((date('Y',$diff)-date('Y',0))*12+date('m',$diff)-1);
+ return $sign * ((date('Y', $diff) - date('Y', 0)) * 12 + date('m', $diff) - 1);
case "WEEK":
- return intval(floor(($d2-$d1)/3600/7));
+ return intval(floor(($d2 - $d1) / 3600 / 7));
case "DAY":
- return intval(floor(($d2-$d1)/3600/24));
+ return intval(floor(($d2 - $d1) / 3600 / 24));
case "HOUR":
- return intval(floor(($d2-$d1)/3600));
+ return intval(floor(($d2 - $d1) / 3600));
case "MINUTE":
- return intval(floor(($d2-$d1)/60));
+ return intval(floor(($d2 - $d1) / 60));
case "SECOND":
- return $d2-$d1;
+ return $d2 - $d1;
case "MICROSECOND":
- return $d2-$d1*1000000;
+ return $d2 - $d1 * 1000000;
}
}
}
-// http://doc.spip.org/@_sqlite_func_unix_timestamp
+// http://code.spip.net/@_sqlite_func_unix_timestamp
function _sqlite_func_unix_timestamp($d) {
+ static $mem = array();
+ static $n = 0;
+ if (isset($mem[$d])) {
+ return $mem[$d];
+ }
+ if ($n++ > 100) {
+ $mem = array();
+ $n = 0;
+ }
+
//2005-12-02 20:53:53
#spip_log("Passage avec UNIX_TIMESTAMP : $d",'sqlite.'._LOG_DEBUG);
- // mktime ( [int hour [, int minute [, int second [, int month [, int day [, int year [, int is_dst]]]]]]] )
- if (!$d) return mktime();
- return strtotime($d);
- #preg_match(";^([0-9]{4})-([0-9]+)-([0-9]+)\s*(?:([0-9]+)(?::([0-9]+)(?::([0-9]+))?)?)?;", $d, $f);
- #return mktime($f[4],$f[5],$f[6],$f[2],$f[3],$f[1]);
-}
-
+ if (!$d) {
+ return $mem[$d] = mktime();
+ }
-// http://doc.spip.org/@_sqlite_func_year
-function _sqlite_func_year ($d) {
- return date("Y",_sqlite_func_unix_timestamp($d));
+ // une pile plus grosse n'accelere pas le calcul
+ return $mem[$d] = strtotime($d);
}
-// http://doc.spip.org/@_sqlite_func_vide
-function _sqlite_func_vide(){
- return;
+// http://code.spip.net/@_sqlite_func_year
+function _sqlite_func_year($d) {
+ return _sqlite_func_date("Y", $d);
}
+/**
+ * version optimisee et memoizee de date() utilisee par
+ * _sqlite_func_year, _sqlite_func_month, _sqlite_func_dayofmonth
+ *
+ * @param string $quoi
+ * format : Y, m, ou d
+ * @param int $d
+ * timestamp
+ * @return int
+ */
+function _sqlite_func_date($quoi, $d) {
+ static $mem = array();
+ static $n = 0;
+ if (isset($mem[$d])) {
+ return $mem[$d][$quoi];
+ }
+ if ($n++ > 100) {
+ $mem = array();
+ $n = 0;
+ }
+
+ $dec = date("Y-m-d", _sqlite_func_unix_timestamp($d));
+ $mem[$d] = array("Y" => substr($dec, 0, 4), "m" => substr($dec, 5, 2), "d" => substr($dec, 8, 2));
+ return $mem[$d][$quoi];
+}
-?>
+// http://code.spip.net/@_sqlite_func_vide
+function _sqlite_func_vide() {
+ return;
+}