自己动手做一个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之第四天
Oct 09 PHP
PHP异步调用socket实现代码
Jan 12 PHP
PHP实现根据浏览器跳转不同语言页面代码
Aug 02 PHP
改写函数实现PHP二维/三维数组转字符串
Sep 13 PHP
PHP添加Xdebug扩展的方法
Feb 12 PHP
PHP管理依赖(dependency)关系工具 Composer的自动加载(autoload)
Aug 18 PHP
浅析THINKPHP的addAll支持的最大数据量
Feb 03 PHP
php控制文件下载速度的方法
Mar 24 PHP
PHP网站建设的流程与步骤分享
Sep 25 PHP
php 计算两个时间相差的天数、小时数、分钟数、秒数详解及实例代码
Nov 09 PHP
PHP中仿制 ecshop验证码实例
Jan 06 PHP
详谈php ip2long 出现负数的原因及解决方法
Apr 05 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
PHP5常用函数列表(分享)
2013/06/07 PHP
php实现天干地支计算器示例
2014/03/14 PHP
php使用ob_flush不能每隔一秒输出原理分析
2015/06/02 PHP
PHP图形计数器程序显示网站用户浏览量
2016/07/20 PHP
PHP 实现公历日期与农历日期的互转换
2017/09/13 PHP
php命令行写shell实例详解
2018/07/19 PHP
关于html+ashx开发中几个问题的解决方法
2011/07/18 Javascript
js判断undefined类型示例代码
2014/02/10 Javascript
简单谈谈Javascript中类型的判断
2015/10/19 Javascript
JavaScript Array对象详解
2016/03/01 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
js判断浏览器是否支持严格模式的方法
2016/10/04 Javascript
canvas知识总结
2017/01/25 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
Vue.js之slot深度复制详解
2017/03/10 Javascript
vue实现todolist单页面应用
2017/04/11 Javascript
node+express+ejs使用模版引擎做的一个示例demo
2017/09/18 Javascript
深入浅析Vue中mixin和extend的区别和使用场景
2019/08/01 Javascript
vue实现点击追加选中样式效果
2019/11/01 Javascript
微信小程序之左右布局的实现代码
2019/12/13 Javascript
用Python代码来绘制彭罗斯点阵的教程
2015/04/03 Python
解决Python中由于logging模块误用导致的内存泄露
2015/04/23 Python
简单介绍Python中的几种数据类型
2016/01/02 Python
python遍历文件夹,指定遍历深度与忽略目录的方法
2018/07/11 Python
使用WingPro 7 设置Python路径的方法
2019/07/24 Python
ProBikeKit英国:在线公路自行车之家
2017/02/10 全球购物
美术专业学生个人自我评价
2013/09/19 职场文书
2014乡镇“三八”国际劳动妇女节活动总结
2014/03/01 职场文书
药店采购员岗位职责
2014/09/30 职场文书
大学辅导员述职报告
2015/01/10 职场文书
仓库统计员岗位职责
2015/04/14 职场文书
公司开会通知
2015/04/20 职场文书
毕业设计致谢语
2015/05/14 职场文书
扩展多台相同的Web服务器
2021/04/01 Servers
idea编译器vue缩进报错问题场景分析
2021/07/04 Vue.js
IDEA2021.2配置docker如何将springboot项目打成镜像一键发布部署
2021/09/25 Java/Android