-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathquery.cc
201 lines (169 loc) · 5.63 KB
/
query.cc
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
* $Id: query.cc,v 2.13 2005/10/20 11:24:12 martin Exp $
* Copyright (c) 2004, 2005, Voidsoft AB
*/
#include "query.hh"
Query::Query(TDSPP* tds)
: TDS(tds), endoffile(false) {
rows = new Rows();
}
Query::~Query() {
delete rows;
}
void Query::init(void) {
}
void Query::execute(void) {
if (ct_command(TDS->cmd, CS_LANG_CMD,
(CS_CHAR*)command.c_str(), CS_NULLTERM,
CS_UNUSED) != CS_SUCCEED)
throw TDSPP::Exception("Query::execute: ct_command() failed");
if (ct_send(TDS->cmd) != CS_SUCCEED) throw TDSPP::Exception("Query::execute: ct_send() failed");
getresults();
first();
}
void Query::getrc(void) {
if (ct_res_info(TDS->cmd, CS_ROW_COUNT,
&rowcount, CS_UNUSED, NULL) != CS_SUCCEED)
throw TDSPP::Exception("Query::getrc: ct_res_info() failed");
}
void Query::addrow(void) {
Rows::FieldList fl;
rows->currentrow = rows->rows.size();
rows->rows.push_back(fl);
for (int i=0; i < fieldcount; i ++) {
if (!addfield()) {
rows->rows.pop_back();
break;
}
}
}
bool Query::addfield(void) {
CS_DATAFMT datafmt;
if (ct_describe(TDS->cmd,
rows->rows[rows->currentrow].size()+1, &datafmt)
!= CS_SUCCEED) {
throw TDSPP::Exception("Query::addfield: ct_describe() failed");
}
/** Store enough space for UNICODE chars in tds version >= 7.0 */
datafmt.maxlength = datafmt.maxlength *2 + 1;
/** DATETYPE is reported as 8 bytes from server,
* but becomes 32 when converted. Adjusting for that.
*/
if (datafmt.maxlength < 32) datafmt.maxlength = 32;
// Store the actual datatype before converting to char_type.
int dt = datafmt.datatype;
//if (datafmt.format == CS_FMT_UNUSED) return false;
datafmt.format = CS_FMT_NULLTERM;
datafmt.datatype = CS_CHAR_TYPE;
Field* f = new Field(datafmt.name, datafmt.maxlength, dt);
CS_SMALLINT ind;
if (ct_bind(TDS->cmd,
rows->rows[rows->currentrow].size()+1,
&datafmt,
f->data,
&f->datalength,
&ind) != CS_SUCCEED) {
delete f;
throw TDSPP::Exception("Query::addfield: ct_bind() failed");
}
rows->rows[rows->currentrow].push_back(f);
return true;
}
void Query::getresults(void) {
CS_RETCODE ret;
CS_RETCODE results_ret;
CS_INT result_type;
CS_INT count;
while ((results_ret = ct_results(TDS->cmd, &result_type)) == CS_SUCCEED) {
switch ((int) result_type) {
case CS_CMD_SUCCEED:
getrc();
break;
case CS_CMD_DONE:
getrc();
break;
case CS_CMD_FAIL:
throw TDSPP::Exception("Query::getresults: ct_results() failed.");
case CS_ROW_RESULT:
if (ct_res_info(TDS->cmd,
CS_NUMDATA,
&fieldcount,
CS_UNUSED,
NULL) != CS_SUCCEED)
throw TDSPP::Exception("Query::getresults: ct_res_info() failed");
rows->clear();
do {
addrow();
ret = ct_fetch(TDS->cmd,
CS_UNUSED,
CS_UNUSED,
CS_UNUSED,
&count);
} while (ret == CS_SUCCEED);
switch ((int) ret) {
case CS_END_DATA: {
// Delete unused fields in extra row.
Rows::FIte i;
for (i = rows->rows.back().begin(); i != rows->rows.back().end(); ++i) {
delete (*i);
}
rows->rows.pop_back();
break;
}
case CS_ROW_FAIL:
throw TDSPP::Exception("Query::getresults: ct_fetch() returned CS_ROW_FAIL.");
case CS_FAIL:
throw TDSPP::Exception("Query::getresults: ct_fetch() returned CS_FAIL.");
default:
throw TDSPP::Exception("Query::getresults: ct_fetch() unexpected return.");
} // switch
rows->currentrow = 0;
rowcount = rows->rows.size();
break;
case CS_COMPUTE_RESULT:
throw TDSPP::Exception("Query::getresults: ct_results() unexpected CS_COMPUTE_RESULT.");
default:
throw TDSPP::Exception("Query::getresults: ct_results() unexpected result_type.");
} // switch
} // while
switch ((int) results_ret) {
case CS_END_RESULTS:
break;
case CS_FAIL:
throw TDSPP::Exception("Query::getresults: ct_results() failed.");
default:
throw TDSPP::Exception("Query::getresults: ct_results() unexpected return.");
} // switch
}
void Query::next(void) {
rows->currentrow++;
if (rows->currentrow >= (int)rows->rows.size()) endoffile = true;
}
Field* Query::fields(int i) {
return rows->rows[rows->currentrow][i];
}
Field* Query::fields(string s) {
for (unsigned int i=0; i < rows->rows[rows->currentrow].size(); i++) {
if (rows->rows[rows->currentrow][i]->colname == s) {
return rows->rows[rows->currentrow][i];
}
}
return 0;
}
void Query::first(void) {
rows->currentrow = 0;
if (rows->rows.size() == 0) {
endoffile = true;
} else {
endoffile = false;
}
}
bool Query::eof() {
return endoffile;
}
string Query::operator[] (const char *s) {
return fields(s)->to_str();
}
string Query::operator[] (string s) {
return fields(s)->to_str();
}