/**************************************************************************** ** ** Copyright (C) 1992-2005 Trolltech AS. All rights reserved. ** ** This file is part of the sql module of the TQt Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.TQPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for ** information about TQt Commercial License Agreements. ** See http://www.trolltech.com/qpl/ for TQPL licensing information. ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include "qsqlcachedresult.h" #include #include #include static const uint initial_cache_size = 128; class TQSqlCachedResultPrivate { public: TQSqlCachedResultPrivate(); bool canSeek(int i) const; inline int cacheCount() const; void init(int count, bool fo); void cleanup(); int nextIndex(); void revertLast(); TQSqlCachedResult::ValueCache cache; int rowCacheEnd; int colCount; bool forwardOnly; }; TQSqlCachedResultPrivate::TQSqlCachedResultPrivate(): rowCacheEnd(0), colCount(0), forwardOnly(false) { } void TQSqlCachedResultPrivate::cleanup() { cache.clear(); forwardOnly = false; colCount = 0; rowCacheEnd = 0; } void TQSqlCachedResultPrivate::init(int count, bool fo) { Q_ASSERT(count); cleanup(); forwardOnly = fo; colCount = count; if (fo) { cache.resize(count); rowCacheEnd = count; } else { cache.resize(initial_cache_size * count); } } int TQSqlCachedResultPrivate::nextIndex() { if (forwardOnly) return 0; int newIdx = rowCacheEnd; if (rowCacheEnd == (int)cache.size()) cache.resize(cache.size() * 2); /* if (newIdx + colCount > cache.size()){ if(cache.size() * 2 < cache.size() + 10000) cache.resize(cache.size() * 2); else cache.resize(cache.size() + 10000); }*/ rowCacheEnd += colCount; return newIdx; } bool TQSqlCachedResultPrivate::canSeek(int i) const { if (forwardOnly || i < 0) return false; return rowCacheEnd >= (i + 1) * colCount; } void TQSqlCachedResultPrivate::revertLast() { if (forwardOnly) return; rowCacheEnd -= colCount; } inline int TQSqlCachedResultPrivate::cacheCount() const { Q_ASSERT(!forwardOnly); Q_ASSERT(colCount); return rowCacheEnd / colCount; } ////////////// TQSqlCachedResult::TQSqlCachedResult(const TQSqlDriver * db): TQSqlResult (db) { d = new TQSqlCachedResultPrivate(); } TQSqlCachedResult::~TQSqlCachedResult() { delete d; } void TQSqlCachedResult::init(int colCount) { d->init(colCount, isForwardOnly()); } bool TQSqlCachedResult::fetch(int i) { if ((!isActive()) || (i < 0)) return false; if (at() == i) return true; if (d->forwardOnly) { // speed hack - do not copy values if not needed if (at() > i || at() == TQSql::AfterLast) return false; while(at() < i - 1) { if (!gotoNext(d->cache, -1)) return false; setAt(at() + 1); } if (!gotoNext(d->cache, 0)) return false; setAt(at() + 1); return true; } if (d->canSeek(i)) { setAt(i); return true; } if (d->rowCacheEnd > 0) setAt(d->cacheCount()-1); while (at() < i) { if (!cacheNext()) return false; } return true; } bool TQSqlCachedResult::fetchNext() { if (d->canSeek(at() + 1)) { setAt(at() + 1); return true; } return cacheNext(); } bool TQSqlCachedResult::fetchPrevious() { return fetch(at() - 1); } bool TQSqlCachedResult::fetchFirst() { if (d->forwardOnly && at() != TQSql::BeforeFirst) { return false; } if (d->canSeek(0)) { setAt(0); return true; } return cacheNext(); } bool TQSqlCachedResult::fetchLast() { if (at() == TQSql::AfterLast) { if (d->forwardOnly) return false; else return fetch(d->cacheCount() - 1); } int i = at(); while (fetchNext()) ++i; /* brute force */ if (d->forwardOnly && at() == TQSql::AfterLast) { setAt(i); return true; } else { return fetch(i); } } TQVariant TQSqlCachedResult::data(int i) { int idx = d->forwardOnly ? i : at() * d->colCount + i; if (i >= d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) return TQVariant(); return d->cache.at(idx); } bool TQSqlCachedResult::isNull(int i) { int idx = d->forwardOnly ? i : at() * d->colCount + i; if (i > d->colCount || i < 0 || at() < 0 || idx >= d->rowCacheEnd) return true; return d->cache.at(idx).isNull(); } void TQSqlCachedResult::cleanup() { setAt(TQSql::BeforeFirst); setActive(false); d->cleanup(); } bool TQSqlCachedResult::cacheNext() { if (!gotoNext(d->cache, d->nextIndex())) { d->revertLast(); return false; } setAt(at() + 1); return true; } int TQSqlCachedResult::colCount() const { return d->colCount; } TQSqlCachedResult::ValueCache &TQSqlCachedResult::cache() { return d->cache; }