自己动手做一个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开发规范手册之PHP代码规范详解
Jan 13 PHP
写php分页时出现的Fatal error的解决方法
Apr 18 PHP
php中使用exec,system等函数调用系统命令的方法(不建议使用,可导致安全问题)
Sep 07 PHP
PHP实现返回JSON和XML的类分享
Jan 28 PHP
7个鲜为人知却非常实用的PHP函数
Jul 01 PHP
yii实现model添加默认值的方法(2种方法)
Jan 06 PHP
PHP 数组遍历foreach语法结构及实例
Jun 13 PHP
php自定义函数实现二维数组按指定key排序的方法
Sep 29 PHP
详解PHP处理密码的几种方式
Nov 30 PHP
PHP中ajax无刷新上传图片与图片下载功能
Feb 21 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
Jul 21 PHP
php使用curl模拟多线程实现批处理功能示例
Jul 25 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
基于wordpress主题制作的具体实现步骤
2013/05/10 PHP
探讨:使用XMLSerialize 序列化与反序列化
2013/06/08 PHP
WordPress中邮件的一些修改和自定义技巧
2015/12/15 PHP
解析PHP之提取多维数组指定列的方法
2017/01/03 PHP
全面解析PHP面向对象的三大特征
2017/06/10 PHP
php7新特性的理解和比较总结
2019/04/14 PHP
原来Jquery.load的方法可以一直load下去
2011/03/28 Javascript
关于 文本框默认值 的操作js代码
2012/01/12 Javascript
Javascript数组操作函数总结
2015/02/05 Javascript
JS+CSS实现感应鼠标渐变显示DIV层的方法
2015/02/20 Javascript
jQuery实现有动画淡出效果的二级折叠菜单代码
2015/10/17 Javascript
通过node-mysql搭建Windows+Node.js+MySQL环境的教程
2016/03/01 Javascript
JS Array创建及concat()split()slice()的使用方法
2016/06/03 Javascript
JSONP跨域请求实例详解
2016/07/04 Javascript
详解vue组件通信的三种方式
2017/06/30 Javascript
JavaScript解析任意形式的json树型结构展示
2017/07/23 Javascript
微信小程序MUI导航栏透明渐变功能示例(通过改变rgba的a值实现)
2019/01/24 Javascript
解决vue v-for src 图片路径问题 404
2019/11/12 Javascript
在Vue中创建可重用的 Transition的方法
2020/06/02 Javascript
30分钟搭建Python的Flask框架并在上面编写第一个应用
2015/03/30 Python
python使用webbrowser浏览指定url的方法
2015/04/04 Python
画pytorch模型图,以及参数计算的方法
2019/08/17 Python
Python IDE环境之 新版Pycharm安装详细教程
2020/03/05 Python
Python使用tkinter实现摇骰子小游戏功能的代码
2020/07/02 Python
Python内置函数property()如何使用
2020/09/01 Python
python 5个顶级异步框架推荐
2020/09/09 Python
用python读取xlsx文件
2020/12/17 Python
CSS3 绘制BMW logo实的现代码
2013/04/25 HTML / CSS
台湾母婴用品限时团购:妈咪爱
2018/08/03 全球购物
C#如何允许一个类被继承但是避免这个类的方法被重载?
2015/02/24 面试题
同学会邀请书大全
2014/01/12 职场文书
商务英语广告词大全
2014/03/18 职场文书
新闻专业毕业生英文求职信
2014/03/19 职场文书
公司应聘自荐书
2014/06/14 职场文书
致运动员赞词
2015/07/22 职场文书
如何撰写促销方案?
2019/07/05 职场文书