自己动手做一个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
4.与数据库的连接
Oct 09 PHP
十天学会php之第十天
Oct 09 PHP
php 数组的创建、调用和更新实现代码
Mar 09 PHP
探讨PHP删除文件夹的三种方法
Jun 09 PHP
php读取csv文件并输出的方法
Mar 14 PHP
joomla数据库操作示例代码
Jan 06 PHP
Laravel 的数据库迁移的方法
Jul 31 PHP
PHP闭包定义与使用简单示例
Apr 13 PHP
实例讲解PHP中使用命名空间
Jan 27 PHP
Linux下安装Memcached服务器和客户端与PHP使用示例
Apr 15 PHP
php实现微信和支付宝支付的示例代码
Aug 11 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
基于mysql的bbs设计(二)
2006/10/09 PHP
Zend Studio for Eclipse的java.lang.NullPointerException错误的解决方法
2008/12/06 PHP
PHP 数据库树的遍历方法
2009/02/06 PHP
php数据结构与算法(PHP描述) 查找与二分法查找
2012/06/21 PHP
PHP中文分词 自动获取关键词介绍
2012/11/13 PHP
PHP中的替代语法简介
2014/08/22 PHP
Thinkphp单字母函数使用指南
2016/05/08 PHP
PHP操作mysql数据库分表的方法
2016/06/09 PHP
Yii框架用户登录session丢失问题解决方法
2017/01/07 PHP
js获取TreeView控件选中节点的Text和Value值的方法
2012/11/24 Javascript
JS中图片缓冲loading技术的实例代码
2013/08/29 Javascript
ie浏览器使用js导出网页到excel并打印
2014/03/11 Javascript
再谈javascript原型继承
2014/11/10 Javascript
你不需要jQuery(三) 新AJAX方法fetch()
2016/06/14 Javascript
JS for...in 遍历语句用法实例分析
2016/08/24 Javascript
Vue无限滑动周选择日期的组件的示例代码
2018/07/18 Javascript
jQuery中使用validate插件校验表单功能
2019/05/24 jQuery
在JavaScript中如何访问暂未存在的嵌套对象
2019/06/18 Javascript
Python脚本实现Web漏洞扫描工具
2016/10/25 Python
详解python3中tkinter知识点
2018/06/21 Python
pycharm打开命令行或Terminal的方法
2019/01/16 Python
基于Python的ModbusTCP客户端实现详解
2019/07/13 Python
使用Tensorflow实现可视化中间层和卷积层
2020/01/24 Python
基于python求两个列表的并集.交集.差集
2020/02/10 Python
手把手教你安装Windows版本的Tensorflow
2020/03/26 Python
keras的ImageDataGenerator和flow()的用法说明
2020/07/03 Python
python 获取字典键值对的实现
2020/11/12 Python
英语教师岗位职责
2014/03/16 职场文书
航空学院求职信
2014/06/11 职场文书
融资合作协议书范本
2014/10/17 职场文书
2014年敬老院工作总结
2014/12/08 职场文书
主持人大赛开场白
2015/05/29 职场文书
红十字会救护培训简讯
2015/07/20 职场文书
素质教育学习心得体会
2016/01/19 职场文书
Java 中的 Unsafe 魔法类的作用大全
2021/06/26 Java/Android
十大最强奥特曼武器:怪兽战斗仪在榜,第五奥特之父只使用过一次
2022/03/18 日漫