自己动手做一个SQL解释器

自己动手做一个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>

时间: 2024-11-02 04:46:27

自己动手做一个SQL解释器的相关文章

自已动手做一个最简版的Nhibernate

最近动手做一个项目,结果项目延期了,自己分析一下,大部分的时间花在了与项目中数据的持久化那一块了,觉得自己有点吃亏,原因是自己对Nhiberate不太熟,经常出错,并且,一个很小的项目,所有的东西加起来都不到1M,却因为引用了Nhibernate,加上Nhiberante必须用的几个DLLL很整个工程变得很大,觉得有点过分,所以想来想去,就决定做一个自己版的Nhiberate,这是第一个版本的代码,刚刚写出来, 其中的东西,都集中在了静态类里了,还在要类中实现自己的load,update,ins

自己动手做一个迷你Linux系统

本文将带领大家构建一个迷你型的Linux 系统.它占用的硬盘空间远小于 16M 字节,但是却包括了 XFree86 的 X Window 窗口系统. 目标 本文要构建的这个迷你型的 Linux 系统只能在一台特定的单机上运行,如果读者朋友们有兴趣的话,在这个系统的基础上加以改进,是可以构建出通用的.可以在大多数常规 PC 机上即插即用的系统来的.但是这已经不在本文的话题之内了,读者朋友们如果有兴趣,可以通过我的电子邮件和我讨论其中的细节问题. 我们的目标 Linux 系统运行在一台普通的 Int

我的U盘会唱歌 你也动手做一个吧

U盘也能像CD一样插入电脑就自动播放,如自动全屏播放Flash或课件等.我们现在要来打造一款一插入电脑就能唱歌的U盘. 1.下载AutoFlash.exe,安装后不用作任何设置.如果要卸载AutoFlash.exe,直接删除就可以了. 2.下载MP3TOEXE的小软件.MP3TOEXE是一款将音乐文件(包括MP3.WMA.MID.WAV等)转换为EXE的小工具软件. 打开MP3TOEXE后,单击"歌曲文件"框后的"选择"按钮,选择一首要转换的MP3文件,再单击&qu

数据库是sql server,现有两张表,用lambda表达式做一个查询

问题描述 数据库是sql server,现有两张表,用lambda表达式做一个查询 表t1有7个字段,包括id,code:表t2有5个字段,包括id: 现在要查询:t2上id与t1上的id相同且code为3的t1上的所有字段. 解决方案 var query = from x in t1 join y in t2 on x.id equals y.id where x.code == 3 select new { x, y };

在用VS2010和SQL做一个web开发,求指导解答

问题描述 小弟在做一个GIS设计与实验的结课系统设计实施目前有些问题,求各位大神指导本人纯属第一次自己搞一个什么东西,完全的菜鸟若问题过于低端请谅解首先我的想法是先有一个登录界面,与数据库连接的,验证用户与密码成功后进入主页面主页面中具备的功能就是通过一些下拉选项来选定查询一些数据,并且也是连接数据库的,从数据库中导出相应数据,并在网页的相应位置显示出来再设置一个分析按钮,点击后通过一些算法分析出数据的优良水平等,在网页中显示现在有如下问题:1.不懂得两个用VS2010连接sql数据库的asp.

数据库-怎么用vb.net和sql做一个简易选课系统

问题描述 怎么用vb.net和sql做一个简易选课系统 数据库用mysql好还是sql sever好?还有我想用自己的电脑作为管理端,因为选课的人不多,我想建立一个小型局域网,这要怎么设置? 解决方案 都一样,选择相应的ADO接口,其他的都一样

用asp.net做一个HR的管理系统,目前就卡在考情上面。请教一个SQL语句(在线等。马上结分)

问题描述 图2中的数据为打卡数据,有重复打卡的,和没打卡的.想插入到图1中.图一中只要一天4个打卡的时间,(注意是每天都会往表一中插入表二中新采集的数据哦)多余的不要.请教SQL语句.如果没打卡就为null或者是''谢谢各位大神!!!!!!! 解决方案 解决方案二:要么用存储过程,要么用程序代码实现,一句话的SQL基本无法实现.解决方案三:应该是这样的,表2中的数据应当先根据日期时间进行处理.按照你说的,一天有4个时间段:8:00-9:0012:00-13:0013:45-14:0017:50-

sql server-用VISUAL STUDIO与SQL SERVER做一个系统

问题描述 用VISUAL STUDIO与SQL SERVER做一个系统 用VISUAL STUDIO与SQL SERVER做一个系统,要求有三张表,有查.插.删.改的功能 解决方案 参考http://www.cnblogs.com/csonezp/archive/2012/12/27/2835472.htmlhttp://download.csdn.net/detail/lingtao129/5110574http://wenku.baidu.com/link?url=mmq0W7vkMKN3l

自己动手,结合javascript和dhtml做一个ubb编辑器

dhtml|javascript|ubb    看到chinaASP论坛的abc code editor了吗?是不是觉得很cool? 说真的,刚见到我还以为是用别的什么语言做的控件呢,后来才发现没有那么神秘的.前几天做一个商品bbs,客户要求支持ubb,同时也要做一个编辑器.现在我把做ubb的思路给大家讲一下.    首先遇到的是界面问题,实际上这个很好解决,只是利用td的onmouseover.onmouseout和onmousedown来实现,具体实现方法件下面的代码.    其次就是实现文