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