自己动手做一个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 代码优化之经典示例
Mar 24 PHP
php模拟socket一次连接,多次发送数据的实现代码
Jul 26 PHP
DOM XPATH获取img src值的query
Sep 23 PHP
PHP 只允许指定IP访问(允许*号通配符过滤IP)
Jul 08 PHP
PHP将进程作为守护进程的方法
Mar 19 PHP
Discuz!X中SESSION机制实例详解
Sep 23 PHP
php对文件夹进行相关操作(遍历、计算大小)
Nov 04 PHP
开启PHP的伪静态模式
Dec 31 PHP
php数组函数array_walk用法示例
May 26 PHP
php版微信支付api.mch.weixin.qq.com域名解析慢原因与解决方法
Oct 12 PHP
使用PHP开发留言板功能
Nov 19 PHP
PHP+ajax实现上传、删除、修改单张图片及后台处理逻辑操作详解
Feb 12 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 addslashes 利用递归实现使用反斜线引用字符串
2013/08/05 PHP
php缓存技术详细总结
2013/08/07 PHP
使用PHP实现微信摇一摇周边红包
2016/01/04 PHP
Thinkphp 框架配置操作之动态配置、扩展配置及批量配置实例分析
2020/05/15 PHP
EasyUI的treegrid组件动态加载数据问题的解决办法
2011/12/11 Javascript
window.showModalDialog参数传递中含有特殊字符的处理方法
2013/06/06 Javascript
$.getJSON在IE下失效的原因分析及解决方法
2013/06/16 Javascript
bootstrap data与jquery .data
2014/07/07 Javascript
浏览器缩放检测的js代码
2014/09/28 Javascript
bootstrap监听滚动实现头部跟随滚动
2016/11/08 Javascript
js中的DOM模拟购物车功能
2017/03/22 Javascript
vue router路由嵌套不显示问题的解决方法
2017/06/17 Javascript
js实现图片上传预览原理分析
2017/07/13 Javascript
vue.js项目nginx部署教程
2018/04/05 Javascript
图文讲解用vue-cli脚手架创建vue项目步骤
2019/02/12 Javascript
js通过循环多张图片实现动画效果
2019/12/19 Javascript
Vue引入Stylus知识点总结
2020/01/16 Javascript
Vue Elenent实现表格相同数据列合并
2020/11/30 Vue.js
解决基于 keep-alive 的后台多级路由缓存问题
2020/12/23 Javascript
python实现的系统实用log类实例
2015/06/30 Python
python搭建微信公众平台
2016/02/09 Python
Python实现的连接mssql数据库操作示例
2018/08/17 Python
Python的UTC时间转换讲解
2019/02/26 Python
Python实现图片指定位置加图片水印(附Pyinstaller打包exe)
2021/03/04 Python
Html5 new XMLHttpRequest()监听附件上传进度
2021/01/14 HTML / CSS
Qoo10马来西亚:全球时尚和引领潮流的购物市场
2016/08/25 全球购物
兰芝美国网上商城:购买LANEIGE睡眠面膜等
2017/06/30 全球购物
GIVENCHY纪梵希官方旗舰店:高定彩妆与贵族护肤品
2018/04/16 全球购物
您在慕尼黑的跑步商店:Lauf-bar
2019/10/11 全球购物
大学生最新职业生涯规划书范文
2014/01/12 职场文书
合作协议书怎么写
2014/04/18 职场文书
某集团股份有限公司委托书样本
2014/09/24 职场文书
业务内勤岗位职责
2015/04/13 职场文书
银行岗位培训心得体会
2016/01/09 职场文书
Go语言 go程释放操作(退出/销毁)
2021/04/30 Golang
Python实现天气查询软件
2021/06/07 Python