#
#		ITSV GmbH
#	CCDB - Command and Control DataBase
#
#	FILE:			dquerymfile_mergetextfrags.txt
#	DESCRIPTION:	DQUERY definition of DQUERY mergetextfrags
#					The query merges all text fragments of one text (has same ident and child_index) into 1 text fragments
#
@querytitle			Text-Fragmente vereinen
@querydescription	Vereint alle Fragmente eines Texts zu einem Fragmente
@group				ADMINTEXTFRAG
@attributenames		textident:string:{{textidentoptions}},textindex:integer:{{textindexoptions}},separator:string:{{separatoroptions}}
@textidentoptions	{"labeltext":"Text-ID","typedesc":"ID des Textes, zu dem die zu mergenden Textfragmente gehören"}
@textindexoptions	{"labeltext":"Text-Index","typedesc":"Index des Sub-Texts, zu dem die zu mergenden Textfragmente gehören"}
@separatoroptions	{"labeltext":"Trennzeichen","typedesc":"Zeichen, durch das die zu mergenden Textfragmente verbunden werden sollen (Vorgabe: newline)","is_optional":"true"}
@querytype			function
@function			seqtrans.seqtrans		

~query.tsteps

#
# 0: initialize
#
qexpression
	this.textident = this.query.textident;
	this.textindex = this.query.textindex;
	this.separator = this.query.separator;
	if (this.separator) this.separator = "\r\n";
	ppush(this,[phead(this,"STARTED, "+aux.nowsvtime()),"textident="+this.query.textident,"textindex="+this.query.textindex,""]);
	
#
# 1: get all the fragments and merge them in memory
#
sql					select type,ident,version,parent,child_index,frag_index,data from CCTEXTFRAG tf 
                     where     ident=::textident:: 
						   and child_index=::textindex:: 
                           and tf.version=(select max(version) from CCTEXTFRAG tfv where tfv.ident=::textident:: and tfv.child_index=::textindex:: and tfv.frag_index=tf.frag_index)
					 order by frag_index asc
named_params		textident,textindex
result_varname		alltextres
post_qexpression
	proc: {
		let minfi = 999999;
		let maxfi = 0;
		let mtexts = new Array();
		let ftype = "";
		let crow;
		let lastfi=-1;
		let parid = "";
		let maxvers = -1;
		for (let ri=0; ri<this.alltextres.getRowCount(); ri++) {
			crow = this.alltextres.getRowObject(ri);
			if (crow.frag_index>maxfi) maxfi = crow.frag_index;
			if (crow.frag_index<minfi) minfi = crow.frag_index;
			if (!ftype) ftype = crow.type;
			if (crow.type!=ftype) {
				this.errcoll.collect(null,"fragment type of fragment "+crow.ident+"/"+crow.child_index+"/"+crow.frag_index+" (\""+crow.type+"\") is different from general fragment type of \""+ftype+"\"",crow);
				break proc;
			}
			if (!parid) parid = crow.parent;
			if (parid!=crow.parent) {
				this.errcoll.collect(null,"parent of fragment "+crow.ident+"/"+crow.child_index+"/"+crow.frag_index+" (\""+crow.parent+"\") is different from general parent of \""+parid+"\"",crow);
				break proc;
			}
			if (crow.version>maxvers) maxvers = crow.version;
			if (lastfi>=0) {
				if (crow.frag_index!=(lastfi+1)) {
					this.errcoll.collect(null,"fragment index of text is not contiguous",this.alltextres);
					break proc;
				}
			}
			mtexts.push(crow.data);
			lastfi = crow.frag_index;
		}
		let fcount = (maxfi-minfi+1);
		if (this.alltextres.getRowCount()!=fcount) {
			this.errcoll.collect(null,"fragments of text are not contiguous, "+minfi+" thru "+maxfi+" should be "+fcount+" fragments, but are "+this.alltextres.getRowCount(),this.alltextres);
			break proc;
		}
		this.merged_text = mtexts.join(this.separator);
		this.minfi = minfi;
		this.maxfi = maxfi;
		this.ftype = ftype;
		this.fcount = fcount;
		this.parid = parid;
		this.vers = maxvers;
		ppush(this,[phead(this,"textmerged"),"textfragsmerged="+this.fcount,"",""]);
	}

#
# 2: delete the old text fragments
#
sql				delete from CCTEXTFRAG where type=::ftype:: and ident=::textident:: and child_index=::textindex:: and frag_index between ::minfi:: and ::maxfi::  
named_params 	ftype,textident,textindex,minfi,maxfi
result_varname	delres
post_qexpression
	proc: {
		this.drows = this.delres.resultobject.affectedRows;
		if (this.drows!=this.fcount) {
			this.errcoll.collect(null,"there should be "+this.fcount+" old fragments deleted but there have been "+this.drows,this.delres);
			break proc;
		}
		ppush(this,[phead(this,"fragsdeleted"),"fragsdeleted="+this.drows,"",""]);
	}
	
#
# 3: create a new fragment with the merged text
#
sql					insert into CCTEXTFRAG(type,ident,version,parent,child_index,frag_index,data) values(::ftype::,::textident::,::vers::,::parid::,::textindex::,::minfi::,::merged_text::)
named_params		ftype,textident,vers,parid,textindex,minfi,merged_text
result_varname		insres
post_qexpression
	proc: {
		this.irows = this.insres.resultobject.affectedRows;
		if (this.irows!=1) {
			this.errcoll.collect(null,"there should have been one new row inserted, but there have been "+this.irows,this.insres);
			break proc;
		}
		ppush(this,[phead(this,("FINISHED, "+aux.nowsvtime())),"fragsinserted="+this.irows,"",""]);
	}