EDB
[ class tree: EDB ] [ index: EDB ] [ all elements ]

Source for file EDB_SQLITE3.php

Documentation is available at EDB_SQLITE3.php

  1. <?php
  2. /**
  3.  * Project: EDB_SQLITE3 :: SQLITE3 abstraction layer
  4.  * File:    EDB/EDB_SQLITE3.php
  5.  *
  6.  * The EDB_SQLITE3 class is sqlite3 abstraction layer that used internally
  7.  * on EDB class.
  8.  *
  9.  * @category    Database
  10.  * @package     EDB
  11.  * @subpackage  EDB_ABSTRACT
  12.  * @author      JoungKyun.Kim <http://oops.org>
  13.  * @copyright   (c) 2018, JoungKyun.Kim
  14.  * @license     BSD License
  15.  * @version     $Id$
  16.  * @link        http://pear.oops.org/package/EDB
  17.  * @filesource
  18.  */
  19.  
  20. /**
  21.  * SQLite3 engine for EDB API
  22.  *
  23.  * This class support abstracttion DB layer for SQLite3 Engine
  24.  *
  25.  * @package     EDB
  26.  */
  27. Class EDB_SQLITE3 extends EDB_Common {
  28.     // {{{ properties
  29.     /**#@+
  30.      * @access private
  31.      */
  32.     /**
  33.      * db handler of EDB_SQLITE3 class
  34.      * @var    object 
  35.      */
  36.     private $db;
  37.     /**
  38.      * SQLITE3 STMT object of EDB_SQLITE3 class
  39.      * @var    object 
  40.      */
  41.     private $stmt;
  42.     /**
  43.      * The number of query parameter
  44.      * @var    integer 
  45.      */
  46.     private $pno 0;
  47.     /**
  48.      * The number of query parameter
  49.      * @var    integer 
  50.      */
  51.     private $field array ();
  52.     /**
  53.      * number of query result rows
  54.      * @var    integer 
  55.      */
  56.     private $nums 0;
  57.     /**#@-*/
  58.     // }}}
  59.  
  60.     // {{{ (object) EDB_SQLITE3::__construct ($path, $flag = SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE)
  61.     /** 
  62.      * Instantiates an EDB_SQLITE3 object and opens an SQLite 3 database
  63.      *
  64.      * For examples:
  65.      * <code>
  66.      * $db = new EDB_SQLITE3 ('sqlite3:///path/file.db');
  67.      * $db = new EDB_SQLITE3 ('sqlite3:///path/file.db', SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
  68.      * $db = new EDB_SQLITE3 ('sqlite3://:memory:', SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
  69.      * </code>
  70.      *
  71.      * @access public
  72.      * @return EDB_SQLITE3 
  73.      * @param  string  $path  sqlite3 database file
  74.      * @param  int     $flags (optinal) open flags of sqlite3. See also {@link http://manual.phpdoc.org/HTMLSmartyConverter/PHP/phpDocumentor/tutorial_tags.inlinelink.pkg.html SQLite3::__construct}.
  75.      */
  76.     function __construct ({
  77.         if extension_loaded ('sqlite3') )
  78.             throw new myException ('sqlite3 extension is not loaded on PHP!'E_USER_ERROR);
  79.  
  80.         try {
  81.             $_argv func_get_args ();
  82.             $argv is_array ($_argv[0]$_argv[0$_argv;;
  83.  
  84.             $o = (object) array (
  85.                 'path' => preg_replace ('!^sqlite3://!'''$argv[0]),
  86.                 'flag' => $argv[2],
  87.             );
  88.  
  89.             if $o->flag )
  90.                 $o->flag SQLITE3_OPEN_READWRITE SQLITE3_OPEN_CREATE;
  91.  
  92.             // for persistent connection. sqlite3 don't support
  93.             if preg_match ('!^p~!'$o->path) )
  94.                 $o->path preg_replace ('!^p~!'''$o->path);
  95.  
  96.             $this->db new SQLite3 ($o->path$o->flag);
  97.         catch Exception $e {
  98.             throw new myException ($e->getMessage ()$e->getCode()$e);
  99.         }
  100.     }
  101.     // }}}
  102.  
  103.     // {{{ (string) EDB_SQLITE3::get_charset (void)
  104.     /** 
  105.      * Get character set of current database
  106.      *
  107.      * This method is not allow on SQLite3 Engine
  108.      *
  109.      * @access public
  110.      * @return string Current character set name
  111.      */
  112.     function get_charset ({
  113.         return 'Unsupport';
  114.         #throw new myException ('Unsupported method on SQLITE3 engine', E_ERROR);
  115.     }
  116.     // }}}
  117.  
  118.     // {{{ (bool) EDB_SQLITE3::set_charset ($charset)
  119.     /** 
  120.      * Set character set of current database
  121.      *
  122.      * This method is not allow on SQLite3 Engine, and always
  123.      * returns true.
  124.      *
  125.      * @access public
  126.      * @return bool   always retuns true
  127.      * @param  string $char name of character set that supported from database
  128.      */
  129.     function set_charset ({
  130.         return true;
  131.         #throw new myException ('Unsupported method on SQLITE3 engine', E_ERROR);
  132.     }
  133.     // }}}
  134.  
  135.     // {{{ (string) EDB_SQLITE3::escape ($string)
  136.     /** 
  137.      * Escape special characters in a string for use in an SQL statement
  138.      *
  139.      * @access public
  140.      * @return string 
  141.      * @param  string  The string that is to be escaped.
  142.      */
  143.     function escape ($string{
  144.         return $this->db->escapeString ($string);
  145.     }
  146.     // }}}
  147.  
  148.     // {{{ (int) EDB_SQLITE3::query ($query, $param_type, $param1, $param2 ...)
  149.     /** 
  150.      * Performs a query on the database
  151.      *
  152.      * Executes an SQL query, returning number of affected rows
  153.      *
  154.      * @access public
  155.      * @return integer The number of affected rows or false. If is not delete/insert/update
  156.      *                  query, always returns 0.
  157.      * @param  string $query  The query strings
  158.      * @param  string $type   (optional) Bind parameter type. See also
  159.      *  {@link http://www.php.net/manual/en/sqlite3stmt.bindparam.php SQLite3Stmt::bindparam()}.
  160.      *  <code>
  161.      *  i => integer SQLITE3_INTEGER
  162.      *  d => double  SQLITE3_FLOAT
  163.      *  s => string  SQLITE3_TEXT
  164.      *  b => blob    SQLITE3_BLOB
  165.      *  n => null    SQLITE3_NULL
  166.      *  </code>
  167.      * @param  mixed  $param1 (optional) Bind parameter 1
  168.      * @param  mixed  $param2,... (optional) Bind parameter 2 ..
  169.      */
  170.     function query ({
  171.         $_argv func_get_args ();
  172.         $argv is_array ($_argv[0]$_argv[0$_argv;;
  173.  
  174.         try {
  175.             $sql array_shift ($argv);
  176.             $this->pno count ($argv$this->get_param_number ($sql0;
  177.  
  178.             if $this->free )
  179.                 $this->free_result ();
  180.  
  181.             // store query in log variable
  182.             $this->queryLog[$sql;
  183.  
  184.             /*
  185.              * For no bind query
  186.              */
  187.             if $this->pno++ == )
  188.                 return $this->no_bind_query ($sql);
  189.  
  190.             /*
  191.              * For bind query
  192.              */
  193.             return $this->bind_query ($sql$argv);
  194.         catch Exception $e {
  195.             throw new myException ($e->getMessage ()$e->getCode()$e);
  196.             return false;
  197.         }
  198.     }
  199.     // }}}
  200.  
  201.     // {{{ (int) EDB_SQLITE3::lastId (void)
  202.     /**
  203.      * 가장 마지막 입력 row ID를 반환한다.
  204.      *
  205.      * @since  2.0.4
  206.      * @access public
  207.      * @return int|false
  208.      */
  209.     function lastId ({
  210.         return $this->db->lastInsertRowID ();
  211.     }
  212.     // }}}
  213.  
  214.     // {{{ (bool) EDB_SQLITE3::seek ($offset)
  215.     /**
  216.      * Adjusts the result pointer to an arbitrary row in the result
  217.      *
  218.      * @access public
  219.      * @return boolean 
  220.      * @param  integer Must be between zero and the total number of rows minus one
  221.      */
  222.     function seek ($offset{
  223.         try {
  224.             if is_object ($this->result) )
  225.                 return false;
  226.  
  227.             $this->result->reset ();
  228.  
  229.             if $offset == )
  230.                 return true;
  231.  
  232.             if $offset >= $this->nums )
  233.                 $offset $this->nums;
  234.  
  235.             $i 0;
  236.             $offset--;
  237.             while $this->result->fetchArray (SQLITE3_ASSOC!== false {
  238.                 if $i == $offset )
  239.                     break;
  240.                 $i++;
  241.             }
  242.         catch Exception $e {
  243.             throw new myException ($e->getMessage ()$e->getCode()$e);
  244.             return false;
  245.         }
  246.  
  247.         return true;
  248.     }
  249.     // }}}
  250.  
  251.     // {{{ (object) EDB_SQLITE3::fetch (void)
  252.     /**
  253.      * Fetch a result row as an associative object
  254.      *
  255.      * @access public
  256.      * @return object The object of fetched a result row or false
  257.      * @param  boolean (optional) fetch 수행 후 result를 free한다.
  258.      *                  (기본값: false) EDB >= 2.0.3
  259.      */
  260.     function fetch ($free false{
  261.         try {
  262.             $r $this->result->fetchArray (SQLITE3_ASSOC);
  263.             if $free )
  264.                 $this->free_result ();
  265.             return is_array ($r? (object) $r false;
  266.         catch Exception $e {
  267.             throw new myException ($e->getMessage ()$e->getCode()$e);
  268.             return false;
  269.         }
  270.     }
  271.     // }}}
  272.  
  273.     // {{{ (array) EDB_SQLITE3::fetch_all ($free = true)
  274.     /**
  275.      * Fetch all result rows as an associative object
  276.      *
  277.      * @access public
  278.      * @return array The fetched result rows
  279.      * @param  boolean (optional) free result set after fetch.
  280.      *                  Defaluts is true.
  281.      */
  282.     function fetch_all ($free true{
  283.         $this->field array ();
  284.         $rows array ();
  285.  
  286.         try {
  287.             while ( ($row $this->result->fetchArray (SQLITE3_ASSOC)) !== false )
  288.                 $rows[= (object) $row;
  289.  
  290.             if $free )
  291.                 $this->free_result ();
  292.         catch Exception $e {
  293.             throw new myException ($e->getMessage ()$e->getCode()$e);
  294.             return array ();
  295.         }
  296.  
  297.         return $rows;
  298.     }
  299.     // }}}
  300.  
  301.     // {{{ (bool) EDB_SQLITE3::free_result (void)
  302.     /**
  303.      * Frees stored result memory for the given statement handle
  304.      *
  305.      * @access public
  306.      * @return boolean always returns true
  307.      */
  308.     function free_result ({
  309.         if $this->free return true;
  310.         $this->free = false;
  311.  
  312.         try {
  313.             $this->result->finalize ();
  314.             if $this->stmt instanceof SQLite3Stmt )
  315.                 $this->stmt->clear ();
  316.         catch Exception $e {
  317.             throw new myException ($e->getMessage ()$e->getCode()$e);
  318.             return false;
  319.         }
  320.  
  321.         return true;
  322.     }
  323.     // }}}
  324.  
  325.     // {{{ (string) EDB_SQLITE3::field_name ($index)
  326.     /**
  327.      * Returns the name of the column specified by the column_number.
  328.      *
  329.      * @access public
  330.      * @return string|false
  331.      * @param  integer The numeric zero-based index of the column.
  332.      */
  333.     function field_name ($index{
  334.         try {
  335.             if is_object ($this->result) )
  336.                 return false;
  337.             return $this->result->columnName ($index);
  338.         catch Exception $e {
  339.             throw new myException ($e->getMessage ()$e->getCode()$e);
  340.             return false;
  341.         }
  342.     }
  343.     // }}}
  344.  
  345.     // {{{ (string) EDB_SQLITE3::field_type ($index)
  346.     /**
  347.      * Get the type of the specified field in a result
  348.      *
  349.      * @access public
  350.      * @return string|false
  351.      * @param  integer The numeric zero-based index of the column.
  352.      */
  353.     function field_type ($index{
  354.         try {
  355.             if is_object ($this->result) )
  356.                 return false;
  357.  
  358.             $r $this->result->columnType ($index);
  359.  
  360.             switch ($r{
  361.                 case SQLITE3_INTEGER :
  362.                     return 'int';
  363.                 case SQLITE3_FLOAT :
  364.                     return 'float';
  365.                 case SQLITE3_TEXT :
  366.                     return 'string';
  367.                 case SQLITE3_BLOB :
  368.                     return 'blob';
  369.                 case SQLITE3_NULL :
  370.                     return 'null';
  371.                 default :
  372.                     //throw new myException ('Unknown. This is libsqlite3 bug!', E_USER_WARNING);
  373.                     //return false;
  374.                     return 'unknown, maybe libsqlite3 bug?';
  375.             }
  376.         catch Exception $e {
  377.             throw new myException ($e->getMessage ()$e->getCode()$e);
  378.             return false;
  379.         }
  380.     }
  381.     // }}}
  382.  
  383.     // {{{ (int) EDB_SQLITE3::num_fields (void)
  384.     /**
  385.      * Get number of fields in result
  386.      *
  387.      * @access public
  388.      * @return integer|false
  389.      */
  390.     function num_fields ({
  391.         try {
  392.             if is_object ($this->result) )
  393.                 return false;
  394.  
  395.             return $this->result->numColumns ();
  396.         catch Exception $e {
  397.             throw new myException ($e->getMessage ()$e->getCode()$e);
  398.             return false;
  399.         }
  400.     }
  401.     // }}}
  402.  
  403.     // {{{ (void) EDB_SQLITE3::trstart (void)
  404.     /**
  405.      * DB transaction 을 시작한다.
  406.      *
  407.      * @access public
  408.      * @return void 
  409.      */
  410.     function trstart ({
  411.         $this->db->query ('BEGIN TRANSACTION');
  412.     }
  413.     // }}}
  414.  
  415.     // {{{ (void) EDB_SQLITE3::trend ($v)
  416.     /**
  417.      * DB transaction 을 종료한다.
  418.      *
  419.      * @access public
  420.      * @return void 
  421.      * @param bool false일경우 rollback을 수행한다.
  422.      */
  423.     function trend ($v true{
  424.         $sql ($v === false'ROLLBACK' 'COMMIT';
  425.         $this->db->query ($sql ' TRANSACTION');
  426.     }
  427.     // }}}
  428.  
  429.     // {{{ (void) EDB_SQLITE3::close (void)
  430.     /**
  431.      * Close the db handle
  432.      *
  433.      * @access public
  434.      * @return void 
  435.      */
  436.     function close ({
  437.         if is_object ($this->db) ) {
  438.             $this->db->close ();
  439.             unset ($this->db);
  440.         }
  441.     }
  442.     // }}}
  443.  
  444.     /*
  445.      * Priavte functions
  446.      */
  447.  
  448.     // {{{ private (int) EDB_SQLITE3::num_rows ()
  449.     /**
  450.      * Returns the number of rows in the result set
  451.      *
  452.      * SQLite3 extension don't support num_rows method. Why???
  453.      *
  454.      * @access private
  455.      * @return integer 
  456.      */
  457.     function num_rows ({
  458.         $this->nums 0;
  459.  
  460.         try {
  461.             $r &$this->result;
  462.  
  463.             $i 0;
  464.             while ( ($r->fetchArray (SQLITE3_ASSOC)) !== false )
  465.                 $this->nums++;
  466.  
  467.             unset ($r);
  468.  
  469.             return $this->nums;
  470.         catch Exception $e {
  471.             $this->free = false;
  472.             throw new myException ($e->getMessage ()$e->getCode()$e);
  473.             return false;
  474.         }
  475.     }
  476.     // }}}
  477.  
  478.     // {{{ private (int) EDB_SQLITE3::no_bind_query ($sql)
  479.     /** 
  480.      * Performs a query on the database
  481.      *
  482.      * @access private
  483.      * @return integer The number of affected rows or false only update|insert|delete.
  484.      *                  other row is returned -1.
  485.      * @param  string  The query strings
  486.      */
  487.     private function no_bind_query ($sql{
  488.         try {
  489.             if ( ($this->result = $this->db->query ($sql)) === false {
  490.                 $this->free = false;
  491.                 throw new myException ($this->db->lastErrorMsg ()E_USER_WARNING);
  492.                 return false;
  493.             }
  494.         catch Exception $e {
  495.             $this->free = false;
  496.             throw new myException ($e->getMessage ()$e->getCode()$e);
  497.             return false;
  498.         }
  499.  
  500.         $this->switch_freemark ();
  501.  
  502.         if preg_match ('/^(update|insert|delete|replace)/i'trim ($sql)) )
  503.             return $this->db->changes ();
  504.         else if preg_match ('/^create|drop/i'trim ($sql)) ) 
  505.             return 1;
  506.  
  507.         return $this->num_rows ();
  508.     }
  509.     // }}}
  510.  
  511.     // {{{ private (int) EDB_SQLITE3::bind_query ($sql, $parameters)
  512.     /** 
  513.      * Performs a bind query on the database
  514.      *
  515.      * @access private
  516.      * @return integer The number of affected rows or false
  517.      * @param  string  The query strings
  518.      * @param  array   (optional) Bind parameter type
  519.      */
  520.     private function bind_query ($sql$params{
  521.         if isset ($param) )
  522.             unset ($param);
  523.  
  524.         try {
  525.             $this->stmt $this->db->prepare ($sql);
  526.         catch Exception $e {
  527.             throw new myException ($e->getMessage ()$e->getCode()$e);
  528.         }
  529.  
  530.         if $this->pno != count ($params|| $this->check_param ($params=== false {
  531.             $this->stmt->clear ();
  532.             throw new myException (
  533.                 'Number of elements in query doesn\'t match number of bind variables',
  534.                 E_USER_WARNING
  535.             );
  536.             return false;
  537.         }
  538.  
  539.         $param[array_shift ($params);
  540.         for $i=0$i<count ($params)$i++ )
  541.             $param[&$params[$i];
  542.  
  543.         try {
  544.             for $i=1$i<$this->pno+1$i++ {
  545.                 switch ($param[0][$i-1]{
  546.                     case 'b' :
  547.                     case 'c' :
  548.                         $data is_object ($param[$i]$param[$i]->data $param[$i];
  549.                         $this->stmt->bindParam ($i$dataSQLITE3_BLOB);
  550.                         unset ($data);
  551.                         break;
  552.                     case 'i' :
  553.                         $this->stmt->bindParam ($i$param[$i]SQLITE3_INTEGER);
  554.                         break;
  555.                     case 'd' :
  556.                     case 'f' :
  557.                         $this->stmt->bindParam ($i$param[$i]SQLITE3_FLOAT);
  558.                         break;
  559.                     case 'n' :
  560.                         $this->stmt->bindParam ($i$param[$i]SQLITE3_NULL);
  561.                         break;
  562.                     default :
  563.                         $this->stmt->bindParam ($i$param[$i]);
  564.                 }
  565.             }
  566.  
  567.             $this->result = $this->stmt->execute ();
  568.         catch Exception $e {
  569.             #$this->stmt->clear ();
  570.             throw new myException ($e->getMessage ()$e->getCode()$e);
  571.             #return false;
  572.         }
  573.  
  574.         $this->switch_freemark ();
  575.  
  576.         if preg_match ('/^(create|update|insert|delete)/i'trim ($sql)) )
  577.             return $this->db->changes ();
  578.         else if preg_match ('/^create/i'trim ($sql)) )
  579.             return 1;
  580.  
  581.         return $this->num_rows ();
  582.     }
  583.     // }}}
  584.  
  585.     function __destruct ({
  586.         try {
  587.             @$this->free_result ();
  588.             $this->close ();
  589.         catch Exception $e }
  590.     }
  591. }
  592.  
  593. /*
  594.  * Local variables:
  595.  * tab-width: 4
  596.  * c-basic-offset: 4
  597.  * End:
  598.  * vim: set filetype=php noet sw=4 ts=4 fdm=marker:
  599.  * vim600: noet sw=4 ts=4 fdm=marker
  600.  * vim<600: noet sw=4 ts=4
  601.  */
  602. ?>

Documentation generated on Fri, 30 Aug 2024 06:10:20 +0900 by phpDocumentor 1.4.4