自己动手做一个SQL解释器


Posted in PHP onOctober 09, 2006

自己动手做一个SQL解释器
在一些小型的应用中,完全没有必要使用大型数据库软件。自己做一个SQL解释器就能用数据库的方式来管理了。
这个解释器,能解释常用的SQL命令。你可以自行添加其他功能。

<?php
class DB_text {
  var $conn;
  var $classname = "db_text";
  var $database;
  function on_create() {
  }
  function connect($database_name) {
    $this->database = $database_name;
    if(! file_exists($database_name)) {
      $this->conn = array();
      $this->_close();
    }
    $fp = fopen($this->database,"r");
    $this->conn = unserialize(fread($fp,filesize($this->database)));
    fclose($fp);
  }
  function &query($query) {
    if(eregi("select ",$query)) return $this->_select($query);
    if(eregi("insert ",$query)) return $this->_insert($query);
    if(eregi("delete ",$query)) return $this->_delete($query);
    if(eregi("update ",$query)) return $this->_update($query);
    return array();
  }
  function fetch_row(&$result) {
    if(list($key,$value) = each($result))
      return $value;
    return false;
  }
  function num_rows($result) {
    return count($result);
  }

  /**
   * query的辅助函数
   */
  function _select($query) {
    if(eregi("(order by (.+))",$query,$regs)) {
      $order = $regs[2];
      $query = eregi_replace($regs[1],"",$query);
    }
    if(eregi("(group by (.+))",$query,$regs)) {
      $group = $regs[2];
      $query = eregi_replace($regs[1],"",$query);
    }
    eregi("select .* from ([0-9a-z_]+) *(where +(.+))?",$query,$regs);
    if($regs[3] != "") {
      $keys = $this->_where($regs[3],"\$this->conn[$regs[1]]");
      while(list($key,$value) = each($keys)) {
        $rs[] = $this->conn[$regs[1]][$value];
      }
    }else {
      $rs = $this->conn[$regs[1]];
    }
    if($order) {
      sscanf($order,"%s %s",$key,$type);
      if(empty($type)) $type = "asc";
        $this->_sort($rs,$key,$type);
    }
    return $rs;
  }
  function _insert($query) {
    eregi("insert +into +([0-9a-z_]+) *(.+) *values? *(.+)",$query,$regs);
    eval("\$key=array$regs[2];");
    eval("\$value=array$regs[3];");
    for($i=0;$i<count($key);$i++)
      $rs[$key[$i]] = $value[$i];
    $this->conn[$regs[1]][] = $rs;
    $this->_close();
  }
  function _update($query) {
    eregi("update +([0-9a-z_]+) +set *(,?.*=.*)+( +where +(.+))",$query,$regs);
    $regs[2] = eregi_replace(",","=",$regs[2]);
    $v = split("=",$regs[2]);
    $keys = $this->_where($regs[4],"\$this->conn[$regs[1]]");
    while(list($key,$value) = each($keys)) {
      for($i=0;$i<count($v);$i+=2)
        $this->conn[$regs[1]][$value][$v[$i]] = eregi_replace("'","",$v[$i+1]);
    }
    $this->_close();
  }
  function _delete($query) {
    eregi("delete +from +([0-9a-z_]+) *(where +(.+))?",$query,$regs);
    $keys = $this->_where($regs[3],"\$this->conn[$regs[1]]");
    while(list($key,$value) = each($keys)) {
      unset($this->conn[$regs[1]][$value]);
    }
    reset($this->conn[$regs[1]]);
    while(list($key,$value) = each($this->conn[$regs[1]])) {
      $ch[] = $value;
    }
    $this->conn[$regs[1]] = $ch;
    $this->_close();
  }
  function _where($search,$table) {
    $search = eregi_replace("\("," ( ",$search);
    $search = eregi_replace("\)"," ) ",$search);
    $search = eregi_replace("\+"," + ",$search);
    $search = eregi_replace("\*"," * ",$search);
    while(eregi("[^ ]([*/><!=-])",$search,$regs)) {
      $search = eregi_replace($regs[1]," $regs[1] ",$search);
    }
    while(eregi("([><!] +=)",$search,$regs)) {
      $search = eregi_replace($regs[1],eregi_replace(" ","",$regs[1]),$search);
    }
    $search = eregi_replace("  "," ",trim($search));
    $search = eregi_replace(" and "," && ",$search);
    $search = eregi_replace(" or "," || ",$search);
    $search = eregi_replace(" = "," == ",$search);
    $ar = split(" ",$search);
    eval("\$t=$table;");

    for($i=0;$i<count($ar);$i++) {
      if(isset($t[0][$ar[$i]]))
        $ar[$i] = "\$value[".$ar][$i]."]";
    }
    $expr = "\$expl=(".join(" ",$ar).");";

    while(list($key,$value) = each($t)) {
      eval($expr);
      if($expl)
        $keys[] = $key;
    }
    return $keys;
  }
  function _sort(&$ar,$key=0,$mode="desc") {
    global $cmp_key;
    $cmp_key = $key;
    if($mode == "asc")
      usort($ar,_cmp_asc);
    else
      usort($ar,_cmp_desc);
  }
  function _close() {
    $fp = fopen($this->database,"w");
    fwrite($fp,serialize($this->conn));
    fclose($fp);
  }
}

/** 排序键
*/
$cmp_key = "";

/** 排序用工作函数(降序 由usort()调用)
*/
function _cmp_desc($a,$b) {
  global $cmp_key;
  if ($a[$cmp_key] == $b[$cmp_key]) return 0;
  return ($a[$cmp_key] > $b[$cmp_key]) ? -1 : 1;
}

/** 排序用工作函数(升序 由usort()调用)
*/
function _cmp_asc($a,$b) {
  global $cmp_key;
  if ($a[$cmp_key] == $b[$cmp_key]) return 0;
  return ($a[$cmp_key] > $b[$cmp_key]) ? 1 : -1;
}
?>

测试例:
<pre>
<?php
//require_once "db_text.php";

$conn = new DB_text;
$conn->connect("text1.txt");

$conn->query("insert into manage (id,title) values (10,'abcd')");
$conn->query("insert into manage (id,title) values (2,'43d')");
$conn->query("insert into manage (id,title) values (20,'tuu')");
$conn->query("update manage set id=101,test='a' where id=10");
//$conn->query("delete from manage where id='10'");
//$conn->query("delete from manage where id=10 or table='code'");

//$rt = $conn->query("select * from manage where id=101 or table='code' group by 1 order by 1 asc");
$rt = $conn->query("select * from manage group by 1 order by id desc");

print_r($rt);

?>
</pre>

PHP 相关文章推荐
php数组总结篇(一)
Sep 30 PHP
一步一步学习PHP(6) 面向对象
Feb 16 PHP
php下mysql数据库操作类(改自discuz)
Jul 03 PHP
php二维数组排序详解
Nov 06 PHP
PHP加密扩展库Mcrypt安装和实例
Nov 10 PHP
在php和MySql中计算时间差的方法详解
Mar 27 PHP
PHP面向对象详解(三)
Dec 07 PHP
Zend Framework创建自己的动作助手详解
Mar 05 PHP
Symfony2之session与cookie用法小结
Mar 18 PHP
PHP标准类(stdclass)用法示例
Sep 28 PHP
PHP函数按引用传递参数及函数可选参数用法示例
Jun 04 PHP
php命令行写shell实例详解
Jul 19 PHP
GD输出汉字的函数的分析
Oct 09 #PHP
类的另类用法--数据的封装
Oct 09 #PHP
最小化数据传输――在客户端存储数据
Oct 09 #PHP
网站加速 PHP 缓冲的免费实现方法
Oct 09 #PHP
Windows下PHP的任意文件执行漏洞
Oct 09 #PHP
通过对服务器端特性的配置加强php的安全
Oct 09 #PHP
用Zend Encode编写开发PHP程序
Oct 09 #PHP
You might like
深入PHP变量存储的详解
2013/06/13 PHP
php文件缓存类汇总
2014/11/21 PHP
php连接与操作PostgreSQL数据库的方法
2014/12/25 PHP
php中实现进程锁与多进程的方法
2016/09/18 PHP
Yii2配置Nginx伪静态的方法
2017/05/05 PHP
php简单读取.vcf格式文件的方法示例
2017/09/02 PHP
laravel实现一个上传图片的接口,并建立软链接,访问图片的方法
2019/10/12 PHP
PHP强制转化的形式整理
2020/05/22 PHP
JQuery Tips(3) 关于$()包装集内元素的改变
2009/12/14 Javascript
使用JQUERY Tabs插件宿主IFRAMES
2010/01/01 Javascript
JS实现DIV高度自适应窗口示例
2017/02/16 Javascript
浅谈JS中的常用选择器及属性、方法的调用
2017/07/28 Javascript
解决axios发送post请求返回400状态码的问题
2018/08/11 Javascript
使用Vue.js中的过滤器实现幂方求值的方法
2019/08/27 Javascript
jQuery实现数字华容道小游戏(实例代码)
2020/01/16 jQuery
解决echarts 一条柱状图显示两个值,类似进度条的问题
2020/07/20 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
JS实现超级好看的鼠标小尾巴特效
2020/12/01 Javascript
Python模拟登陆淘宝并统计淘宝消费情况的代码实例分享
2016/07/04 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
详解Python读取yaml文件多层菜单
2019/03/23 Python
详解Python locals()的陷阱
2019/03/26 Python
python调用摄像头拍摄数据集
2019/06/01 Python
python中time库的实例使用方法
2019/10/31 Python
python3实现弹弹球小游戏
2019/11/25 Python
关于Tensorflow 模型持久化详解
2020/02/12 Python
python应用Axes3D绘图(批量梯度下降算法)
2020/03/25 Python
Python如何生成xml文件
2020/06/04 Python
Python生成器generator原理及用法解析
2020/07/20 Python
波兰运动鞋网上商店:e-Sporting
2018/02/16 全球购物
雅诗兰黛澳大利亚官网:Estée Lauder澳大利亚
2019/05/31 全球购物
标记环介质访问控制协议
2016/03/27 面试题
2014年政务公开工作总结
2014/12/09 职场文书
市级三好学生评语
2014/12/29 职场文书
提取视频中的音频 Python只需要三行代码!
2021/05/10 Python
详解CSS3.0(Cascading Style Sheet) 层叠级联样式表
2021/07/16 HTML / CSS