groupBy.cpp 2.89 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* groupBy.cpp
 *
 *  Created on: Apr 22, 2015
 *      Author: nek3d
 */

#include "groupBy.h"
#include "Tokenizer.h"
#include "ParseTools.h"

GroupBy::GroupBy(ContextGroupBy *context)
: ToolBase(context),
  _queryFRM(NULL),
  _prevRecord(NULL)
{
16
17
18

}

19
20
GroupBy::~GroupBy()
{
21
22
23

}

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
bool GroupBy::init()
{
	Tokenizer groupColsTokens;
	groupColsTokens.tokenize(upCast(_context)->getGroupCols(), ',');
	int numElems = groupColsTokens.getNumValidElems();
	for (int i=0; i < numElems; i++) {
		//if the item is a range, such as 3-5,
		//must split that as well.
		const QuickString &elem = groupColsTokens.getElem(i);

		if (strchr(elem.c_str(), '-')) {
			Tokenizer rangeElems;
			rangeElems.tokenize(elem, '-');
			int startNum = str2chrPos(rangeElems.getElem(0));
			int endNum = str2chrPos(rangeElems.getElem(1));
			for (int i=startNum; i <= endNum; i++) {
				_groupCols.push_back(i);
			}
		} else {
			_groupCols.push_back(str2chrPos(elem));
		}
	}
	_queryFRM = _context->getFile(0);
47
	_prevFields.resize(_groupCols.size());
48
49
50

	_prevRecord = getNextRecord();
	return true;
51
52
}

53
bool GroupBy::findNext(RecordKeyVector &hits)
54
{
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
	//get one record.
	if (_prevRecord == NULL) {
		return false;
	}
	assignPrevFields();
	hits.setKey(_prevRecord);
	hits.push_back(_prevRecord); //key should also be part of group for calculations
	while (1) {
		const Record *newRecord = getNextRecord();
		if (newRecord == NULL) {
			_prevRecord = NULL;
			break;
		} else if (canGroup(newRecord)) {
			hits.push_back(newRecord);
		} else {
			_prevRecord = newRecord;
			break;
		}
	}
	return true;
75
76
}

77
78
void GroupBy::processHits(RecordOutputMgr *outputMgr, RecordKeyVector &hits)
{
79

80
81
82
83
84
85
86
87
88
89
90
91
92
	const Record *rec = hits.getKey();
	const QuickString &opVal  = _context->getColumnOpsVal(hits);
	if (upCast(_context)->printFullCols()) {
		outputMgr->printRecord(rec, opVal);
	} else {
		QuickString outBuf;
		for (int i=0; i < (int)_groupCols.size(); i++) {
			outBuf.append(rec->getField(_groupCols[i]));
			outBuf.append('\t');
		}
		outBuf.append(opVal);
		outputMgr->printRecord(NULL, outBuf);
	}
93
94
}

95
96
97
98
void GroupBy::cleanupHits(RecordKeyVector &hits)
{
	_queryFRM->deleteRecord(hits.getKey());
	hits.clearAll();
99
100
101

}

102
103
104
105
106
107
108
109
110
111
const Record *GroupBy::getNextRecord() {
	while (!_queryFRM->eof()) {
		Record *queryRecord = _queryFRM->getNextRecord();
		if (queryRecord == NULL) {
			continue;
		} else {
			return queryRecord;
		}
	}
	return NULL;
112
113
}

114
115
116
117
void GroupBy::assignPrevFields() {
	for (int i=0; i < (int)_prevFields.size(); i++) {
		_prevFields[i] = _prevRecord->getField(_groupCols[i]);
	}
118
119
}

120
bool GroupBy::canGroup(const Record *newRecord) {
121

122
123
124
125
126
127
128
129
130
131
132
	for (int i=0; i < (int)_groupCols.size(); i++) {
		int fieldNum = _groupCols[i];
		const QuickString &newField = newRecord->getField(fieldNum);
		const QuickString &oldField = _prevFields[i];
		if (upCast(_context)->ignoreCase()) {
			if (oldField.stricmp(newField)) return false;
		} else {
			if (oldField != newField) return false;
		}
	}
	return true;
133
134

}
135