-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathTmpRowset.cpp
More file actions
180 lines (155 loc) · 4.31 KB
/
Copy pathTmpRowset.cpp
File metadata and controls
180 lines (155 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright © 2014 CCP ehf.
#include "StdAfx.h"
#include "TmpRowset.h"
#include "NSession.h"
#include <comutil.h>
extern ITaskletTimer *ttimer;
#define AUTOTASKLET(c) AutoTasklet _at(ttimer, c)
#if 0
#define TTIMER1 AUTOTASKLET
#define TTIMER2 AUTOTASKLET
#endif
#define TTIMER1 __noop
#define TTIMER2 __noop
DelayedException *TmpRowset::Get(DBLENGTH &recvLen, rowset_t &rs)
{
DelayedException *de = mRD.Init(rs);
if (de)
return de;
mRows.clear();
HRESULT hr = rs.MoveFirst();
if (FAILED(hr))
return DelayedException::New(hr, "MoveFirst failed");
int got = 0;
recvLen = 0;
const int numCols = (int)rs.GetColumnCount(); //expensive, pays to take this outside loop
while(hr != DB_S_ENDOFROWSET) {
Row *rp;
DBLENGTH len;
de = Row::NewRow(&rp, mAllocator, len, mRD, rs, numCols, mStore);
if (de)
return de;
recvLen += len;
got++;
mRows.push_back(rp);
hr = rs.MoveNext();
if (FAILED(hr))
return DelayedException::New(hr, "MoveFirst failed");
}
return 0;
}
TmpRowset::~TmpRowset()
{
for(rows_i i = mRows.begin(); i != mRows.end(); i++)
if (*i)
Row::DeleteRow(*i, mRD);
}
//returns a tuple: (rowdscriptor, [row, row, ...])
PyObject *TmpRowset::ToPython(ToPythonCtxt &ctxt)
{
TTIMER1("DB::NSession::ToPython::RowSet");
BluePyTuple rs(2);
if (!rs) return 0;
BluePy pyrd(mRD.ToPython(ctxt.mBlue));
rs.Set(0, pyrd); //row descriptor
int len = (int)mRows.size();
BluePyList list(len);
if (!list) return 0;
rs.Set(1, list);
rows_i ri = mRows.begin();
for(int i = 0; i<len; i++, ri++) {
BluePy pyrow((*ri)->ToPython(mRD, pyrd, ctxt));
if (!pyrow || !list.Set(i, pyrow))
return 0;
//destroy the old data as we go along.
Row::DeleteRow(*ri, mRD);
*ri = 0;
if (ctxt.mBeNiceEvery && ((++ctxt.mRowCounter) % ctxt.mBeNiceEvery) == 0 && ctxt.mBeNice) {
//be nice. But first, count allocated python mem
size_t now = ctxt.GetMem();
ctxt.mTotalPyBytes += now - ctxt.mLastPyBytes;
if (!ctxt.BeNice())
return 0; //Probably tasklet got killed
ctxt.mLastPyBytes = ctxt.GetMem();
}
}
return rs.Detach();
}
//The first result has already been bound
DelayedException *TmpRowsetList::Get(DBLENGTH &recvLen, NSession *sess, command_t &rs, DBROWCOUNT rc)
{
//note that the implicit GetNextResult in the rc.Open command may have failed. This failure is (erroneously) not handled
//with a hresult, but we must check the m_spRowset to see if it zero. In this case, we must get the errorRecords, and
//try again.
HRESULT hr = S_OK;
//get result value from the parameters
if (!rs.GetParam(1, &mProcResult)) { //Get return value
mProcResult=0;
recvLen = 0;
} else
recvLen = sizeof(mProcResult);
int got = 0;
do {
//handle the failure mode of GetNextResult at the start of each loop point
//(Command->Open() had an implicit GetNextResult)
if (!rs.m_spRowset) {
hr = rs.GetNextResult(&rc, true);
if (hr == DB_S_NORESULT || !rs.m_spRowset) //yes, sometimes we get the null m_spRowset. This API is broken.
break;
if (FAILED(hr))
return DelayedException::New(hr, "GetNextResult() failed (1)");
}
TmpRowset *trs = new TmpRowset(sess, mAllocator, mStore);
if (!trs)
return DelayedException::NoMem("Couldn't allocate memory for row");
DBLENGTH len;
DelayedException *e = trs->Get(len, rs);
trs->mRC = rc; //rowcount
if (e) {
delete trs;
return e;
}
recvLen += len;
mRowsets.push_back(trs);
got++;
//get the next stuff for the next round of the loop
hr = rs.GetNextResult(&rc, true);
if (hr == DB_S_NORESULT)
break;
} while(hr == S_OK);
if (FAILED(hr))
return DelayedException::New(hr, "GetNextResult() failed");
return 0;
}
TmpRowsetList::~TmpRowsetList()
{
for(rowsets_i i = mRowsets.begin(); i != mRowsets.end(); i++)
delete *i;
}
PyObject *TmpRowsetList::ToPython(ToPythonCtxt &ctxt)
{
int len = (int)mRowsets.size();
if (!len)
return PyLong_FromLong( mProcResult );
ctxt.mLastPyBytes = ctxt.GetMem();
BluePyList list(len);
if (!list)
return 0;
if (len) {
BluePy blueModule(PyImport_Import(BluePyStr("blue")));
if (!blueModule)
return 0;
for(int i = 0; i<len; i++) {
TmpRowset * &trs = mRowsets[i];
if (trs) {
BluePy rs(trs->ToPython(ctxt));
if (!rs || !list.Set(i, rs))
return 0;
delete trs;
trs = 0;
}
}
}
ctxt.mTotalPyBytes += ctxt.GetMem() - ctxt.mLastPyBytes;
return list.Detach();
}