原创性声明
此博文的出处 为 http://blog.csdn.net/zhujunxxxxx/article/details/39251241如果进行转载请注明出处。本文作者原创,邮箱zhujunxxxxx@163.com,如有问题请联系作者
一个java模拟的存储过程
在前两篇博客中介绍了存储过程的设计方法和数据结构。但是没有一个例子恐怕文章在好也没有很容易理解把
为此博主专门给了一个实例,我用java模拟了一个存储过程来实现,由于java下我没有进行词法语法解析,所以我的语法树就得自己来构造了(这真累)
我的所有表达式计算都是通过数据引擎计算的(其实很多数据库的存储过程都是这样的 比如postgresql)
先把给出我的数据结构
数据结构类
package java_test; import java.util.List; enum NodeType { t_none,t_var,t_stmt,t_create,t_declare,t_set,t_expr, t_if,t_elseif,t_when,t_case,t_while,t_for, t_exec,t_proc } enum DataType{ TT_INT,TT_CHAR,TT_BOOL,TT_DATE,TT_TIME,TT_APPROXNUM,TT_NULL,TT_VAR,TT_EXPR,TT_SIGN } class Node { int dno; NodeType node_type; } class VarNode extends Node{ String var_name; DataType data_type; int isconst; int notnull; String default_val;/*默认值*/ int isnull; String setvalue;/*赋值过后值*/ ExprNode expr_value; } class DeclareNode extends Node{ List<Node> var_list;/*这个declare语句所包含的变量*/ } class DeclNode extends Node{ /*定义存储过程的节点*/ String proc_name;/*存储过程名*/ List<Node> params;/*存储过程参数*/ } /*终结点*/ class ProcNode extends Node{ DeclNode declnode;/*定义存储过程的节点*/ List<Node> proc_body;/*存储过程的具体块,我觉得它有各种 if-else declare set sql when-case for while 构成的list*/ List<Node> except_list;/*异常列表*/ } class StmtNode extends Node{/*具体的一个sql语句节点*/ int sql_type; String str_sql; List<Node> params;/*此sql语句的参数*/ } class SetNode extends Node{ List<Node> var_list;/*这个set语句所包含的变量,和具体的值*/ } class ExprNode extends Node{ int is_const;/*是否是常量 -1 0 1*/ int is_wrap;/*是否有括号*/ DataType data_type;/*类型*/ String const_value;/*常量表达式的*/ String sign; String param; String str_value;/*无用*/ VarNode var_value;/*变量表达式的变量*/ ExprNode lnext; ExprNode rnext; } class IfNode extends Node{ ExprNode expr; List<Node> then_body; List<Node> elseif_body; List<Node> else_body; } class ElseIfNode extends Node{ ExprNode expr; List<Node> body; } class CaseNode extends Node{ ExprNode expr; List<Node> case_list; int have_else; List<Node> else_stmts; } class WhenNode extends Node{ ExprNode expr; List<Node> stmts; } class WhileNode extends Node{ ExprNode expr; List<Node> body; } class ForNode extends Node{ ExprNode lower; ExprNode upper; ExprNode step; List<Node> body; } class ProcExecState{ int dno; ProcNode proc; int rettype; Node lastnode; Node nextnode; String error; } class Dataum { DataType type; String value; boolean is_init; public Dataum(DataType t) { this.type=t; is_init=false; } public Dataum(DataType t,String v) { this.type=t; this.value=v; is_init=true; } }
这个类就是我们基本的数据结构
然后是一个解释器类,专门用来解释执行语法树的
解释器类
package java_test; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; enum ProcSQLState { PROC_SQL_RC_ERROR(0), PROC_SQL_RC_OK(1), PROC_SQL_RC_EXIT(2), PROC_SQL_RC_CONTINUE(3), PROC_SQL_RC_RETURN(4); private int nCode ; private ProcSQLState( int _nCode) { this . nCode = _nCode; } public int toInt() { return this.nCode; } @Override public String toString() { return String.valueOf (this.nCode ); } } public class language { public static MysqlHelper mysql=new MysqlHelper(); public static HashMap<String,Object> var_table =new HashMap<String,Object>(); public static int exec_stmts(ProcExecuteState estate,List<Node> stmts) { if(stmts==null) return 0; for (Node node : stmts) { int rc=exec_stmt(estate,node); if(rc==0) return 0; } return 1; } public static int exec_stmt(ProcExecuteState estate,Node stmt) { int rc=-1; switch(stmt.node_type) { case t_if: rc=exec_stmt_if(estate,(IfNode)stmt); break; case t_while: rc=exec_stmt_while(estate,(WhileNode)stmt); break; case t_case: rc=exec_stmt_case(estate,(CaseNode)stmt); break; case t_declare: rc=exec_stmt_declare(estate,(DeclareNode)stmt); break; case t_set: rc=exec_stmt_assign(estate,(SetNode)stmt); break; case t_stmt: rc=exec_stmt_sql(estate,(StmtNode)stmt); break; default: break; } return rc; } public static int exec_stmt_declare(ProcExecuteState estate,DeclareNode stmt) { for (Node node : stmt.var_list) { VarNode vnode=(VarNode)node; if(vnode.isconst!=1) { Dataum data=new Dataum(vnode.data_type); add_var(vnode.var_name,data); } } return 1; } public static int exec_stmt_assign(ProcExecuteState estate,SetNode stmt) { for (Node node : stmt.var_list) { VarNode vnode=(VarNode)node; if(vnode.isconst!=1) { set_value(vnode.var_name,vnode.expr_value); } } return 1; } public static int exec_stmt_if(ProcExecuteState estate,IfNode ifnode) { boolean value; value=exec_eval_bool(estate,ifnode.expr); if(value) return exec_stmts(estate,ifnode.then_body); for (Node item : ifnode.elseif_body) { ElseIfNode eifnode=(ElseIfNode)item; value=exec_eval_bool(estate,eifnode.expr); if(value) return exec_stmts(estate,eifnode.body); } return exec_stmts(estate, ifnode.else_body); } public static int exec_stmt_while(ProcExecuteState estate,WhileNode whilenode) { for(;;) { int rc; boolean value; value = exec_eval_bool(estate, whilenode.expr); if(!value) break; rc = exec_stmts(estate, whilenode.body); ProcSQLState erc=null; switch(rc) { case 0: erc=ProcSQLState.PROC_SQL_RC_ERROR; break; case 1: erc=ProcSQLState.PROC_SQL_RC_OK; break; case 2: erc=ProcSQLState.PROC_SQL_RC_EXIT; break; case 3: erc=ProcSQLState.PROC_SQL_RC_CONTINUE; break; case 4: erc=ProcSQLState.PROC_SQL_RC_RETURN; break; default: break; } switch(erc)//这里是while循环退出的地方 exit break return continue 等 有待完善 { case PROC_SQL_RC_OK: break; case PROC_SQL_RC_EXIT: break; case PROC_SQL_RC_CONTINUE: break; case PROC_SQL_RC_RETURN: break; default: break; } } return 1; } public static int exec_stmt_case(ProcExecuteState estate,CaseNode casenode) { ExprNode val=null; //case expr 的那个变量的值 接下来每一个whennode 的expr和它做比较 如果为真就执行,否则就不执行 if(casenode.expr!=null) { //val=exec_eval_expr(estate,casenode.expr); val=casenode.expr; //exec_assign_value 在这里给变量赋值 } for (Node item : casenode.case_list) { WhenNode whennode=(WhenNode)item; boolean value =exec_eval_compare(val,whennode.expr); if(value) { return exec_stmts(estate, whennode.stmts); } } if(casenode.have_else==1) { return exec_stmts(estate, casenode.else_stmts); } return 1; } public static int exec_stmt_sql(ProcExecuteState estate,StmtNode stmt) { return mysql.exec_update(stmt.str_sql); } //执行表达式,并返回结果 public static boolean exec_eval_bool(ProcExecuteState estate,ExprNode expr) { String sql=String.format("select %s", GetExprString(expr));//获取表达式字符串 return Integer.parseInt(mysql.exec(sql).toString())==1?true:false;//从数据库查询的到结果 } public static boolean exec_eval_compare(ExprNode expr1,ExprNode expr2) { String sql1=String.format("select %s", GetExprString(expr1));//获取表达式字符串 String ret1=mysql.exec(sql1).toString(); String sql2=String.format("select %s", GetExprString(expr2));//获取表达式字符串 String ret2=mysql.exec(sql2).toString(); return ret1.equals(ret2); } public static int exec_eval_int(ProcExecuteState estate,ExprNode expr) { String sql=String.format("select %s", GetExprString(expr)); return Integer.parseInt(mysql.exec(sql).toString()); } public static ExprNode exec_eval_expr(ProcExecuteState estate,ExprNode expr) { return null; } public static void add_var(String var_name,Dataum data) { if(!var_table.containsKey(var_name)) { var_table.put(var_name, data); } } public static void set_value(String var_name,Object value) { ExprNode v=(ExprNode)value; Dataum data; if(v.is_const==1)//是否常量 如果是常量就用常量值 否则就计算该表达式的值 data=new Dataum(v.data_type, v.const_value); else { String sql=String.format("select %s", GetExprString(v));//获取表达式字符串 String ret=mysql.exec(sql).toString();//从数据库查询的到结果 data=new Dataum(v.data_type, ret); } if(!var_table.containsKey(var_name)) { var_table.put(var_name, data); } else { var_table.remove(var_name); var_table.put(var_name, data); } } private static Dataum get_var_value(String var_name) { return (Dataum) var_table.get(var_name); } //获取该表达式节点的 字符串形式 还应该为里面的变量替换为真正的值 public static String expr_str=""; public static String GetExprString(ExprNode expr) { expr_str=""; InOrder(expr); return expr_str; } //中序遍历表达式 private static void InOrder(ExprNode expr) { if(expr==null) return; if(expr.is_wrap==1) expr_str+="("; InOrder(expr.lnext); if(expr.is_const==-1)//+ - * / % >>等 expr_str+=expr.sign; else if(expr.is_const==1) expr_str+=expr.const_value; else if(expr.is_const==0) { Dataum data=get_var_value(expr.var_value.var_name); if(data!=null) { expr_str+=data.value; } else { expr_str+=expr.var_value.var_name; System.out.println(expr.var_value.var_name+" 未赋值"); } } InOrder(expr.rnext); if(expr.is_wrap==1) expr_str+=")"; } public static void show_var() { Iterator iter = var_table.entrySet().iterator(); while(iter.hasNext()) { Map.Entry<String, Object> entry = (Map.Entry<String, Object>) iter.next(); String key = entry.getKey(); Dataum data=(Dataum)entry.getValue(); System.out.println(key+" "+data.value); } } }
可以看出来一个存储过程的执行基本上就是一个递归的过程
此博文的出处 为 http://blog.csdn.net/zhujunxxxxx/article/details/39251241如果进行转载请注明出处。本文作者原创,邮箱zhujunxxxxx@163.com,如有问题请联系作者
作者简介
作者是一名软件工程出生的苦逼程序员,本科阶段也是软件工程,目前研究生在读,热爱新技术,热爱编程,为人幽默,热爱开源。
个人网站:http://www.zhujuncoding.com/
github: https://github.com/zhujunxxxxx/
测试类
public class test3 { public static void main(String[] args) { DeclareNode d1=new DeclareNode();// 定义x 和 y两个变量 d1.node_type=NodeType.t_declare; List<Node> list=new ArrayList<Node>(); VarNode var1=new VarNode(); var1.data_type=DataType.TT_INT; var1.var_name="x"; VarNode var2=new VarNode(); var2.data_type=DataType.TT_INT; var2.var_name="y"; list.add(var1); list.add(var2); d1.var_list=list; SetNode set=new SetNode(); set.node_type=NodeType.t_set; List<Node> setlist=new ArrayList<Node>(); VarNode svar=new VarNode(); //给x 赋值为 1 + 9 svar.data_type=DataType.TT_INT; svar.var_name="x"; ExprNode expr=new ExprNode(); expr.is_const=-1; expr.data_type=DataType.TT_SIGN; expr.sign="+"; ExprNode l=new ExprNode(); l.is_const=1; l.const_value="1"; l.data_type=DataType.TT_INT; ExprNode r=new ExprNode(); r.is_const=1; r.const_value="9"; r.data_type=DataType.TT_INT; expr.lnext=l; expr.rnext=r; svar.expr_value=expr; setlist.add(svar); set.var_list=setlist; /* SetNode set_add=new SetNode(); set_add.node_type=NodeType.t_set; List<Node> setlist_add=new ArrayList<Node>(); VarNode svar_add=new VarNode(); //给x 赋值为 11 svar_add.data_type=DataType.TT_INT; svar_add.var_name="x"; ExprNode expr_add=new ExprNode(); expr_add.is_const=1; expr_add.const_value="11"; svar_add.expr_value=expr_add; setlist_add.add(svar_add); set_add.var_list=setlist_add; */ SetNode set_add=new SetNode(); // x = x + 1 set_add.node_type=NodeType.t_set; List<Node> setlist_add=new ArrayList<Node>(); VarNode svar_add=new VarNode(); // x = svar_add.data_type=DataType.TT_INT; svar_add.var_name="x"; ExprNode expr_add=new ExprNode();// x + 1 expr_add.is_const=-1; expr_add.data_type=DataType.TT_SIGN; expr_add.sign="+"; // + ExprNode lexpr_add=new ExprNode();// x lexpr_add.is_const=0; lexpr_add.data_type=DataType.TT_INT; VarNode var_add=new VarNode(); var_add.data_type=DataType.TT_INT; var_add.var_name="x"; lexpr_add.var_value=var_add; ExprNode rexpr_add=new ExprNode();// 1 rexpr_add.is_const=1; rexpr_add.const_value="1"; rexpr_add.data_type=DataType.TT_INT; expr_add.lnext=lexpr_add; expr_add.rnext=rexpr_add; svar_add.expr_value=expr_add; //x = expr setlist_add.add(svar_add); set_add.var_list=setlist_add; //if(x>10) ExprNode ifexpr=new ExprNode(); //定义一个 if 语句的expr 为x>10 ifexpr.is_const=-1; ifexpr.sign=">"; ifexpr.is_wrap=1; ifexpr.data_type=DataType.TT_SIGN; ExprNode lexpr=new ExprNode(); lexpr.is_const=0; lexpr.data_type=DataType.TT_INT; VarNode var=new VarNode(); var.data_type=DataType.TT_INT; var.var_name="x"; lexpr.var_value=var; ExprNode rexpr=new ExprNode(); rexpr.is_const=1; rexpr.const_value="10"; rexpr.data_type=DataType.TT_INT; ifexpr.lnext=lexpr; ifexpr.rnext=rexpr; List<Node> thenlist=new ArrayList<Node>(); StmtNode sql=new StmtNode(); sql.node_type=NodeType.t_stmt; sql.str_sql="insert into zz_test(name,age) values('true',10);"; thenlist.add(sql); List<Node> elselist=new ArrayList<Node>(); StmtNode sql2=new StmtNode(); sql2.node_type=NodeType.t_stmt; sql2.str_sql="insert into zz_test(name,age) values('false',20);"; elselist.add(sql2); IfNode ifnode=new IfNode(); ifnode.node_type=NodeType.t_if; ifnode.expr=ifexpr; ifnode.then_body=thenlist; ifnode.else_body=elselist; ifnode.elseif_body=new ArrayList<Node>();//赋值为空list //while ( x < 20) WhileNode whilenode =new WhileNode(); whilenode.node_type=NodeType.t_while; ExprNode whileexpr=new ExprNode(); whileexpr.is_const=-1; whileexpr.sign="<"; whileexpr.is_wrap=1; whileexpr.data_type=DataType.TT_SIGN; ExprNode wlexpr=new ExprNode(); wlexpr.is_const=0; wlexpr.data_type=DataType.TT_INT; VarNode wvar=new VarNode(); wvar.data_type=DataType.TT_INT; wvar.var_name="x"; wlexpr.var_value=wvar; ExprNode wrexpr=new ExprNode(); wrexpr.is_const=1; wrexpr.const_value="20"; wrexpr.data_type=DataType.TT_INT; whileexpr.lnext=wlexpr; whileexpr.rnext=wrexpr; whilenode.expr=whileexpr;//设置while 的expe List<Node> whilelist=new ArrayList<Node>(); StmtNode whilesql=new StmtNode(); whilesql.node_type=NodeType.t_stmt; whilesql.str_sql="insert into zz_test(name,age) values('while',10);"; whilelist.add(whilesql); whilelist.add(set_add);//x=x+1 whilenode.body=whilelist;//设置while的body //case case CaseNode casenode=new CaseNode(); //case x then ExprNode caseexpr=new ExprNode(); caseexpr.is_const=0; caseexpr.data_type=DataType.TT_VAR; VarNode casevar=new VarNode(); casevar.data_type=DataType.TT_INT; casevar.var_name="x"; caseexpr.var_value=casevar; casenode.expr=caseexpr;//给casenode 赋值 表达式 casenode.node_type=NodeType.t_case;// 设置类型 casenode.have_else=0; List<Node> caselist=new ArrayList<Node>(); WhenNode when1=new WhenNode();//设置一个when节点 ExprNode whenexpr1=new ExprNode(); whenexpr1.is_const=1; whenexpr1.data_type=DataType.TT_INT; whenexpr1.const_value="11"; when1.expr=whenexpr1;//设置when 11 List<Node> caselist_when1=new ArrayList<Node>(); StmtNode casesql_1=new StmtNode(); casesql_1.node_type=NodeType.t_stmt; casesql_1.str_sql="insert into zz_test(name,age) values('when1',10);"; caselist_when1.add(casesql_1); when1.stmts=caselist_when1;//设置 when1的执行语句 WhenNode when2=new WhenNode(); ExprNode whenexpr2=new ExprNode(); whenexpr2.is_const=1; whenexpr2.data_type=DataType.TT_INT; whenexpr2.const_value="12"; when2.expr=whenexpr2; List<Node> caselist_when2=new ArrayList<Node>(); StmtNode casesql_2=new StmtNode(); casesql_2.node_type=NodeType.t_stmt; casesql_2.str_sql="insert into zz_test(name,age) values('when2',10);"; caselist_when2.add(casesql_2); when2.stmts=caselist_when2; caselist.add(when1); caselist.add(when2); casenode.case_list=caselist;//设置caselist List<Node> root=new ArrayList<Node>(); root.add(d1);//定义x , y root.add(set);// 设置 x等于 1+9 root.add(ifnode); //设置条件 x>10 这时候 10>10 为fasle //root.add(whilenode); root.add(set_add); root.add(set_add);// 设置 x等于 x = x + 1 11 //root.add(set_add);// 设置 x等于 x = x + 1 12 //root.add(set_add);// 设置 x等于 x = x + 1 13 //root.add(set_add);// 设置 x等于 x = x + 1 14 root.add(casenode); //root.add(ifnode); //设置条件 x>10 ProcExecuteState estste=new ProcExecuteState(); language.exec_stmts(estste, root); language.show_var(); } }