自己动手做一个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应用程序来获取Web服务器的状态信息
Oct 09 PHP
Win2003下APACHE+PHP5+MYSQL4+PHPMYADMIN 的简易安装配置
Nov 18 PHP
解决控件遮挡问题:关于有窗口元素和无窗口元素
Jan 28 PHP
php对gzip文件或者字符串解压实例参考
Jul 25 PHP
PHP 伪静态技术原理以及突破原理实现介绍
Jul 12 PHP
PHP数字和字符串ID互转函数(类似优酷ID)
Jun 30 PHP
ThinkPHP关于session的操作方法汇总
Jul 18 PHP
php获取随机数组列表的方法
Nov 13 PHP
php获取访问者浏览页面的浏览器类型
Jan 23 PHP
万能的php分页类
Jul 06 PHP
Yii2框架自定义验证规则操作示例
Feb 08 PHP
laravel框架 api自定义全局异常处理方法
Oct 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
解析php中如何调用用户自定义函数
2013/08/06 PHP
php中adodbzip类实例
2014/12/08 PHP
Symfony2函数用法实例分析
2016/03/18 PHP
深入浅析yii2-gii自定义模板的方法
2016/04/26 PHP
Yii框架实现多数据库配置和操作的方法
2017/05/25 PHP
JavaScript动态调整TextArea高度的代码
2010/12/28 Javascript
js 上下左右键控制焦点(示例代码)
2013/12/14 Javascript
JavaScript实现带标题的图片轮播特效
2015/05/20 Javascript
Bootstrap3.0学习教程之JS折叠插件
2016/05/27 Javascript
javascript数组去重常用方法实例分析
2017/04/11 Javascript
React应用中使用Bootstrap的方法
2017/08/15 Javascript
JavaScript实现的反序列化json字符串操作示例
2018/07/18 Javascript
jQuery实现表格的增、删、改操作示例
2019/01/27 jQuery
vue使用el-upload上传文件及Feign服务间传递文件的方法
2019/03/15 Javascript
vue开发拖拽进度条滑动组件
2019/09/21 Javascript
VUE单页面切换动画代码(全网最好的切换效果)
2019/10/31 Javascript
基于js实现逐步显示文字输出代码实例
2020/04/02 Javascript
jQuery实现查看图片功能
2020/12/01 jQuery
[01:29:31]VP VS VG Supermajor小组赛胜者组第二轮 BO3第一场 6.2
2018/06/03 DOTA
wxpython学习笔记(推荐查看)
2014/06/09 Python
Python实现测试磁盘性能的方法
2015/03/12 Python
在Python程序中操作MySQL的基本方法
2015/07/29 Python
约瑟夫问题的Python和C++求解方法
2015/08/20 Python
Python单元测试简单示例
2018/07/03 Python
详解Python中的type和object
2018/08/15 Python
python json 递归打印所有json子节点信息的例子
2020/02/27 Python
床上用品全球在线购物:BeddingInn
2016/12/18 全球购物
Timex手表官网:美国运动休闲手表品牌
2017/01/28 全球购物
美国儿童玩具、装扮和玩偶商店:Magic Cabin
2018/09/02 全球购物
Amcal中文官网:澳洲综合性连锁药房
2019/03/28 全球购物
下列程序在32位linux或unix中的结果是什么
2015/01/26 面试题
公司面试感谢信
2014/02/01 职场文书
户外婚礼策划方案
2014/02/08 职场文书
幸福家庭标语
2014/06/27 职场文书
2016十一国庆节感言
2015/12/09 职场文书
python 实现德洛内三角剖分的操作
2021/04/22 Python