复杂数据类型抽取支持

来源:互联网 发布:自学电脑编程 编辑:程序博客网 时间:2024/05/22 11:48

复杂数据类型是指一个数据对象(实体)涉及多个数据库表,表之间的逻辑关系可以用一个树形结构表示。
在该树形结构中,每个表是其中的一个节点。
.仅有一个根
.除根以外的节点,有且仅有一个父节点.

主从等价父子。以A-->B表示A是B的主表,A是父节点,B为子节点.
复杂数据类型的支持实际上通过以下2种结构的支持实现。

(1)A-->B-->C
A: select f1,f2,f3 from t1 
主键列:f1,f2
B: select t2.f1,t2.f2,t2.f3 from t2,t1 where t1.f1=t2.f1 and t1.f2=t2.f2 and
t2.f1=@f1 and t2.f2=@f2
---@f1,@f2为A抽取的对应的f1,f2字段的值
C: select t3.f1,t3.f2,t3.f3 from t3,t2 where t2.f1=t3.f1 and
t2.f1=@f1
---@f1为B抽取的对应的f1的字段值.

声明主键列的作用只是用来记录已抽取单据(对象)。
主表查询列必须包含从表关联的字段,如果是表达式则必须指定别名.
抽取规则中的参数来自父表.

(2)A-->B,A-->C:
A: select f1,f2,f3 from t1 
B: select t2.f1,t2.f2,t2.f3 from t2,t1 where t1.f1=t2.f1 and t1.f2=t2.f2 and
t2.f1=@f1 and t2.f2=@f2
C: select t2.f1,t2.f2,t2.f3 from t3,t1 where t1.f1=t3.f1 and t1.f2=t3.f2 andt3.f1=@f1 andt3.f2=@f2

多个表在未指定关联关系时,默认是一主多从的情况.


系统对参数的处理最早来源于C处理printf的方法,使用"%s"作为参数占位符。
这种方式有2个缺陷:
(1)当抽取命令需要使用to_date等数据库函数时,无法支持,只能采用烦琐和低效的变通办法处理
(2)同一个参数出现多次时无法支持

改用"@参数名"方式后可以解决上述问题.
为了保证兼容性,抽取规则中引入以下参数:
<parameterize_version>2</parameterize> <!-- 抽取命令参数化版本 1-%s 2-@参数名 默认:1 -->

对于<parameterize_version>为1的情况,先把%s占位符用字段列表名称作为参数替换。
如主键字段列为:f1,f2.
则把参数化版本为1的抽取命令:
select f1,f2,f3 from t2 where f1='%s' and f2='%s'
替换为:
select f1,f2,f3 from t2 where
f1='@f1' andf2='@f2'.

这样,可以把2种版本的配置统一处理.

以下是参数化提升的代码:
int CRule::UpParam() {
 if (cmd_parameterize_version_!=1)
  return 0;
 
 CAutoVector<RuleCommand*>::iterator iter = cmds_.begin();
 while(iter!=cmds_.end()) {
  RuleCommand *rc = *iter;
  vector<int> v_pos; ///< 每个参数的开始位置
  size_t offset = 0;
  const int hold_len = 2;///< %s长度
  do {
   size_t pos = sql.find("%s",offset);
   if (pos==string::npos)
    break;
   v_pos.push_back(pos);

   offset = pos+hold_len;
  } while(1);

  if (keys_.size()<v_pos.size()) { ///< 严格意义上,两者应该相同.如果主键列数少于配置的%s个数,则属于配置错误.
   return -1;
  }
  if (v_pos.size()==0) {
   iter++;
   continue;
  }
  offset = 0;
  string sql;
  for (int i=0;i<v_pos.size();i++) {
   int pos = v_pos[i];
   sql += rc->sql.substr(offset,pos-offset);
   sql += keys_[i]->name_;
   offset = pos+hold_len;
  }
  sql += sql.substr(offset);
  rc->sql = sql;

  iter++;
 }

 return 0;
}

原创粉丝点击