File indexing completed on 2024-05-19 08:32:17
0001 /* This file is part of the KDE project 0002 Copyright (C) 2007 Sharan Rao <sharanrao@gmail.com> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this program; see the file COPYING. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 0021 #include "SybaseCursor.h" 0022 #include "SybaseConnection.h" 0023 #include "SybaseConnection_p.h" 0024 0025 0026 #include "KDbError.h" 0027 #include "KDbUtils.h" 0028 0029 #include <limits.h> 0030 #include <cstring> 0031 0032 #include <sqldb.h> 0033 0034 SybaseCursor::SybaseCursor(KDbConnection* conn, const KDbEscapedString& sql, int cursor_options) 0035 : KDbCursor(conn, sql, cursor_options) 0036 , d(new SybaseCursorData(conn)) 0037 { 0038 0039 //m_options |= Buffered; 0040 0041 d->dbProcess = static_cast<SybaseConnection*>(conn)->d->dbProcess; 0042 // sybaseDebug() << "SybaseCursor: constructor for query statement"; 0043 } 0044 0045 SybaseCursor::SybaseCursor(KDbConnection* conn, KDbQuerySchema* query, int options) 0046 : KDbCursor(conn, query, options) 0047 , d(new SybaseCursorData(conn)) 0048 { 0049 // m_options |= Buffered; 0050 0051 d->dbProcess = static_cast<SybaseConnection*>(conn)->d->dbProcess; 0052 // sybaseDebug() << "SybaseCursor: constructor for query statement"; 0053 } 0054 0055 SybaseCursor::~SybaseCursor() 0056 { 0057 close(); 0058 } 0059 0060 bool SybaseCursor::drv_open(const KDbEscapedString& sql) 0061 { 0062 0063 /* Pseudo Code 0064 * 0065 * Execute Query 0066 * If no error 0067 * Store Result in buffer ( d-> ?? ) 0068 * Store fieldcount ( no. of columns ) in m_fieldCount 0069 * Set m_fieldsToStoreInRecord equal to m_fieldCount 0070 * Store number of rows in d->numRows 0071 * Set pointer at 0 ( m_at = 0 ) 0072 * 0073 * Set opened flag as true ( m_opened = true ) 0074 * Set numberoOfRecordsInbuffer as d->numRows ( m_records_in_buf = d->numRows ) 0075 * Set Buffering Complete flag = true 0076 * Set After Last flag = false 0077 * 0078 */ 0079 0080 // clear all previous results ( if remaining ) 0081 if (dbcancel(d->dbProcess) == FAIL) 0082 sybaseWarning() << "drv_open" << "dead DBPROCESS ?"; 0083 0084 // insert into command buffer 0085 dbcmd(d->dbProcess, sql.toByteArray()); 0086 // execute query 0087 dbsqlexec(d->dbProcess); 0088 0089 if (dbresults(d->dbProcess) == SUCCEED) { 0090 // result set goes directly into dbProcess' buffer 0091 m_fieldCount = dbnumcols(d->dbProcess); 0092 m_fieldsToStoreInRecord = m_fieldCount; 0093 0094 // only relevant if buffering will ever work 0095 // <ignore> 0096 d->numRows = DBLASTROW(d->dbProcess); // only true if buffering enabled 0097 m_records_in_buf = d->numRows; 0098 m_buffering_completed = true; 0099 // </ignore> 0100 0101 m_afterLast = false; 0102 m_opened = true; 0103 m_at = 0; 0104 0105 return true; 0106 } 0107 0108 setError(ERR_DB_SPECIFIC, static_cast<SybaseConnection*>(connection())->d->errmsg); 0109 return false; 0110 } 0111 0112 0113 bool SybaseCursor::drv_close() 0114 { 0115 0116 m_opened = false; 0117 d->numRows = 0; 0118 return true; 0119 } 0120 0121 //! @todo SybaseCursor::drv_moveFirst() 0122 /*bool SybaseCursor::drv_moveFirst() { 0123 return true; 0124 }*/ 0125 0126 void SybaseCursor::drv_getNextRecord() 0127 { 0128 // sybaseDebug(); 0129 0130 // no buffering , and we don't know how many rows are there in result set 0131 0132 if (dbnextrow(d->dbProcess) != NO_MORE_ROWS) 0133 m_fetchResult = FetchResult::Ok; 0134 else { 0135 m_fetchResult = FetchResult::End; 0136 } 0137 0138 } 0139 0140 0141 QVariant SybaseCursor::value(int pos) 0142 { 0143 if (!d->dbProcess || pos >= m_fieldCount) 0144 return QVariant(); 0145 0146 KDbField *f = (m_visibleFieldsExpanded && pos < m_visibleFieldsExpanded->count()) 0147 ? m_visibleFieldsExpanded->at(pos)->field : 0; 0148 0149 // db-library indexes its columns from 1 0150 pos = pos + 1; 0151 0152 long int columnDataLength = dbdatlen(d->dbProcess, pos); 0153 0154 // 512 is 0155 // 1. the length used internally in dblib for allocating data to each column in function dbprrow() 0156 // 2. it's greater than all the values returned in the dblib internal function _get_printable_size 0157 long int pointerLength = qMax(columnDataLength , (long int)512); 0158 0159 BYTE* columnValue = new unsigned char[pointerLength + 1] ; 0160 0161 // convert to string representation. All values are convertible to string 0162 dbconvert(d->dbProcess , dbcoltype(d->dbProcess , pos), dbdata(d->dbProcess , pos), columnDataLength , (SYBCHAR), columnValue, -2); 0163 0164 QVariant returnValue = KDbcstringToVariant((const char*)columnValue , f, strlen((const char*)columnValue)); 0165 0166 delete[] columnValue; 0167 0168 return returnValue; 0169 } 0170 0171 0172 /* As with sqlite, the DB library returns all values (including numbers) as 0173 strings. So just put that string in a QVariant and let KDb deal with it. 0174 */ 0175 bool SybaseCursor::drv_storeCurrentRecord(KDbRecordData* data) const 0176 { 0177 // sybaseDebug() << "Position is" << (long)m_at; 0178 // if (d->numRows<=0) 0179 // return false; 0180 0181 const int fieldsExpandedCount = m_visibleFieldsExpanded 0182 ? m_visibleFieldsExpanded->count() : INT_MAX; 0183 const int realCount = qMin(fieldsExpandedCount, m_fieldsToStoreInRecord); 0184 for (int i = 0; i < realCount; i++) { 0185 KDbField *f = m_visibleFieldsExpanded ? m_visibleFieldsExpanded->at(i)->field : 0; 0186 if (m_visibleFieldsExpanded && !f) 0187 continue; 0188 0189 long int columnDataLength = dbdatlen(d->dbProcess, i + 1); 0190 0191 // 512 is 0192 // 1. the length used internally in dblib for allocating data to each column in function dbprrow() 0193 // 2. it's greater than all the values returned in the dblib internal function _get_printable_size 0194 long int pointerLength = qMax(columnDataLength , (long int)512); 0195 0196 BYTE* columnValue = new unsigned char[pointerLength + 1] ; 0197 0198 // convert to string representation. All values are convertible to string 0199 dbconvert(d->dbProcess , dbcoltype(d->dbProcess , i + 1), dbdata(d->dbProcess , i + 1), columnDataLength , (SYBCHAR), columnValue, -2); 0200 0201 (*data)[i] = KDbcstringToVariant((const char*)columnValue , f, strlen((const char*)columnValue)); 0202 0203 delete[] columnValue; 0204 } 0205 return true; 0206 } 0207 0208 void SybaseCursor::drv_appendCurrentRecordToBuffer() 0209 { 0210 } 0211 0212 0213 void SybaseCursor::drv_bufferMovePointerNext() 0214 { 0215 //dbgetrow( d->dbProcess, m_at + 1 ); 0216 } 0217 0218 void SybaseCursor::drv_bufferMovePointerPrev() 0219 { 0220 //dbgetrow( d->dbProcess, m_at - 1 ); 0221 } 0222 0223 0224 void SybaseCursor::drv_bufferMovePointerTo(qint64 to) 0225 { 0226 //dbgetrow( d->dbProcess, to ); 0227 } 0228 0229 const char** SybaseCursor::recordData() const 0230 { 0231 //! @todo 0232 return 0; 0233 } 0234 0235 int SybaseCursor::serverResult() 0236 { 0237 return d->res; 0238 } 0239 0240 QString SybaseCursor::serverResultName() const 0241 { 0242 return QString(); 0243 }