自己动手做一个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 相关文章推荐
IIS环境下快速安装、配置和调试PHP5.2.0
Dec 17 PHP
ie6 动态缩略图不显示的原因
Jun 21 PHP
关于JSON以及JSON在PHP中的应用技巧
Nov 27 PHP
CentOS 6.3下安装PHP xcache扩展模块笔记
Sep 10 PHP
PHP易混淆函数的区别及用法汇总
Nov 22 PHP
php实现图片添加描边字和马赛克的方法
Dec 10 PHP
php获取百度收录、百度热词及百度快照的方法
Apr 02 PHP
PHP限制HTML内容中图片必须是本站的方法
Jun 16 PHP
php基于Snoopy解析网页html的方法
Jul 09 PHP
PHP对象克隆clone用法示例
Sep 28 PHP
PHP查询大量数据内存耗尽问题的解决方法
Oct 28 PHP
PHP设计模式之装饰器模式定义与用法简单示例
Aug 13 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
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
ThinkPHP php 框架学习笔记
2009/10/30 PHP
php下连接ftp实现文件的上传、下载、删除文件实例代码
2010/06/03 PHP
《PHP编程最快明白》第四讲:日期、表单接收、session、cookie
2010/11/01 PHP
php 冒泡排序 交换排序法
2011/05/10 PHP
解决cPanel无法安装php5.2.17
2014/06/22 PHP
php单例模式实现方法分析
2015/03/14 PHP
thinkphp 验证码 的使用小结
2017/05/07 PHP
浅谈PHPANALYSIS提取关键字
2019/03/08 PHP
JavaScript(js)设置默认输入焦点(focus)
2012/12/28 Javascript
javascript 获取网页标题代码实例
2014/01/22 Javascript
JavaScript比较两个对象是否相等的方法
2015/02/06 Javascript
jQuery选择id属性带有点符号元素的方法
2015/03/17 Javascript
nodejs中的fiber(纤程)库详解
2015/03/24 NodeJs
JS实现下拉菜单赋值到文本框的方法
2015/08/18 Javascript
JS实现星星评分功能实例代码(两种方法)
2016/06/09 Javascript
Vue.js 表单校验插件
2016/08/14 Javascript
webpack教程之webpack.config.js配置文件
2017/07/05 Javascript
JS+HTML5 FileReader实现文件上传前本地预览功能
2020/03/27 Javascript
React Native中TabBarIOS的简单使用方法示例
2017/10/13 Javascript
js实现轮播图效果 纯js实现图片自动切换
2020/08/09 Javascript
[45:17]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第三场 1月9日
2021/03/11 DOTA
Python实现删除当前目录下除当前脚本以外的文件和文件夹实例
2015/07/27 Python
Python的MongoDB模块PyMongo操作方法集锦
2016/01/05 Python
TensorFlow自定义损失函数来预测商品销售量
2020/02/05 Python
python能否java成为主流语言吗
2020/06/22 Python
使用PyWeChatSpy自动回复微信拍一拍功能的实现代码
2020/07/02 Python
金讯Java笔试题目
2013/06/18 面试题
新闻专业学生的自我评价
2014/02/13 职场文书
地质工程专业毕业生求职信
2014/08/08 职场文书
党的生日演讲稿
2014/09/10 职场文书
法定代表人身份证明书(含说明)
2014/10/02 职场文书
证券区域经理岗位职责
2015/04/10 职场文书
工作报告范文
2019/06/20 职场文书
Nginx中break与last的区别详析
2021/03/31 Servers
Java使用jmeter进行压力测试
2021/07/09 Java/Android