数据库技术之存储过程设计与实现(三)

时间:2022-09-10 08:18:37

原创性声明

此博文的出处 为 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/

邮箱: zhujunxxxxx@163.com

 

测试类

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();
		
	}

}