自己动手做一个SQL解释器
在一些小型的应用中,完全没有必要使用大型数据库软件。自己做一个SQL解释器就能用数据库的方式来管理了。
这个解释器,能解释常用的SQL命令。你可以自行添加其他功能。
1
2class DB_text {
3var $conn;
4var $classname = "db_text";
5var $database;
6function on_create() {
7}
8function connect($database_name) {
9$this->database = $database_name;
10if(! file_exists($database_name)) {
11$this->conn = array();
12$this->_close();
13}
14$fp = fopen($this->database,"r");
15$this->conn = unserialize(fread($fp,filesize($this->database)));
16fclose($fp);
17}
18function &query($query) {
19if(eregi("select ",$query)) return $this->_select($query);
20if(eregi("insert ",$query)) return $this->_insert($query);
21if(eregi("delete ",$query)) return $this->_delete($query);
22if(eregi("update ",$query)) return $this->_update($query);
23return array();
24}
25function fetch_row(&$result) {
26if(list($key,$value) = each($result))
27return $value;
28return false;
29}
30function num_rows($result) {
31return count($result);
32}
33
34/**
35* query的辅助函数
36*/
37function _select($query) {
38if(eregi("(order by (.+))",$query,$regs)) {
39$order = $regs[2];
40$query = eregi_replace($regs[1],"",$query);
41}
42if(eregi("(group by (.+))",$query,$regs)) {
43$group = $regs[2];
44$query = eregi_replace($regs[1],"",$query);
45}
46eregi("select .* from ([0-9a-z_]+) *(where +(.+))?",$query,$regs);
47if($regs[3] != "") {
48$keys = $this->_where($regs[3],"\$this->conn[$regs[1]]");
49while(list($key,$value) = each($keys)) {
50$rs[] = $this->conn[$regs[1]][$value];
51}
52}else {
53$rs = $this->conn[$regs[1]];
54}
55if($order) {
56sscanf($order,"%s %s",$key,$type);
57if(empty($type)) $type = "asc";
58$this->_sort($rs,$key,$type);
59}
60return $rs;
61}
62function _insert($query) {
63eregi("insert +into +([0-9a-z_]+) *(.+) *values? *(.+)",$query,$regs);
64eval("\$key=array$regs[2];");
65eval("\$value=array$regs[3];");
66for($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;
}
1
2测试例:
3<pre>
//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);
1</pre></count($v);$i+=2)></count($key);$i++)>