IF EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID('[dbo].[sys_sql_genproc_fldval]') AND type = 'P')
DROP PROCEDURE [dbo].[sys_sql_genproc_fldval]
GO

--本存储过程功能：
--生成读取数据源字段变量的存储过程
--  读取字段值通过output变量返回

create procedure [dbo].[sys_sql_genproc_fldval] (
@cmpid int,
@parseid int,
@pretbname varchar(20),--读取该表的后继数据源字段，直到明细表数据源
@indent int,--代码缩进量
@isRecursive int ,--是否递归调用
@hasUpDS int output,--是否有上级
@callFmt nvarchar(1000) output, --调用格式
@script nvarchar(max) output
)
as 
begin
--初始化
select @script='',@hasUpDS=0

declare @preBank varchar(20),@i int,@dsname varchar(20),@prebank2 varchar(20),@varType varchar(10),@predschain varchar(50)
,@varName varchar(20),@fromInd int ,@toInd int, @dschain varchar(50),@hasUpDSs int, @predsname varchar(20),@script2 varchar(max)
,@keyval varchar(20),@preLnkFld varchar(20),@biztype varchar(20),@prekeyval varchar(20),@isDetailTable int
  ,@keyfld varchar(20),@prekeyfld varchar(20),@shortname varchar(20),@bizid int,@tagid int,@preLnkVal varchar(20),@fullName varchar(100)
  ,@defParams varchar(1000), @callParams varchar(1000),@procname varchar(100),@localvar varchar(max),@nextFmt varchar(4000)
  ,@tbname varchar(20)

--TODO:生成取字段值存储过程头，存储过程名称
--存储过程名称规则：sys_sql_getfldval_{@parseid}_{@pretbname} ,@pretbname 为空，以"b"代替
if (@pretbname is null)
set @dsname=null
else
select @predsname = dsname
from flatDSS
where tbname=@pretbname

--存储过程头，及变量定义
if (@isRecursive=0)
begin
exec sys_sql_genparams @parseid,@predsname ,0,@defParams output,@callParams output,@procname output,@localvar output

select @callFmt=@procname + ' ' + @callParams

select @script='create procedure ' +  @procname + '  (' +  char(13)
if (@defParams is not null)
select @script = @script + '' + @defParams + char(13) 

select @script = @script +
   '    )   as ' + char(13) + 'BEGIN' + char(13)+char(13) 
   
if (@localvar is not null)
select @script = @script + ' declare ' +char(13)
+'' +  @localvar
end   



select @preBank='',@i=0,@hasUpDS = 0 

while @i<@indent
select @preBank= @preBank + '  ',@i=@i+1
select @prebank2=@preBank + '  '

--1. 生成pretbname=@pretbname的游标：dsCursor
if (@pretbname is not null)
Declare dsCursor Cursor local static For
select distinct dsname
from flatDSS
where parseid=@parseid and pretbname=@pretbname
else
Declare dsCursor Cursor local static For
select distinct dsname
from flatDSS
where parseid=@parseid and pretbname is null


select @indent=@indent + 1



  --2. 对每个数据源名称处理
  --2.1 数据源名称 @dsname
Open dsCursor
Fetch Next From dsCursor Into @dsname
While (@@FETCH_STATUS=0)
Begin
--2.2 生成该数据源名称下的所有物理表记录游标： tbCursor
Declare  tbCursor Cursor local static For
select tbname,keyval,preLnkFld,pretbname,prekeyfld,shortname,keyfld,bizid,tagid,biztype,dsname,fullname,predsname,isDetailTable
from flatDSS
where parseid=@parseid and predsname=@predsname

Open tbCursor
Fetch Next From tbCursor Into @tbname ,@keyval,@preLnkFld ,@pretbname,@prekeyfld,
@shortname,@keyfld,@bizid,@tagid,@biztype,@dsname,@fullName,@predsname,@isDetailTable
declare @upcount int
set @upcount = 0

while  (@@FETCH_STATUS=0)
begin --2.2
if (@bizid is null)
set @bizid=0
if (@tagid is null)
set @tagid=0

if (@tbname is null)
print 'error:'+ @dsname + ' 没有对应的table '  

if (@isDetailTable=1) --明细表，直接返回
goto over1

--2.3 针对不同@dsname处理
-- 2.3.1 @dsname不是“上级”
if (@shortname != '上级')
begin--2.3.1
--2.3.1.1 获得记录ID
if (@shortname='this')
select @script=@script + char(13) + 
@preBank +' select @'+@dsname+'_keyval=@thisval '  + char(13)
else if (@shortname='user')
select @script=@script + char(13) + 
@preBank +' select @'+@dsname+'_keyval=@useruid '  + char(13)
else if (@shortname='depart')
select @script=@script + char(13) + 
@preBank +' select @'+@dsname+'_keyval=@dpid '  + char(13)
else if (@shortname='company')
select @script=@script + char(13) + 
@preBank +' select @'+@dsname+'_keyval=@cmpid '  + char(13)
else 
select @script=@script + char(13) 

--2.3.1.2 本数据源字段取值，包括所有后级连接字段值
exec sys_sql_getfldval @cmpid,@parseid,@dsname,@tbname,@keyfld,@preBank,@script2 output
if (@script2 is not null)
select @script=@script +@script2


--2.3.1.3 递归后级 如果存在后级，递归后级
select @i=count(*) from flatDSS where pretbname=@tbname and parseid=@parseid
if (@i>0)
begin
select @script=@script + char(13) +
@preBank +' -- 普通递归下级,cur tbname: ' +@tbname +  char(13)

 
--@cmpid ,@parseid ,@pretbname ,@indent ,@isRecursive  ,@hasUpDS @script nvarchar(max) output
exec sys_sql_genproc_fldval @cmpid,@parseid,@tbname,@indent,1,@hasUpDSs output ,@nextFmt output,@script2 output
if (@hasUpDSs=1)
select @hasUpDS = 1

-- 合并后级脚本
if (@script2 is not null and len(@script2)>0)
select @script = @script + char(13) + @script2 
end
select @script = @script + char(13) +
@preBank +' -- 数据源取值结束： ' + @fullname + char(13)


end      --end 2.3.1
  else if (@shortname='上级' or @shortname='根') --shortname='上级'    根 怎么处理  
begin   
--2.3.2 如果@dsname是上级
if (@upcount=0)
begin
select @hasUpDS=1  --存在上级

--2.3.2.2 设置“数据源未出现”标志
select @script = @script + char(13)+
@preBank + ' -- 上级 BEGIN  -- ' + @fullname + char(13) +     
@preBank + ' -- 设置上级业务类型不存在 -- ' + char(13) +     
@preBank + 'select @sys_sql_isUpBizExisted=0,@hasUpDS=1 ' + char(13)

end
--2.3.2.4 对tbCursor的每记录处理：


--5.2 循环，处理上级实例
select @script=@script + char(13) + 
@preBank +'   -- while : ' + @fullname + char(13) 
if (@upcount>0)
select @script=@script + 'else ' 

--（a）生成动态值与静态值比较分支语句script
-- 匹配原则：
if (@shortname='上级')
select @script=@script +  
@preBank +'if (@'+@predsname +'_fbizid=' + convert(varchar(4), @bizid)+') and (@'+@predsname +'_ford2tag=' + convert(varchar(4), @tagid)+')' + char(13) 
if (@shortname='根')
select @script=@script +  
@preBank +'if (@'+@predsname +'_rbizid=' + convert(varchar(4), @bizid)+') and (@'+@predsname +'_rord2tag=' + convert(varchar(4), @tagid)+')' + char(13) 

select @script=@script +  
@preBank +'begin       -- '  +@dsname +'_bizid=' + convert(varchar(4), @bizid)+')' +  char(13) +
@preBank +'  select @sys_sql_isUpBizExisted=1 ' + char(13) +  --（b）清除“数据源未出现”标志script
@preBank +  char(13) +
@preBank +'  --获得本级表字段数据，包括记录ID   ' +  char(13) 

--（c）取数据源字段值script
exec sys_sql_getfldval @cmpid,@parseid,@dsname,@tbname,@keyfld,@preBank,@script2 output

-- 合并script
if (@script2 is not null and len(@script2)>1)
select @script=@script + char(13) + @script2  

select @script=@script + @preBank +' -- end 本级数据获取 ' + char(13) 

select @upcount=@upcount + 1


 --(d)递归后级 如果存在后级，递归后级
if (@tbname is not null)  --防止出现死循环，加条件
begin
declare @nextDSShort varchar(20)
select @nextDSShort=shortname
from sys_sql_ds
where parseid=@parseid and predsname=@dsname
if (@nextDSShort is not null)
begin

select @script=@script + char(13) +
@preBank +' -- 递归下级 ' + @fullname + ': ' + @tbname + char(13) 
if (@nextDSShort='上级')
select @script=@script + char(13) +
@preBank +'  select @sys_sql_isUpBizExisted=0 --nextDSShort' + @nextDSShort+ char(13) 


exec sys_sql_genproc_fldval @cmpid,@parseid,@tbname,@indent,1,@hasUpDSs output,@nextFmt output,@script2 output
if (@hasUpDSs=1)
select @hasUpDS = 1

--4.5 合并后级脚本
if (@script2 is not null and len(@script2)>0)
select @script = @script + char(13) + @script2
end
end  --(d)递归后级 


select @script=@script + 
@preBank +'end  --  ' + @dsname +'_bizid=' + convert(varchar(4), @bizid)+')' + char(13)

select @script = @script +  
@preBank +' -- 上级 end : ' + @fullname + char(13)
end  -- 上级

Fetch Next From tbCursor Into @tbname ,@keyval,@preLnkFld ,@pretbname,@prekeyfld,
@shortname,@keyfld,@bizid,@tagid,@biztype,@dsname,@fullName,@predsname,@isDetailTable

end  --2.2 

Close tbCursor
Deallocate tbCursor

Fetch Next From dsCursor Into @dsname

end

over1:
Close dsCursor
Deallocate dsCursor


if (@isRecursive=0)
begin
select @script = @script + char(13)  + 'END'

--生成存储过程
exec('drop procedure ' + @procname)
exec(@script)
end
end