File indexing completed on 2024-05-05 16:47: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 }