| 213 | } |
| 214 | |
| 215 | void DsqlCursor::getInfo(thread_db* tdbb, |
| 216 | unsigned int itemsLength, const unsigned char* items, |
| 217 | unsigned int bufferLength, unsigned char* buffer) |
| 218 | { |
| 219 | if (bufferLength < 7) // isc_info_error + 2-byte length + 4-byte error code |
| 220 | { |
| 221 | if (bufferLength) |
| 222 | *buffer = isc_info_truncated; |
| 223 | return; |
| 224 | } |
| 225 | |
| 226 | const bool isScrollable = (m_flags & IStatement::CURSOR_TYPE_SCROLLABLE); |
| 227 | |
| 228 | ClumpletWriter response(ClumpletReader::InfoResponse, bufferLength - 1); // isc_info_end |
| 229 | ISC_STATUS errorCode = 0; |
| 230 | bool needLength = false, completed = false; |
| 231 | |
| 232 | try |
| 233 | { |
| 234 | ClumpletReader infoItems(ClumpletReader::InfoItems, items, itemsLength); |
| 235 | for (infoItems.rewind(); !errorCode && !infoItems.isEof(); infoItems.moveNext()) |
| 236 | { |
| 237 | const auto tag = infoItems.getClumpTag(); |
| 238 | |
| 239 | switch (tag) |
| 240 | { |
| 241 | case isc_info_end: |
| 242 | break; |
| 243 | |
| 244 | case isc_info_length: |
| 245 | needLength = true; |
| 246 | break; |
| 247 | |
| 248 | case IResultSet::INF_RECORD_COUNT: |
| 249 | if (isScrollable && !m_eof) |
| 250 | { |
| 251 | cacheInput(tdbb); |
| 252 | fb_assert(m_eof); |
| 253 | } |
| 254 | response.insertInt(tag, isScrollable ? m_cachedCount : -1); |
| 255 | break; |
| 256 | |
| 257 | default: |
| 258 | errorCode = isc_infunk; |
| 259 | break; |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | completed = infoItems.isEof(); |
| 264 | |
| 265 | if (needLength && completed) |
| 266 | { |
| 267 | response.rewind(); |
| 268 | response.insertInt(isc_info_length, response.getBufferLength() + 1); // isc_info_end |
| 269 | } |
| 270 | } |
| 271 | catch (const Exception&) |
| 272 | { |
nothing calls this directly
no test coverage detected