自己动手做一个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 相关文章推荐
用Apache反向代理设置对外的WWW和文件服务器
Oct 09 PHP
通过html表格发电子邮件
Oct 09 PHP
php获得当前的脚本网址
Dec 10 PHP
使用PHP提取视频网站页面中的FLASH地址的代码
Apr 17 PHP
PHP下对字符串的递增运算代码
Aug 21 PHP
PHP和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍
Jul 03 PHP
PHP中几个常用的魔术常量
Feb 23 PHP
php 截取utf-8格式的字符串实例代码
Oct 30 PHP
PHP结合Vue实现滚动底部加载效果
Dec 17 PHP
laravel邮件发送的实现代码示例
Jan 31 PHP
php7 list()、session及其他模块的修改实例分析
May 25 PHP
PHP7 新增功能
Mar 09 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实现scws中文分词搜索的方法
2015/12/25 PHP
Thinkphp和onethink实现微信支付插件
2016/04/13 PHP
PHP删除二维数组中相同元素及数组重复值的方法示例
2017/05/05 PHP
php实现简单四则运算器
2020/11/29 PHP
javascript 一段左右两边随屏滚动的代码
2009/06/18 Javascript
JavaScript 题型问答有答案参考
2010/02/17 Javascript
jQuery学习笔记 获取jQuery对象
2012/09/19 Javascript
javascript判断机器是否联网的2种方法
2013/08/09 Javascript
Extjs表单常见验证小结
2014/03/07 Javascript
JS实现关闭当前页而不弹出提示框的方法
2016/06/22 Javascript
js 动态给元素添加、移除事件的实现方法
2016/07/19 Javascript
详解angular中如何监控dom渲染完毕
2017/01/03 Javascript
angularjs实现的前端分页控件示例
2017/02/10 Javascript
原生js实现仿window10系统日历效果的实例
2017/10/31 Javascript
Vue 实现手动刷新组件的方法
2019/02/19 Javascript
js实现无缝滚动双图切换效果
2019/07/09 Javascript
vue+elementUI组件table实现前端分页功能
2020/11/15 Javascript
Vuex的各个模块封装的实现
2020/06/05 Javascript
iview实现图片上传功能
2020/06/29 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
[04:32]DOTA2著名解说配音敌法师 现场专访海涛怒切假腿
2013/12/20 DOTA
Python3之文件读写操作的实例讲解
2018/01/23 Python
python 通过麦克风录音 生成wav文件的方法
2019/01/09 Python
在Python中调用Ping命令,批量IP的方法
2019/01/26 Python
Python Pandas中根据列的值选取多行数据
2019/07/08 Python
python2与python3爬虫中get与post对比解析
2019/09/18 Python
python--shutil移动文件到另一个路径的操作
2020/07/13 Python
详解如何通过H5(浏览器/WebView/其他)唤起本地app
2017/12/11 HTML / CSS
欧洲最大的高尔夫零售商:American Golf
2019/09/02 全球购物
一年级评语大全
2014/04/23 职场文书
加入学生会演讲稿
2014/04/24 职场文书
学雷锋月活动总结
2014/04/25 职场文书
绿色环保标语
2014/06/12 职场文书
2014年小学教师工作自我评价
2014/09/22 职场文书
四风问题专项整治工作情况报告
2014/10/28 职场文书
php 防护xss,PHP的防御XSS注入的终极解决方案
2021/04/01 PHP