Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

TableCursors.h

Go to the documentation of this file.
00001 #ifndef TABLE_CURSORS_H 00002 #define TABLE_CURSORS_H 00003 00004 #include "Table.h" 00005 00008 class TableScanCursor : public Table::Cursor { 00009 public: 00010 static ptr<TableScanCursor> factory(Table *table, 00011 ptr<SQLWhereClause> wc); 00012 00014 bool avail() const { 00015 return _avail; 00016 } 00017 00020 const char *rowData() const { 00021 ASSERT(avail()); 00022 return (char *)_row.get_data(); 00023 } 00024 00027 virtual void deleteRow() const { 00028 try { 00029 _table->deleteFromIndexes(_key, _row); 00030 _dbc->del(0); 00031 } catch (DbException &e) { 00032 Throw(AuroraBadEntityException, string() + 00033 "DbException while deleting row: " 00034 + e.what()); 00035 } 00036 } 00037 00038 virtual void setTuple(const char *tuple) { 00039 _ctxt.setTuple(0, tuple); 00040 } 00041 00042 virtual void reset() { 00043 try { 00044 int ret = _dbc->get(&_key, &_row, DB_FIRST); 00045 if (ret == DB_NOTFOUND) { 00046 // No rows. 00047 _avail = false; 00048 } else if (ret == 0) { 00049 _ctxt.setTuple(1, (const char *)_row.get_data()); 00050 if (!_where_clause || 00051 _where_clause->eval<bool>(_ctxt)) { 00052 DEBUG << "Satisfied the where clause"; 00053 _avail = true; 00054 } else { 00055 // Find the next key. 00056 ++(*this); 00057 } 00058 } else { 00059 // Shouldn't happen. 00060 ASSERT(false); 00061 } 00062 } catch (DbException &e) { 00063 Throw(AuroraBadEntityException, string() + 00064 "DbException while resetting cursor: " 00065 + e.what()); 00066 } 00067 } 00068 00071 virtual TableScanCursor& operator ++ () { 00072 try { 00073 int ret; 00074 while ((ret = _dbc->get(&_key, &_row, DB_NEXT)) == 0) { 00075 // TODO: Check the length of the returned row. 00076 _ctxt.reset(); 00077 _ctxt.setTuple(1, (const char *)_row.get_data()); 00078 // NULL _where_clause is true. 00079 if (!_where_clause || 00080 _where_clause->eval<bool>(_ctxt)) { 00081 DEBUG << "Satisfied the where clause"; 00082 _avail = true; 00083 return *this; 00084 } 00085 } 00086 if (ret == DB_NOTFOUND) { 00087 DEBUG << "No more results available in table"; 00088 _avail = false; 00089 } 00090 return *this; 00091 } catch (DbException &e) { 00092 Throw(AuroraBadEntityException, string() + 00093 "DbException while retrieving next result from table: " 00094 + e.what()); 00095 } 00096 } 00097 00098 virtual string as_string() const { 00099 return "TableScanCursor(where=" + 00100 to_string(_where_clause) + ")" ; 00101 } 00102 00103 // Reset will need to be called before this can be used. 00104 TableScanCursor(Table *table, 00105 ptr<Expression> where_clause) : 00106 _table(table), _dbc(_table->getDbCursor()), 00107 _where_clause(where_clause), _ctxt(2) 00108 { 00109 } 00110 00113 virtual ~TableScanCursor() { 00114 _dbc->close(); 00115 } 00116 00117 private: 00118 Table *_table; 00119 Dbc *_dbc; 00120 ptr<Expression> _where_clause; 00121 EvalContext _ctxt; 00122 Dbt _key; 00123 Dbt _row; 00124 bool _avail; 00125 }; 00126 00129 class KeyEqualCursor : public Table::Cursor { 00130 public: 00131 static ptr<KeyEqualCursor> factory(Table *table, 00132 ptr<SQLWhereClause> wc); 00133 00135 bool avail() const { 00136 return _avail; 00137 } 00138 00141 const char *rowData() const { 00142 ASSERT(avail()); 00143 return (char *)_row.get_data(); 00144 } 00145 00148 virtual void deleteRow() const { 00149 try { 00150 _table->deleteFromIndexes(_key, _row); 00151 _dbc->del(0); 00152 } catch (DbException &e) { 00153 Throw(AuroraBadEntityException, string() + 00154 "DbException while deleting row: " 00155 + e.what()); 00156 } 00157 } 00158 00159 virtual void setTuple(const char *tuple) { 00160 _ctxt.setTuple(0, tuple); 00161 } 00162 00163 virtual void reset() { 00164 try { 00165 Expression::evalVectorInto(_values, _key_buf, _ctxt); 00166 _key.set_data(_key_buf); 00167 _key.set_size(_key_size); 00168 00169 int ret = _dbc->get(&_key, &_row, DB_SET); 00170 if (ret == DB_NOTFOUND) { 00171 // No rows. 00172 DEBUG << "No rows on reset for key " 00173 << to_hex_string(_key_buf, _key_size); 00174 _avail = false; 00175 } else if (ret == 0) { 00176 // Set the tuple because broken things expect that. 00177 // TODO: Get rid of broken thigns. 00178 _ctxt.setTuple(1, (const char *)_row.get_data()); 00179 // TODO: Eval the rest of the where clause, if any. 00180 DEBUG << "Satisfied the where clause"; 00181 _avail = true; 00182 } else { 00183 // Shouldn't happen. 00184 ASSERT(false); 00185 } 00186 } catch (DbException &e) { 00187 Throw(AuroraBadEntityException, string() + 00188 "DbException while resetting cursor: " 00189 + e.what()); 00190 } 00191 } 00192 00195 virtual KeyEqualCursor& operator ++ () { 00196 // Only ever one valid row. 00197 _avail = false; 00198 return *this; 00199 } 00200 00201 virtual string as_string() const { 00202 return "KeyEqualCursor(values=" + to_string(_values) + ")"; 00203 } 00204 00205 // Reset will need to be called before this can be used. 00206 KeyEqualCursor(Table *table, size_t key_size, 00207 ptr<Expression> value) : 00208 _table(table), 00209 _dbc(_table->getDbCursor()), _values(1), 00210 _ctxt(2), _key_size(key_size) 00211 { 00212 _values[0] = value; 00213 _key_buf = new char[_key_size]; 00214 } 00215 00216 // Reset will need to be called before this can be used. 00217 KeyEqualCursor(Table *table, size_t key_size, 00218 vector<ptr<Expression> > values) : 00219 _table(table), _dbc(_table->getDbCursor()), _values(values), 00220 _ctxt(2), _key_size(key_size) 00221 { 00222 _key_buf = new char[_key_size]; 00223 } 00224 00227 virtual ~KeyEqualCursor() { 00228 _dbc->close(); 00229 delete[] _key_buf; 00230 } 00231 00232 private: 00233 Table *_table; 00234 Dbc *_dbc; 00235 vector<ptr<Expression> > _values; 00236 EvalContext _ctxt; 00237 size_t _key_size; 00238 char *_key_buf; 00239 Dbt _key; 00240 Dbt _row; 00241 bool _avail; 00242 }; 00243 00246 class IndexKeyEqualCursor : public Table::Cursor { 00247 public: 00248 static ptr<IndexKeyEqualCursor> factory(Table *table, 00249 ptr<SQLWhereClause> wc); 00250 00252 virtual bool avail() const { 00253 return _avail; 00254 } 00255 00258 const char *rowData() const { 00259 ASSERT(avail()); 00260 return (char *)_row.get_data(); 00261 } 00262 00265 virtual void deleteRow() const { 00266 try { 00267 _table->deleteFromIndexes(_pkey, _row); 00268 _pdbc->del(0); 00269 } catch (DbException &e) { 00270 Throw(AuroraBadEntityException, string() + 00271 "DbException while deleting row: " 00272 + e.what()); 00273 } 00274 } 00275 00276 virtual void setTuple(const char *tuple) { 00277 _ctxt.setTuple(0, tuple); 00278 } 00279 00280 virtual void reset() { 00281 try { 00282 _value->evalInto(_key_buf, _ctxt); 00283 _skey.set_data(_key_buf); 00284 _skey.set_size(_key_size); 00285 00286 int ret = _sdbc->get(&_skey, &_pkey, DB_SET); 00287 if (ret == DB_NOTFOUND) { 00288 // No rows. 00289 DEBUG << "No rows on reset for secondary key " 00290 << _skey; 00291 _avail = false; 00292 } else if (ret == 0) { 00293 getPrimaryRow(); 00294 return; 00295 } else { 00296 // Shouldn't happen. 00297 ASSERT(false); 00298 } 00299 } catch (DbException &e) { 00300 Throw(AuroraBadEntityException, string() + 00301 "DbException while resetting cursor: " 00302 + e.what()); 00303 } 00304 } 00305 00308 virtual IndexKeyEqualCursor& operator ++ () { 00309 // TODO: There may be more rows, duplicate secondary keys should be allowed. 00310 // Only ever one valid row. 00311 int ret = _sdbc->get(&_skey, &_pkey, DB_NEXT_DUP); 00312 if (ret == DB_NOTFOUND) { 00313 // No more rows. 00314 _avail = false; 00315 } else if (ret == 0) { 00316 getPrimaryRow(); 00317 } else { 00318 // Shouldn't happen. 00319 ASSERT(false); 00320 } 00321 return *this; 00322 } 00323 00324 virtual string as_string() const { 00325 return "IndexKeyEqualCursor(value=" + to_string(_value) + ")"; 00326 } 00327 00328 // Reset will need to be called before this can be used. 00329 IndexKeyEqualCursor(Table *table, TableIndex *table_index, 00330 size_t key_size, ptr<Expression> value) : 00331 _table(table), _table_index(table_index), 00332 _pdbc(_table->getDbCursor()), 00333 _sdbc(_table_index->getDbCursor()), 00334 _value(value), _ctxt(2), _key_size(key_size), 00335 _key_buf(new char[_key_size]), _avail(false) 00336 {} 00337 00340 virtual ~IndexKeyEqualCursor() { 00341 _pdbc->close(); 00342 _sdbc->close(); 00343 delete[] _key_buf; 00344 } 00345 00346 private: 00348 void getPrimaryRow() { 00349 int ret = _pdbc->get(&_pkey, &_row, DB_SET); 00350 if (ret == DB_NOTFOUND) { 00351 // No rows. This should never happen. 00352 FATAL << "No rows for primary key " << _pkey; 00353 } else if (ret == 0) { 00354 // Set the tuple because broken things expect that. 00355 // TODO: Get rid of broken thigns. 00356 _ctxt.setTuple(1, (const char *)_row.get_data()); 00357 // TODO: Eval the rest of the where clause, if any. 00358 DEBUG << "Satisfied the where clause"; 00359 _avail = true; 00360 } else { 00361 // Shouldn't happen. 00362 ASSERT(false); 00363 } 00364 } 00365 00366 Table *_table; 00367 TableIndex *_table_index; 00368 Dbc *_pdbc; 00369 Dbc *_sdbc; 00370 ptr<Expression> _value; 00371 EvalContext _ctxt; 00372 size_t _key_size; 00373 char *_key_buf; 00374 Dbt _pkey; 00375 Dbt _skey; 00376 Dbt _row; 00377 bool _avail; 00378 }; 00379 00380 #endif

Generated on Fri Nov 12 15:15:22 2004 for Borealis by doxygen 1.3.8