自己动手做一个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 相关文章推荐
人大复印资料处理程序_查询篇
Oct 09 PHP
PHP实现Socket服务器的代码
Apr 03 PHP
PHP+FFMPEG实现将视频自动转码成H264标准Mp4文件
Sep 24 PHP
Laravel执行migrate命令提示:No such file or directory的解决方法
Mar 16 PHP
Yii数据读取与跳转参数传递用法实例分析
Jul 12 PHP
PHP三种方式实现链式操作详解
Jan 21 PHP
PHP房贷计算器实例代码,等额本息,等额本金
Apr 01 PHP
一个实用的php验证码类
Jul 06 PHP
PHP代码重构方法漫谈
Apr 17 PHP
PHP中PDO事务处理操作示例
May 02 PHP
java解析json方法总结
May 16 PHP
php+laravel 扫码二维码签到功能
May 15 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中VC6 X86和VC9 X86的区别及 Non Thread Safe的意思
2013/06/28 PHP
php使用flock阻塞写入文件和非阻塞写入文件的实例讲解
2017/07/10 PHP
用javascript实现点击链接弹出&quot;图片另存为&quot;而不是直接打开
2007/08/15 Javascript
javascript 函数式编程
2007/08/16 Javascript
10个新的最有前途的JavaScript框架
2009/03/12 Javascript
Javascript图像处理—虚拟边缘介绍及使用方法
2012/12/27 Javascript
Jquery AJAX POST与GET之间的区别
2013/11/14 Javascript
jquery ztree实现树的搜索功能
2016/02/25 Javascript
jQuery判断checkbox选中状态
2016/05/12 Javascript
xtemplate node.js 的使用方法实例解析
2016/08/22 Javascript
Angular.js自动化测试之protractor详解
2017/07/07 Javascript
浅谈angular4 ng-content 中隐藏的内容
2017/08/18 Javascript
基于jQuery实现图片推拉门动画效果的两种方法
2017/08/26 jQuery
JS中用EL表达式获取上下文参数值的方法
2018/03/28 Javascript
Vue2.0 实现单选互斥的方法
2018/04/13 Javascript
js replace 全局替换的操作方法
2018/06/12 Javascript
NodeJS加密解密及node-rsa加密解密用法详解
2018/10/12 NodeJs
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
微信小程序按顺序同步执行的两种方式
2019/12/20 Javascript
js实现时间日期校验
2020/05/26 Javascript
vue输入框使用模糊搜索功能的实现代码
2020/05/26 Javascript
[16:21]教你分分钟做大人:圣堂刺客
2014/12/03 DOTA
Python中的tuple元组详细介绍
2015/02/02 Python
Python中用于去除空格的三个函数的使用小结
2015/04/07 Python
ubuntu17.4下为python和python3装上pip的方法
2018/06/12 Python
Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)
2020/07/06 Python
基于python实现复制文件并重命名
2020/09/16 Python
css3的focus-within选择器的使用
2020/05/11 HTML / CSS
有影响力的人、名人和艺术家的官方商品:Represent
2019/11/26 全球购物
莫斯科的韩国化妆品店:Sifo
2019/12/04 全球购物
计算机通信专业推荐信
2014/02/22 职场文书
道路交通事故赔偿协议书
2014/10/24 职场文书
市场总监岗位职责
2015/02/11 职场文书
安全知识竞赛主持词
2015/06/30 职场文书
go语言使用Casbin实现角色的权限控制
2021/06/26 Golang
解决Laravel使用验证时跳转到首页的问题
2021/11/17 PHP