Secondo Sortby分析
函数代码
1 /* 2 3.2 Operator ~sortby~ 3 4 这个操作符类型由给定的属性列表流元组。 5 对于每个属性可以指定清单应按升序(ASC)或降序(DESC)对属性的顺序。 6 7 3.2.1 Type mapping function of operator ~sortby~ 8 9 类型映射~sortby~ is 10 11 ---- ((stream (tuple ((x1 t1)...(xn tn)))) ((xi1 asc/desc) ... (xij asc/desc))) 12 -> ((stream (tuple ((x1 t1)...(xn tn)))) 13 APPEND (j i1 true/false i2 true/false ... ij true/false)) 14 ---- 15 16 类型映射函数确定给定属性列表的属性索引,并生成相应的排序顺序规范。 17 属性的数量,属性索引和布尔标志,表示一个提升(真)或降排序顺序 18 (假),被添加到值映射函数的参数列表中 19 20 */ 21 22 ListExpr SortByTypeMap( ListExpr args )//类型映射 23 { 24 NList type(args); 25 26 // 检查表的长度 27 if ( !type.hasLength(2) ) 28 { 29 return NList::typeError( 30 "Operator sortby expects a list of " 31 "length two."); 32 } 33 34 NList streamDesc = type.first(); 35 NList attrDesc = type.second(); 36 37 // 检查第一个参数是否是一个元组流 38 NList attr; 39 if ( !streamDesc.checkStreamTuple(attr) ) 40 { 41 return NList::typeError( 42 "Operator sortby: first argument is not a tuple stream!" 43 "Operator received: " + streamDesc.convertToString() ); 44 } 45 46 // 检查是否有一个有效的元组描述 47 if ( !IsTupleDescription(attr.listExpr()) ) 48 { 49 return NList::typeError( 50 "Operator sortby: first argument does not " 51 "contain a tuple description!" 52 "Operator received: " + attr.convertToString() ); 53 } 54 55 int numberOfSortAttrs = attrDesc.length(); 56 57 // 检查属性规范的长度 58 if ( numberOfSortAttrs <= 0 ) 59 { 60 return NList::typeError( 61 "Operator sortby: sort order specification " 62 "list may not be empty!"); 63 } 64 65 NList sortDesc; 66 sortDesc.append(NList(numberOfSortAttrs)); 67 NList rest = attrDesc; 68 69 // 过程属性描述 70 while( !rest.isEmpty() ) 71 { 72 // 提取属性规范的第一个元素 73 NList attrElem = rest.first(); 74 75 //切断第一个元素 76 rest.rest(); 77 78 // attrelem可能是一个原子(不可选升序/降序说明符) 79 // 或两个元素的表 (with asc/desc specifier) 80 if ( !(attrElem.isAtom() || attrElem.length() == 2) ) 81 { 82 return NList::typeError( 83 "Operator sortby expects as second argument " 84 "a list of (attrname [asc, desc])|attrname."); 85 } 86 87 string attrName; 88 89 // 处理两种不同的情况 90 if ( attrElem.length() == 2 ) 91 { 92 // 检查类型attrelem 93 if ( !(attrElem.first().isAtom() && 94 attrElem.first().isSymbol() && 95 attrElem.second().isAtom() && 96 attrElem.second().isSymbol() ) ) 97 { 98 return NList::typeError( 99 "Operator sortby expects as second argument a list" 100 " of (attrname [asc, desc])|attrname .\n" 101 "Operator sortby gets a list '" 102 + attrDesc.convertToString() + "'."); 103 } 104 attrName = attrElem.first().str(); 105 } 106 else 107 { 108 // 检查attrelem型原子 109 if ( !(attrElem.isSymbol()) ) 110 { 111 return NList::typeError( 112 "Operator sortby expects as second argument a list" 113 " of (attrname [asc, desc])|attrname .\n" 114 "Operator sortby gets a list '" 115 + attrDesc.convertToString() + "'."); 116 } 117 attrName = attrElem.str(); 118 } 119 120 // 确定属性指标(1-based) 121 ListExpr attrType; 122 int j = FindAttribute(attr.listExpr(), attrName, attrType); 123 124 // 确定升序/降序说明符 125 if (j > 0) 126 { 127 bool isAscending = true; 128 129 if( attrElem.length() == 2 ) 130 { 131 if ( !( attrElem.second().str() == "asc" || 132 attrElem.second().str() == "desc" ) ) 133 { 134 return NList::typeError( 135 "Operator sortby sorting criteria must " 136 "be asc or desc, not '" 137 + attrElem.second().convertToString() + "'!"); 138 } 139 isAscending = attrElem.second().str() == "asc" ? true : false; 140 } 141 142 sortDesc.append(NList(j)); 143 sortDesc.append(NList(isAscending, isAscending)); 144 } 145 else 146 { 147 return NList::typeError( 148 "Operator sortby: attribute name '" + attrName + 149 "' is not known.\nKnown Attribute(s): " 150 + attr.convertToString()); 151 } 152 } 153 154 return NList(NList(Symbol::APPEND()), sortDesc, streamDesc).listExpr(); 155 } 156 /* 157 158 3.2.2 规范操作 ~sortby~ 159 160 */ 161 const string SortBySpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " 162 "\"Example\" ) " 163 "( <text>((stream (tuple([a1:d1, ... ,an:dn])))" 164 " ((xi1 asc/desc) ... (xij [asc/desc]))) -> " 165 "(stream (tuple([a1:d1, ... ,an:dn])))</text--->" 166 "<text>_ sortby [list]</text--->" 167 "<text>Sorts an input stream according to a list " 168 "of attributes ai1 ... aij. For each attribute one " 169 "may specify the sorting order (asc/desc). If no " 170 "order is specified, ascending is assumed." 171 "</text--->" 172 "<text>query employee feed sortby[DeptNo asc] " 173 "consume</text--->" 174 ") )"; 175 176 /* 177 3.2.3 定义的算子~sortby~ 178 179 */ 180 Operator extrelsortby ( 181 "sortby", // name 182 SortBySpec, // specification 183 SortValueMap<2, false>, // value mapping - first argument 184 // of sort order spec is 2 185 Operator::SimpleSelect, // trivial selection function 186 SortByTypeMap // type mapping 187 );
sortby的具体实现
1 template<int firstArg, bool param> 2 int SortValueMap(Word* args, Word& result, int message, Word& local, Supplier s) 3 { 4 bool traceProgress = false; 5 6 // Operator sort2 (firstArg = 1, param = false) 7 // args[0] : stream 8 // args[1] : the number of sort attributes 9 // args[3] : the index of the first sort attribute 10 // args[4] : a boolean which indicates if sortorder should 11 // be asc (true) or desc (false) 12 // args[5] : Same as 3 but for the second sort attribute 13 // args[6] : Same as 4 but for the second sort attribute 14 // .... 15 16 // Operator sort2Param (firstArg = 4, param = true) 17 // args[0] : stream 18 // args[1] : operator's main memory in bytes 19 // args[2] : maximum fan-in of merge phase 20 // args[3] : I/O buffer size in bytes 21 // args[4] : the number of sort attributes 22 // args[5] : the index of the first sort attribute 23 // args[6] : a boolean which indicates if sortorder should 24 // be asc (true) or desc (false) 25 // args[7] : Same as 3 but for the second sort attribute 26 // args[8] : Same as 4 but for the second sort attribute 27 // .... 28 29 // Operator sortby2 (firstArg = 2, param = false) 30 // args[0] : stream 31 // args[1] : sort attributes specification as list (ignored) 32 // args[2] : the number of sort attributes 33 // args[3] : the index of the first sort attribute 34 // args[4] : a boolean which indicates if sortorder should 35 // be asc (true) or desc (false) 36 // args[5] : Same as 3 but for the second sort attribute 37 // args[6] : Same as 4 but for the second sort attribute 38 // .... 39 40 // Operator sortby2Param (firstArg = 5, param = true) 41 // args[0] : stream 42 // args[1] : sort attributes specification as list (ignored) 43 // args[2] : operator's main memory in bytes 44 // args[3] : maximum fan-in of merge phase 45 // args[4] : I/O buffer size in bytes 46 // args[5] : the number of sort attributes 47 // args[6] : the index of the first sort attribute 48 // args[7] : a boolean which indicates if sortorder should 49 // be asc (true) or desc (false) 50 // args[8] : Same as 3 but for the second sort attribute 51 // args[9] : Same as 4 but for the second sort attribute 52 // .... 53 54 SortLocalInfo* li; 55 li = static_cast<SortLocalInfo*>( local.addr ); 56 57 switch(message) 58 { 59 case OPEN: 60 { 61 if (li) 62 { 63 delete li; 64 } 65 66 li = new SortLocalInfo(); 67 local.addr = li; 68 69 // at this point the local value is well defined 70 // afterwards progress request calls are 71 // allowed. 72 73 li->ptr = 0; 74 75 qp->Open(args[0].addr); 76 77 return 0; 78 } 79 80 case REQUEST: 81 { 82 if ( li->ptr == 0 ) 83 { 84 SortOrderSpecification spec; 85 int nAttrCount = StdTypes::GetInt( args[firstArg] ); 86 for(int i = 1; i <= nAttrCount; i++) 87 { 88 int j = firstArg + (2*i - 1); 89 int attrIndex = StdTypes::GetInt( args[j] ); 90 bool isAsc = StdTypes::GetBool( args[j+1] ); 91 spec.push_back(pair<int, bool>(attrIndex, isAsc)); 92 }; 93 94 //Sorting is done in the following constructor. It was moved from 95 //OPEN to REQUEST to avoid long delays in the OPEN method, which are 96 //a problem for progress estimation 97 if ( param ) 98 { 99 int idx = firstArg - 3; 100 int maxMemSize = StdTypes::GetInt( args[idx] ); 101 int maxFanIn = StdTypes::GetInt( args[idx+1] ); 102 int ioBufferSize = StdTypes::GetInt( args[idx+2] ); 103 104 size_t fan = maxFanIn < 0 ? UINT_MAX : (size_t)maxFanIn; 105 size_t mem = maxMemSize < 0 ? UINT_MAX : (size_t)maxMemSize; 106 size_t buf = ioBufferSize < 0 ? UINT_MAX : (size_t)ioBufferSize; 107 108 li->ptr = new SortAlgorithm(args[0], spec, li, s, fan, mem, buf); 109 } 110 else 111 { 112 li->ptr = new SortAlgorithm(args[0], spec, li, s); 113 } 114 } 115 116 SortAlgorithm* sa = li->ptr; 117 118 result.setAddr( sa->NextResultTuple() ); 119 li->returned++; 120 return result.addr != 0 ? YIELD : CANCEL; 121 } 122 123 case CLOSE: 124 { 125 // Note: object deletion is handled in OPEN and CLOSEPROGRESS 126 qp->Close(args[0].addr); 127 return 0; 128 } 129 130 131 case CLOSEPROGRESS: 132 { 133 if (li) 134 { 135 delete li; 136 local.addr = 0; 137 } 138 return 0; 139 } 140 141 case REQUESTPROGRESS: 142 { 143 ProgressInfo p1; 144 ProgressInfo *pRes; 145 const double uSortBy = 0.0000873; //millisecs per byte input and sort 146 // old constant 0.000396; 147 const double vSortBy = 0.0000243; //millisecs per byte output 148 // old constant 0.000194; 149 const double oSortBy = 0.00004; //offset due to writing to disk 150 //not yet measurable 151 152 // constants determined in file ExtRelation-C++/ConstantsExtendStream 153 154 155 156 pRes = (ProgressInfo*) result.addr; 157 158 if( !li ) 159 { 160 return CANCEL; 161 } 162 else 163 { 164 if (qp->RequestProgress(args[0].addr, &p1)) 165 { 166 // ------------------------------------------- 167 // Result cardinality 168 // ------------------------------------------- 169 170 pRes->Card = li->returned == 0 ? p1.Card : li->read; 171 pRes->CopySizes(p1); 172 173 // ------------------------------------------- 174 // Total time 175 // ------------------------------------------- 176 177 pRes->Time = p1.Time 178 + pRes->Card * p1.SizeExt * (uSortBy + oSortBy * li->state) 179 + pRes->Card * p1.SizeExt * vSortBy 180 + li->intTuplesTotal * p1.Size * (2 * vSortBy); 181 182 // ------------------------------------------- 183 // Total progress 184 // ------------------------------------------- 185 186 pRes->Progress = 187 (p1.Progress * p1.Time 188 + li->read * p1.SizeExt * (uSortBy + oSortBy * li->state) 189 + li->returned * p1.SizeExt * vSortBy 190 + li->intTuplesProc * p1.SizeExt * (2 * vSortBy) ) 191 / pRes->Time; 192 193 // ------------------------------------------- 194 // Blocking time 195 // ------------------------------------------- 196 197 // Estimated time until first result tuple is ready 198 pRes->BTime = p1.Time 199 + pRes->Card * p1.SizeExt * (uSortBy + oSortBy * li->state) 200 + li->intTuplesTotal * p1.SizeExt * (2 * vSortBy); 201 202 // ------------------------------------------- 203 // Blocking progress 204 // ------------------------------------------- 205 206 pRes->BProgress = 207 (p1.Progress * p1.Time 208 + li->read * p1.SizeExt * (uSortBy + oSortBy * li->state) 209 + li->intTuplesProc * p1.SizeExt * (2 * vSortBy)) 210 / pRes->BTime; 211 212 if ( traceProgress ) 213 { 214 cmsg.info() << "p1->Card: " << p1.Card 215 << ", p1.Time: " << p1.Time 216 << ", p1.Progress: " << p1.Progress 217 << endl 218 << "pRes->Time: " << pRes->Time 219 << ", pRes->Progress: " << pRes->Progress 220 << endl 221 << ", intTuples: " << li->intTuplesProc 222 << "/" << li->intTuplesTotal 223 << endl; 224 cmsg.send(); 225 } 226 227 return YIELD; 228 } 229 else 230 { 231 return CANCEL; 232 } 233 } 234 } 235 } 236 return 0; 237 }

浙公网安备 33010602011771号