LCOV - code coverage report
Current view: top level - libdbproxy - row.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 180 0.6 %
Date: 2019-12-15 17:13:15 Functions: 2 36 5.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Text:
       3             :  *      libsnapwebsites/src/libdbproxy/row.cpp
       4             :  *
       5             :  * Description:
       6             :  *      Handling of rows. There is no class representing a row in Cassandra.
       7             :  *      A row is just a key. We have this object to allow for our C++ array
       8             :  *      syntax to access the Cassandra data.
       9             :  *
      10             :  * Documentation:
      11             :  *      See each function below.
      12             :  *
      13             :  * License:
      14             :  *      Copyright (c) 2011-2019  Made to Order Software Corp.  All Rights Reserved
      15             :  * 
      16             :  *      https://snapwebsites.org/
      17             :  *      contact@m2osw.com
      18             :  * 
      19             :  *      Permission is hereby granted, free of charge, to any person obtaining a
      20             :  *      copy of this software and associated documentation files (the
      21             :  *      "Software"), to deal in the Software without restriction, including
      22             :  *      without limitation the rights to use, copy, modify, merge, publish,
      23             :  *      distribute, sublicense, and/or sell copies of the Software, and to
      24             :  *      permit persons to whom the Software is furnished to do so, subject to
      25             :  *      the following conditions:
      26             :  *
      27             :  *      The above copyright notice and this permission notice shall be included
      28             :  *      in all copies or substantial portions of the Software.
      29             :  *
      30             :  *      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      31             :  *      OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      32             :  *      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      33             :  *      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      34             :  *      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      35             :  *      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      36             :  *      SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      37             :  */
      38             : 
      39             : #include "libdbproxy/row.h"
      40             : #include "libdbproxy/table.h"
      41             : #include "libdbproxy/context.h"
      42             : #include "libdbproxy/libdbproxy.h"
      43             : 
      44             : #include <iostream>
      45             : #include <stdexcept>
      46             : 
      47             : namespace libdbproxy
      48             : {
      49             : 
      50             : /** \class row
      51             :  * \brief The row class to hold a set of cells.
      52             :  *
      53             :  * These objects are created by the table whenever data is
      54             :  * being read or written to a cell. Rows have a binary key (may be set
      55             :  * as a UTF-8 string) and a map of cells indexed by the names of the
      56             :  * cells.
      57             :  *
      58             :  * The name of a row is limited to nearly 64Kb. Although, if you have
      59             :  * a table with very long names, you may want to consider computing
      60             :  * an md5sum or equivalent. This is important if you want to avoid
      61             :  * slowing down the Cassandra server. Searching through a large set
      62             :  * of 60Kb keys is much slower than doing the same through their
      63             :  * md5sums. Of course, that means you lose the automatic sorting of
      64             :  * the original key.
      65             :  *
      66             :  * By default, most of the functions will create a new cell. If you
      67             :  * need to test the existance without creating a cell, use the
      68             :  * exists() function with the column name of the cell check out.
      69             :  *
      70             :  * \sa exists()
      71             :  */
      72             : 
      73             : 
      74             : /** \typedef row::composite_column_names_t
      75             :  * \brief The set of column names.
      76             :  *
      77             :  * This type is used to declare a set of composite column names as
      78             :  * used by the compositeCell() functions.
      79             :  *
      80             :  * The type simply defines an array of column names. Each name can be any
      81             :  * valid column name key. In other words, a value with any value.
      82             :  * However, to be compatible with CQL and the CLI and possibly other
      83             :  * Cassandra features, you want to limit your names to things that do not
      84             :  * include the colon characters. The CQL and CLI make use of names
      85             :  * separated by colons (i.e. "blah:foo:123".) However, the Cassandra
      86             :  * cluster itself has no limit to the content of the names except for
      87             :  * their length which is 65536 bytes each.
      88             :  */
      89             : 
      90             : 
      91             : /** \var row::f_table
      92             :  * \brief The table this row is part of.
      93             :  *
      94             :  * This bare pointer is used to access the table this row is part of.
      95             :  * It is a bare pointer because you cannot create a row without having
      96             :  * a table and the table keeps a tight reference on the row.
      97             :  */
      98             : 
      99             : 
     100             : /** \var row::f_key
     101             :  * \brief The binary key of the row.
     102             :  *
     103             :  * The binary key of the row is set to UTF-8 when defined with a
     104             :  * string. Otherwise it is defined as specified by the user.
     105             :  */
     106             : 
     107             : 
     108             : /** \var row::f_cells
     109             :  * \brief The array of cells defined in this row.
     110             :  *
     111             :  * This is a map of cells. Cells are names and values pairs.
     112             :  *
     113             :  * The values are defined with a timestamp and ttl value.
     114             :  */
     115             : 
     116             : 
     117             : /** \brief Initialize a row object.
     118             :  *
     119             :  * This function initializes a row object. You must specify the
     120             :  * key of the row and that's the only parameter that a row supports at
     121             :  * this time.
     122             :  *
     123             :  * The key of the row is a binary buffer of data. It must be at least 1 byte
     124             :  * and at most 64Kb minus 1 (65535 bytes).
     125             :  *
     126             :  * A row is composed of multiple cells (called columns in Cassandra.)
     127             :  *
     128             :  * \exception exception
     129             :  * The key of the row cannot be empty or more than 64Kb. If that happens,
     130             :  * this exception is raised.
     131             :  *
     132             :  * \param[in] table  The parent table of this row.
     133             :  * \param[in] row_key  The key of this row.
     134             :  */
     135           0 : row::row(std::shared_ptr<table> table, const QByteArray& row_key)
     136             :     : f_table(table)
     137           0 :     , f_key(row_key)
     138             :     //f_cells() -- auto-init
     139             : {
     140           0 :     if(f_key.size() == 0) {
     141           0 :         throw exception("row key cannot be empty");
     142             :     }
     143           0 :     if(f_key.size() > 65535) {
     144           0 :         throw exception("row key is more than 64Kb");
     145             :     }
     146           0 : }
     147             : 
     148             : 
     149             : /** \brief Clean up the row object.
     150             :  *
     151             :  * This function ensures that all resources allocated by the
     152             :  * row are released.
     153             :  */
     154           0 : row::~row()
     155             : {
     156             :     try
     157             :     {
     158             :         // do an explicit clearCache() so we can try/catch otherwise we
     159             :         // could get a throw in the destructor
     160             :         //
     161           0 :         clearCache();
     162             :     }
     163           0 :     catch(const exception&)
     164             :     {
     165             :         // ignore, not much else we can do in a destructor
     166             :     }
     167           0 : }
     168             : 
     169             : 
     170             : /** \brief Retrieve the name of the row.
     171             :  *
     172             :  * This function returns the name of the row as specified in the
     173             :  * constructor.
     174             :  *
     175             :  * The name cannot be changed.
     176             :  *
     177             :  * Note that if you created the row with a binary key (i.e. a
     178             :  * QByteArray parameter) then you CANNOT retrieve the row name.
     179             :  * Instead, use the rowKey() function.
     180             :  *
     181             :  * \return A string with the key name.
     182             :  *
     183             :  * \sa rowKey()
     184             :  */
     185           0 : QString row::rowName() const
     186             : {
     187           0 :     return QString::fromUtf8(f_key.data());
     188             : }
     189             : 
     190             : 
     191             : /** \brief Retrieve the row key.
     192             :  *
     193             :  * This function returns the key of this row. The key is a binary buffer
     194             :  * of data. This function works whether the row was created with a name
     195             :  * or a key.
     196             :  *
     197             :  * Note that when creating a row with a binary key, you cannot retrieve
     198             :  * it using the rowName() function.
     199             :  *
     200             :  * \return A buffer of data representing the row key.
     201             :  *
     202             :  * \sa rowName()
     203             :  */
     204           0 : const QByteArray& row::rowKey() const
     205             : {
     206           0 :     return f_key;
     207             : }
     208             : 
     209             : 
     210             : /** \brief Retrieve the current timeout.
     211             :  *
     212             :  * This function retrieves the timeout used to wait less or more that
     213             :  * a statement completes.
     214             :  *
     215             :  * The value is in milliseconds.
     216             :  *
     217             :  * If the value is set to 0 then the default order timeout gets used.
     218             :  * This is often 10 seconds. This is often used the backend to increase
     219             :  * our chances of getting the data back because in many cases getting the
     220             :  * info is more important than speed.
     221             :  *
     222             :  * \return The timeout in milliseconds.
     223             :  */
     224           0 : int32_t row::timeout() const
     225             : {
     226           0 :     return f_timeout_ms;
     227             : }
     228             : 
     229             : 
     230             : /** \brief Timeout for orders sent from this row object.
     231             :  *
     232             :  * This value is the timeout in milleseconds for any CQL statement sent
     233             :  * to the backend by the row object.
     234             :  *
     235             :  * \param[in] timeout_ms  The new timeout value in milliseconds.
     236             :  */
     237           0 : void row::setTimeout(int32_t const timeout_ms)
     238             : {
     239           0 :     f_timeout_ms = timeout_ms;
     240           0 : }
     241             : 
     242             : 
     243             : /** \brief Retrieve the number of cells defined in this row.
     244             :  *
     245             :  * This function retrieves the number of cells currently defined in this row,
     246             :  * depending on the specified predicate (by default, all the cells.)
     247             :  *
     248             :  * This counts the number of cells available in the Cassandra database. It
     249             :  * may be different from the number of cells in the memory cache. (i.e. the
     250             :  * value returned by getCells().size())
     251             :  *
     252             :  * \param[in] column_predicate  The predicate used to select which columns to count.
     253             :  *
     254             :  * \return The number of cells defined in this row.
     255             :  *
     256             :  * \note This method no longer changes the row set from the query!
     257             :  *
     258             :  * \sa getCells(), table::readRows()
     259             :  */
     260           0 : int row::cellCount( const cell_predicate::pointer_t column_predicate )
     261             : {
     262             :     //return static_cast<int>(f_cells.size());
     263           0 :     return parentTable()->getCellCount(f_key, column_predicate);
     264             : }
     265             : 
     266             : 
     267             : /** \brief Read the cells as defined by a default column predicate.
     268             :  *
     269             :  * This function is the same as the readCells() with a column predicate
     270             :  * only it uses a default predicate which is to read all the columns
     271             :  * available in that row, with a limit of 100 cells.
     272             :  *
     273             :  * In this case the predicate has no column names or range boundaries
     274             :  * and no index capabilities. This mode should be used on rows which you
     275             :  * know have a limited number of cells. Otherwise, you should use the
     276             :  * other readCells() version.
     277             :  *
     278             :  * To know how many cells were read, save the returned value. When you
     279             :  * use the count() function on the map returned by the getCells() function,
     280             :  * you actually get the total number of cells ever read since the
     281             :  * creation of this row in memory or the last call to clearCache().
     282             :  * Most importantly, the cellCount() function returns the total number of
     283             :  * cells available in the Cassandra database. Not the number of cells
     284             :  * currently available in memory.
     285             :  *
     286             :  * \note
     287             :  * The number of columns read (the value returned by this function) may be
     288             :  * smaller than the total number of columns available in memory if you did
     289             :  * not clear the cache first.
     290             :  *
     291             :  * \return The number of cells read from Cassandra, can be zero.
     292             :  *
     293             :  * \sa cellCount()
     294             :  * \sa getCells()
     295             :  * \sa clearCache()
     296             :  */
     297           0 : uint32_t row::readCells()
     298             : {
     299           0 :     return f_cells.size();
     300             : }
     301             : 
     302             : 
     303             : /** \brief Read the cells as defined by the predicate.
     304             :  *
     305             :  * This function reads a set of cells as specified by the specified
     306             :  * predicate. If you use the default cell_predicate, then
     307             :  * the first 100 cells are read.
     308             :  *
     309             :  * If you are using columns as an index, then the column_predicate
     310             :  * parameter gets modified by this function. The start column name
     311             :  * is updated with the name of the last row read on each iteration.
     312             :  *
     313             :  * See the cell_predicate for more information on how to
     314             :  * select columns.
     315             :  *
     316             :  * This function is often called to read an entire row in memory all
     317             :  * at once (this is faster than reading the row one value at a time
     318             :  * if you anyway are likely to read most of the columns.) However,
     319             :  * this function should not be used that way if the row includes an
     320             :  * index.
     321             :  *
     322             :  * \param[in,out] column_predicate  The predicate used to select which columns to read.
     323             :  *
     324             :  * \note This method no longer changes the row set from the query!
     325             :  *
     326             :  * \sa setIndex(), table::readRows()
     327             :  */
     328           0 : uint32_t row::readCells( cell_predicate::pointer_t column_predicate )
     329             : {
     330           0 :     size_t idx(0);
     331           0 :     order_result selected_cells_result;
     332             : 
     333           0 :     f_cells.clear();
     334             : 
     335           0 :     if( f_cursor_index != -1 )
     336             :     {
     337             :         // Note: the "FETCH" is ignored, only the type is used in this case
     338             :         //
     339           0 :         order select_more_cells;
     340           0 :         select_more_cells.setCql("FETCH", order::type_of_result_t::TYPE_OF_RESULT_FETCH);
     341           0 :         select_more_cells.setCursorIndex(f_cursor_index);
     342           0 :         if(f_timeout_ms > 0)
     343             :         {
     344           0 :             select_more_cells.setTimeout(f_timeout_ms);
     345             :         }
     346           0 :         order_result select_more_cells_result(parentTable()->getProxy()->sendOrder(select_more_cells));
     347           0 :         selected_cells_result.swap(select_more_cells_result);
     348           0 :         if(!selected_cells_result.succeeded())
     349             :         {
     350           0 :             throw exception("select cells failed (FETCH)");
     351             :         }
     352             : 
     353           0 :         if(selected_cells_result.resultCount() == 0)
     354             :         {
     355           0 :             closeCursor();
     356           0 :             return 0;
     357             :         }
     358             :     }
     359             :     else
     360             :     {
     361           0 :         auto row_predicate = std::make_shared<row_key_predicate>();
     362           0 :         row_predicate->setRowKey( f_key );
     363             : 
     364             :         // setup the consistency level
     365           0 :         consistency_level_t consistency_level( parentTable()->parentContext()->parentCassandra()->defaultConsistencyLevel() );
     366           0 :         if( column_predicate )
     367             :         {
     368           0 :             consistency_level_t const default_consistency_level(consistency_level);
     369           0 :             consistency_level = column_predicate->consistencyLevel();
     370           0 :             if( consistency_level == CONSISTENCY_LEVEL_DEFAULT )
     371             :             {
     372             :                 // reset back to default if not defined in the column_predicate
     373           0 :                 consistency_level = default_consistency_level;
     374             :             }
     375             :         }
     376             : 
     377             :         // prepare the CQL order
     378           0 :         QString query_string( QString("SELECT column1,value FROM %1.%2")
     379           0 :                        .arg(parentTable()->contextName())
     380           0 :                        .arg(parentTable()->tableName())
     381           0 :                        );
     382           0 :         int bind_count = 0;
     383           0 :         if( column_predicate )
     384             :         {
     385           0 :             row_predicate->setCellPredicate( column_predicate );
     386             :         }
     387           0 :         row_predicate->appendQuery( query_string, bind_count );
     388             : 
     389             :         // WARNING: the row_predicate we create right here, when the
     390             :         //          ALLOW FILTERING flag can only be set by the caller
     391             :         //          in the column_predicate
     392             :         //
     393           0 :         if(column_predicate->allowFiltering())
     394             :         {
     395           0 :             query_string += " ALLOW FILTERING";
     396             :         }
     397             : 
     398             :         //
     399             : //std::cerr << "query=[" << query_string.toUtf8().data() << "]" << std::endl;
     400           0 :         order select_cells;
     401           0 :         select_cells.setCql(query_string, order::type_of_result_t::TYPE_OF_RESULT_DECLARE);
     402           0 :         select_cells.setConsistencyLevel( consistency_level );
     403           0 :         select_cells.setColumnCount(2);
     404           0 :         if(f_timeout_ms > 0)
     405             :         {
     406           0 :             select_cells.setTimeout(f_timeout_ms);
     407             :         }
     408             : 
     409           0 :         row_predicate->bindOrder( select_cells );
     410             : 
     411             :         //
     412           0 :         if( column_predicate )
     413             :         {
     414           0 :             select_cells.setPagingSize( column_predicate->count() );
     415             :         }
     416             :         //
     417             : 
     418           0 :         order_result select_cells_result(parentTable()->getProxy()->sendOrder(select_cells));
     419           0 :         selected_cells_result.swap(select_cells_result);
     420           0 :         if(!selected_cells_result.succeeded())
     421             :         {
     422           0 :             throw exception("select cells failed (SELECT)");
     423             :         }
     424             : 
     425           0 :         if(selected_cells_result.resultCount() < 1)
     426             :         {
     427           0 :             throw exception("select cells did not return a cursor index");
     428             :         }
     429           0 :         f_cursor_index = int32Value(selected_cells_result.result(0));
     430           0 :         if(f_cursor_index < 0)
     431             :         {
     432           0 :             throw logic_exception("received a negative number as cursor index");
     433             :         }
     434             : 
     435             :         // ignore parameter one, it is not a row of data
     436           0 :         idx = 1;
     437             :     }
     438             : 
     439           0 :     size_t const max_results(selected_cells_result.resultCount());
     440             : #ifdef _DEBUG
     441           0 :     if((max_results - idx) % 2 != 0)
     442             :     {
     443             :         // the number of results must be a multiple of 2, although on
     444             :         // the SELECT (first time in) we expect one additional result
     445             :         // which represents the cursor index
     446           0 :         throw logic_exception("the number of results must be an exact multipled of 2!");
     447             :     }
     448             : #endif
     449           0 :     size_t result_size = 0;
     450           0 :     for(; idx < max_results; idx += 2, ++result_size )
     451             :     {
     452           0 :         const QByteArray column_key( selected_cells_result.result( idx + 0 ) );
     453           0 :         const QByteArray data      ( selected_cells_result.result( idx + 1 ) );
     454             : 
     455           0 :         cell::pointer_t new_cell( getCell( column_key ) );
     456           0 :         new_cell->assignValue( value(data) );
     457             :     }
     458             : 
     459           0 :     return result_size;
     460             : }
     461             : 
     462             : 
     463             : /** \brief Retrieve a cell from the row.
     464             :  *
     465             :  * This function retrieves a cell from this row. If the cell
     466             :  * does not exist, it is created.
     467             :  *
     468             :  * Note that the cell is not saved in the Cassandra database
     469             :  * unless you save a value in it (and assuming the context does
     470             :  * not only exist in memory.)
     471             :  *
     472             :  * This function accepts a column name. The UTF-8 version of it is used to
     473             :  * retrieve the data from Cassandra.
     474             :  *
     475             :  * \param[in] column_name  The name of the column referencing this cell.
     476             :  *
     477             :  * \return A shared pointer to the cell.
     478             :  */
     479           0 : cell::pointer_t row::getCell(const char *column_name)
     480             : {
     481           0 :     return getCell( QByteArray(column_name, qstrlen(column_name)) );
     482             : }
     483             : 
     484             : 
     485             : /** \brief Retrieve a cell from the row.
     486             :  *
     487             :  * This function retrieves a cell from this row. If the cell
     488             :  * does not exist, it is created.
     489             :  *
     490             :  * Note that the cell is not saved in the Cassandra database
     491             :  * unless you save a value in it (and assuming the context does
     492             :  * not only exist in memory.)
     493             :  *
     494             :  * This function accepts a column name. The UTF-8 version of it is used to
     495             :  * retrieve the data from Cassandra.
     496             :  *
     497             :  * \param[in] column_name  The name of the column referencing this cell.
     498             :  *
     499             :  * \return A shared pointer to the cell.
     500             :  */
     501           0 : cell::pointer_t row::getCell(const QString& column_name)
     502             : {
     503           0 :     return getCell(column_name.toUtf8());
     504             : }
     505             : 
     506             : 
     507             : /** \brief Retrieve a cell from the row.
     508             :  *
     509             :  * This function retrieves a cell from this row. If the cell
     510             :  * does not exist, it is created.
     511             :  *
     512             :  * Note that the cell is not saved in the Cassandra database
     513             :  * unless you save a value in it (and assuming the context does
     514             :  * not only exist in memory.)
     515             :  *
     516             :  * This function makes use of a binary key to reference the cell.
     517             :  *
     518             :  * \note
     519             :  * This function cannot be used to read a composite column unless
     520             :  * you know how to build the QByteArray to do so. I suggest you
     521             :  * use the compositeCell() function instead.
     522             :  *
     523             :  * \param[in] column_key  The binary key of the column referencing this cell.
     524             :  *
     525             :  * \return A shared pointer to the cell.
     526             :  *
     527             :  * \sa compositeCell()
     528             :  * \sa compositeCell() const
     529             :  */
     530           0 : cell::pointer_t row::getCell(const QByteArray& column_key)
     531             : {
     532             :     // column already exists?
     533           0 :     cells::iterator ci(f_cells.find(column_key));
     534           0 :     if(ci != f_cells.end()) {
     535           0 :         return ci.value();
     536             :     }
     537             : 
     538             :     // this is a new column, allocate it
     539           0 :     cell::pointer_t c(new cell(shared_from_this(), column_key));
     540           0 :     f_cells.insert(column_key, c);
     541           0 :     return c;
     542             : }
     543             : 
     544             : 
     545             : /** \brief Retrieve the map of cells.
     546             :  *
     547             :  * This function returns a constant reference to the map of cells defined in
     548             :  * the row.
     549             :  *
     550             :  * This map does not generally represent all the cells of a row as only those
     551             :  * that you already accessed in read or write mode will be defined in memory.
     552             :  *
     553             :  * \note
     554             :  * The order of the cells in memory may not be the same as the order of the
     555             :  * cells in the database. This is especially true if the data is not integers.
     556             :  * (i.e. floating point numbers, UTF-8 or other encodings with characters
     557             :  * that are not ordered in the same order as the bytes representing them,
     558             :  * etc.) This also depends on the definition of the type in Cassandra.
     559             :  * Positive integers should always be properly sorted. Negative integers may
     560             :  * be a problem if you use the "wrong" type in Cassandra. FYI, the order of
     561             :  * the map of cells uses the QByteArray < operator.
     562             :  *
     563             :  * \warning
     564             :  * When reading cells from a row representing an index, you probably want to
     565             :  * clear the cells already read before the next read. This is done with the
     566             :  * clearCache() function. Then getCells().isEmpty() returns true if no more
     567             :  * cells can be read from the database.
     568             :  *
     569             :  * \warning
     570             :  * The dropCell() function actually deletes the cell from this map and
     571             :  * therefore the map becomes invalid if you use an iterator in a loop.
     572             :  * Make sure you reset the iterator each time.
     573             :  *
     574             :  * \return The map of cells referenced by column keys.
     575             :  *
     576             :  * \sa clearCache()
     577             :  */
     578           0 : const cells& row::getCells() const
     579             : {
     580           0 :     return f_cells;
     581             : }
     582             : 
     583             : 
     584             : /** \brief Retrieve a cell from the row.
     585             :  *
     586             :  * This function retrieves a cell from this row. If the cell
     587             :  * does not exist, it returns a NULL pointer (i.e. isNull() on the
     588             :  * shared pointer returns true.)
     589             :  *
     590             :  * This function accepts a column name. The UTF-8 version of it is used to
     591             :  * retrieve the data from Cassandra.
     592             :  *
     593             :  * \warning
     594             :  * This function does NOT attempt to read the cell from the Cassandra database
     595             :  * system. It only checks whether the cell already exists in memory. To check
     596             :  * whether the cell exists in the database, use the exists() function instead.
     597             :  *
     598             :  * \param[in] column_name  The name of the column referencing this cell.
     599             :  *
     600             :  * \return A shared pointer to the cell.
     601             :  *
     602             :  * \sa getCell()
     603             :  * \sa exists()
     604             :  */
     605           0 : cell::pointer_t row::findCell(const QString& column_name) const
     606             : {
     607           0 :     return findCell(column_name.toUtf8());
     608             : }
     609             : 
     610             : 
     611             : /** \brief Retrieve a cell from the row.
     612             :  *
     613             :  * This function retrieves a cell from this row. If the cell
     614             :  * does not exist, it returns a NULL pointer (i.e. isNull() on the
     615             :  * shared pointer returns true.)
     616             :  *
     617             :  * This function makes use of a binary key to reference the cell.
     618             :  *
     619             :  * \warning
     620             :  * This function does NOT attempt to read the cell from the Cassandra database
     621             :  * system. It only checks whether the cell already exists in memory. To check
     622             :  * whether the cell exists in the database, use the exists() function instead.
     623             :  *
     624             :  * \param[in] column_key  The binary key of the column referencing this cell.
     625             :  *
     626             :  * \return A shared pointer to the cell.
     627             :  *
     628             :  * \sa getCell()
     629             :  * \sa exists()
     630             :  */
     631           0 : cell::pointer_t row::findCell(const QByteArray& column_key) const
     632             : {
     633           0 :     cells::const_iterator ci(f_cells.find(column_key));
     634           0 :     if(ci == f_cells.end()) {
     635           0 :         cell::pointer_t null;
     636           0 :         return null;
     637             :     }
     638           0 :     return *ci;
     639             : }
     640             : 
     641             : 
     642             : /** \brief Check whether a cell exists in this row.
     643             :  *
     644             :  * The check is happening in memory first. If the cell doesn't exist in memory,
     645             :  * then the row checks in the Cassandra database.
     646             :  *
     647             :  * \todo
     648             :  * Look into why a cell is created when just checking for its existance.
     649             :  *
     650             :  * \bug
     651             :  * At this time this function CREATES the cell if it did not yet
     652             :  * exist!
     653             :  *
     654             :  * \param[in] column_name  The column name.
     655             :  *
     656             :  * \return true if the cell exists, false otherwise.
     657             :  */
     658           0 : bool row::exists(const char * column_name) const
     659             : {
     660           0 :     return exists(QString(column_name));
     661             : }
     662             : 
     663             : 
     664             : /** \brief Check whether a cell exists in this row.
     665             :  *
     666             :  * The check is happening in memory first. If the cell doesn't exist in memory,
     667             :  * then the row checks in the Cassandra database.
     668             :  *
     669             :  * \todo
     670             :  * Look into why a cell is created when just checking for its existance.
     671             :  *
     672             :  * \bug
     673             :  * At this time this function CREATES the cell if it did not yet
     674             :  * exist!
     675             :  *
     676             :  * \param[in] column_name  The column name.
     677             :  *
     678             :  * \return true if the cell exists, false otherwise.
     679             :  */
     680           0 : bool row::exists(const QString& column_name) const
     681             : {
     682           0 :     return exists(column_name.toUtf8());
     683             : }
     684             : 
     685             : 
     686             : /** \brief Check whether a cell exists in this row.
     687             :  *
     688             :  * The check is happening in memory first. If the cell doesn't exist in memory,
     689             :  * then the row checks in the Cassandra database.
     690             :  *
     691             :  * \param[in] column_key  The column binary key.
     692             :  *
     693             :  * \return true if the cell exists, false otherwise.
     694             :  */
     695           0 : bool row::exists(const QByteArray& column_key) const
     696             : {
     697           0 :     cells::const_iterator ci(f_cells.find(column_key));
     698           0 :     if(ci != f_cells.end())
     699             :     {
     700             :         // exists in the cache already
     701           0 :         return true;
     702             :     }
     703             : 
     704             :     // This is already done by the readRows() method of table.
     705             :     // If you have an instance of this class without going through the
     706             :     // table interface, it won't work right.
     707             :     //
     708             :     // try reading this cell
     709           0 :     value value;
     710             :     try
     711             :     {
     712           0 :         if(!parentTable()->getValue(f_key, column_key, value))
     713             :         {
     714           0 :             return false;
     715             :         }
     716             :     }
     717           0 :     catch( const std::exception& )
     718             :     {
     719           0 :         return false;
     720             :     }
     721             : 
     722             :     // since we just got the value, we might as well cache it
     723             :     //
     724           0 :     cell::pointer_t c(const_cast<row *>(this)->getCell(column_key));
     725           0 :     c->assignValue(value);
     726             : 
     727           0 :     return true;
     728             : }
     729             : 
     730             : 
     731             : /** \brief Retrieve a cell from the row.
     732             :  *
     733             :  * This function retrieves a reference to a cell from this row in
     734             :  * array syntax.
     735             :  *
     736             :  * This version returns a writable cell and it creates a new cell
     737             :  * when one with the specified name doesn't already exist.
     738             :  *
     739             :  * This function accepts a column name. The UTF-8 version of it is used to
     740             :  * retrieve the data from Cassandra.
     741             :  *
     742             :  * \param[in] column_name  The name of the column referencing this cell.
     743             :  *
     744             :  * \return A shared pointer to the cell.
     745             :  */
     746           0 : cell& row::operator [] (const char * column_name)
     747             : {
     748           0 :     return *getCell(column_name);
     749             : }
     750             : 
     751             : 
     752             : /** \brief Retrieve a cell from the row.
     753             :  *
     754             :  * This function retrieves a reference to a cell from this row in
     755             :  * array syntax.
     756             :  *
     757             :  * This version returns a writable cell and it creates a new cell
     758             :  * when one with the specified name doesn't already exist.
     759             :  *
     760             :  * This function accepts a column name. The UTF-8 version of it is used to
     761             :  * retrieve the data from Cassandra.
     762             :  *
     763             :  * \param[in] column_name  The name of the column referencing this cell.
     764             :  *
     765             :  * \return A shared pointer to the cell.
     766             :  */
     767           0 : cell& row::operator [] (const QString& column_name)
     768             : {
     769           0 :     return *getCell(column_name);
     770             : }
     771             : 
     772             : 
     773             : /** \brief Retrieve a cell from the row.
     774             :  *
     775             :  * This function retrieves a reference to a cell from this row in
     776             :  * array syntax.
     777             :  *
     778             :  * This version returns a writable cell and it creates a new cell
     779             :  * when one with the specified name doesn't already exist.
     780             :  *
     781             :  * This function makes use of a binary key to reference the cell.
     782             :  *
     783             :  * \param[in] column_key  The binary key of the column referencing this cell.
     784             :  *
     785             :  * \return A shared pointer to the cell.
     786             :  */
     787           0 : cell& row::operator [] (const QByteArray& column_key)
     788             : {
     789           0 :     return *getCell(column_key);
     790             : }
     791             : 
     792             : 
     793             : /** \brief Retrieve a cell from the row.
     794             :  *
     795             :  * This function retrieves a constant reference to a cell from this row
     796             :  * in array syntax.
     797             :  *
     798             :  * This version returns a read-only cell. If the cell doesn't exist,
     799             :  * the funtion raises an exception.
     800             :  *
     801             :  * This function accepts a column name. The UTF-8 version of it is used to
     802             :  * retrieve the data from Cassandra.
     803             :  *
     804             :  * \exception exception
     805             :  * This function requires that the cell being accessed already exist
     806             :  * in memory. If not, this exception is raised.
     807             :  *
     808             :  * \param[in] column_name  The name of the column referencing this cell.
     809             :  *
     810             :  * \return A shared pointer to the cell.
     811             :  */
     812           0 : const cell& row::operator [] (const char* column_name) const
     813             : {
     814           0 :     return operator [] (QString(column_name));
     815             : }
     816             : 
     817             : 
     818             : /** \brief Retrieve a cell from the row.
     819             :  *
     820             :  * This function retrieves a constant reference to a cell from this row
     821             :  * in array syntax.
     822             :  *
     823             :  * This version returns a read-only cell. If the cell doesn't exist, 
     824             :  * the funtion raises an exception.
     825             :  *
     826             :  * This function accepts a column name. The UTF-8 version of it is used to
     827             :  * retrieve the data from Cassandra.
     828             :  *
     829             :  * \exception exception
     830             :  * This function requires that the cell being accessed already exist
     831             :  * in memory. If not, this exception is raised.
     832             :  *
     833             :  * \param[in] column_name  The name of the column referencing this cell.
     834             :  *
     835             :  * \return A shared pointer to the cell.
     836             :  */
     837           0 : const cell& row::operator [] (const QString& column_name) const
     838             : {
     839           0 :     return operator [] (column_name.toUtf8());
     840             : }
     841             : 
     842             : 
     843             : /** \brief Retrieve a cell from the row.
     844             :  *
     845             :  * This function retrieves a cell from this row in array syntax.
     846             :  *
     847             :  * This version returns a writable cell and it creates a new cell
     848             :  * when one with the specified name doesn't already exist.
     849             :  *
     850             :  * This function makes use of a binary key to reference the cell.
     851             :  *
     852             :  * \param[in] column_key  The binary key of the column referencing this cell.
     853             :  *
     854             :  * \return A shared pointer to the cell.
     855             :  */
     856           0 : const cell& row::operator [] (const QByteArray& column_key) const
     857             : {
     858           0 :     cell::pointer_t p_cell( findCell(column_key) );
     859           0 :     if( !p_cell )
     860             :     {
     861           0 :         throw exception("named column while retrieving a cell was not found, cannot return a reference");
     862             :     }
     863             : 
     864           0 :     return *p_cell;
     865             : }
     866             : 
     867             : 
     868             : /** \brief Clear the cached cells.
     869             :  *
     870             :  * This function is used to clear all the cells that were cached in this row.
     871             :  *
     872             :  * As a side effect, all the cell objects are unparented which means
     873             :  * that you cannot use them anymore (doing so raises an exception.)
     874             :  */
     875           0 : void row::clearCache()
     876             : {
     877           0 :     closeCursor();
     878             : 
     879           0 :     f_cells.clear();
     880           0 : }
     881             : 
     882             : 
     883             : /** \brief Close the current cursor.
     884             :  *
     885             :  * This function closes the current cursor (i.e. the cursor used
     886             :  * to gather a set of rows and their data from a table.)
     887             :  */
     888           0 : void row::closeCursor()
     889             : {
     890           0 :     if(f_cursor_index >= 0)
     891             :     {
     892             :         // Note: the "CLOSE" CQL string is ignored
     893             :         //
     894           0 :         order close_cursor;
     895           0 :         close_cursor.setCql("CLOSE", order::type_of_result_t::TYPE_OF_RESULT_CLOSE);
     896           0 :         close_cursor.setCursorIndex(f_cursor_index);
     897           0 :         if(f_timeout_ms > 0)
     898             :         {
     899           0 :             close_cursor.setTimeout(f_timeout_ms);
     900             :         }
     901           0 :         order_result close_cursor_result(parentTable()->getProxy()->sendOrder(close_cursor));
     902           0 :         if(!close_cursor_result.succeeded())
     903             :         {
     904           0 :             throw exception("row::closeCursor(): closing cursor failed.");
     905             :         }
     906           0 :         f_cursor_index = -1;
     907             :     }
     908           0 : }
     909             : 
     910             : 
     911             : /** \brief Drop the named cell.
     912             :  *
     913             :  * This function is the same as the dropCell() that accepts a QByteArray
     914             :  * as its column key. It simply calls it after changing the column name into
     915             :  * a key.
     916             :  *
     917             :  * \param[in] column_name  The name of the column to drop.
     918             :  */
     919           0 : void row::dropCell(const char * column_name)
     920             : {
     921           0 :     dropCell(QByteArray(column_name, qstrlen(column_name)));
     922           0 : }
     923             : 
     924             : 
     925             : /** \brief Drop the named cell.
     926             :  *
     927             :  * This function is the same as the dropCell() that accepts a QByteArray
     928             :  * as its column key. It simply calls it after changing the column name into
     929             :  * a key.
     930             :  *
     931             :  * \param[in] column_name  The name of the column to drop.
     932             :  */
     933           0 : void row::dropCell(const QString& column_name)
     934             : {
     935           0 :     dropCell(column_name.toUtf8());
     936           0 : }
     937             : 
     938             : 
     939             : /** \brief Drop the specified cell from the Cassandra database.
     940             :  *
     941             :  * This function deletes the specified cell and its data from the Cassandra
     942             :  * database and from memory. To delete the cell immediately you want to set
     943             :  * the timestamp to now (i.e. use libdbproxy::timeofday() with the DEFINED
     944             :  * mode as mentioned below.)
     945             :  *
     946             :  * The timestamp \p mode can be set to value::TIMESTAMP_MODE_DEFINED
     947             :  * in which case the value defined in the \p timestamp parameter is used by the
     948             :  * Cassandra remove() function.
     949             :  *
     950             :  * By default the \p mode parameter is set to
     951             :  * value::TIMESTAMP_MODE_AUTO which means that the timestamp
     952             :  * value of the cell f_value parameter is used. This will NOT WORK RIGHT
     953             :  * if the timestamp of the cell value was never set properly (i.e. you
     954             :  * never read the cell from the Cassandra database and never called
     955             :  * the setTimestamp() function on the cell value.) You have two choices here.
     956             :  * You may specify the timestamp on the dropCell() call, or you may change
     957             :  * the cell timestamp:
     958             :  *
     959             :  * \code
     960             :  *     // this is likely to fail if you created the cell in this session
     961             :  *     row->dropCell(cell_name);
     962             :  *
     963             :  *     // define the timestamp in the cell
     964             :  *     cell->setTimestamp(libdbproxy::timeofday());
     965             :  *
     966             :  *     // define the timestamp in the dropCell() call
     967             :  *     row->dropCell(cell_name, value::TIMESTAMP_MODE_DEFINED, libdbproxy::timeofday());
     968             :  * \endcode
     969             :  *
     970             :  * The consistency level of the cell f_value is also passed to the Cassandra
     971             :  * remove() function. This means that by default you'll get whatever the
     972             :  * default is from your libdbproxy object, the default in the value or
     973             :  * whatever the value was when you last read the value. To change that
     974             :  * default you can retrieve the cell and set the consistency level as follow:
     975             :  *
     976             :  * \code
     977             :  *     cell::pointer_t c(f_row->getCell(f_cell));
     978             :  * \endcode
     979             :  *
     980             :  * These 2 lines of code do NOT create the cell in the Cassandra cluster.
     981             :  * It only creates it in memory unless it was read earlier in which case
     982             :  * the cached copy is returned.
     983             :  *
     984             :  * \warning
     985             :  * The corresponding cell is marked as dropped, whether you kept a shared
     986             :  * pointer of that cell does not make it reusable. You must forget about it
     987             :  * after this call.
     988             :  *
     989             :  * \warning
     990             :  * If you used the getCells() function to retrieve a reference to the list of
     991             :  * cells as a reference, that list is broken when this function returns.
     992             :  * Make sure to re-retrieve the list after each call to the dropCell()
     993             :  * function.
     994             :  *
     995             :  * \param[in] column_key  A shared pointer to the cell to remove.
     996             :  * \param[in] mode  Specify the timestamp mode.
     997             :  * \param[in] timestamp  Specify the timestamp to remove only cells that are equal or older.
     998             :  *
     999             :  * \sa getCell()
    1000             :  * \sa getCells()
    1001             :  * \sa libdbproxy::timeofday()
    1002             :  */
    1003           0 : void row::dropCell( const QByteArray& column_key )
    1004             : {
    1005           0 :     cell::pointer_t c(getCell(column_key));
    1006             : 
    1007           0 :     parentTable()->remove( f_key, column_key, c->consistencyLevel() );
    1008           0 :     f_cells.remove(column_key);
    1009           0 : }
    1010             : 
    1011             : 
    1012             : /** \brief Get the pointer to the parent object.
    1013             :  *
    1014             :  * \return Shared pointer to the table object with owns this object.
    1015             :  */
    1016           0 : table::pointer_t row::parentTable() const
    1017             : {
    1018           0 :     table::pointer_t table(f_table.lock());
    1019           0 :     if(table == nullptr)
    1020             :     {
    1021           0 :         throw exception("this row was dropped and is not attached to a table anymore");
    1022             :     }
    1023             : 
    1024           0 :     return table;
    1025             : }
    1026             : 
    1027             : 
    1028             : /** \brief Save a cell value that changed.
    1029             :  *
    1030             :  * This function calls the table insertValue() function to save the new value that
    1031             :  * was defined in a cell.
    1032             :  *
    1033             :  * \param[in] column_key  The key used to identify the column.
    1034             :  * \param[in] value  The new value of the cell.
    1035             :  */
    1036           0 : void row::insertValue(const QByteArray& column_key, const value& value)
    1037             : {
    1038           0 :     parentTable()->insertValue(f_key, column_key, value);
    1039           0 : }
    1040             : 
    1041             : 
    1042             : /** \brief Get a cell value from Cassandra.
    1043             :  *
    1044             :  * This function calls the table getValue() function to retrieve the currrent
    1045             :  * value that defined in a cell.
    1046             :  *
    1047             :  * If the cell does not exist, then value is set to the Null value.
    1048             :  *
    1049             :  * \param[in] column_key  The key used to identify the column.
    1050             :  * \param[out] value  To return the value of the cell.
    1051             :  *
    1052             :  * \return false when the value was not found in the database, true otherwise
    1053             :  */
    1054           0 : bool row::getValue(const QByteArray& column_key, value& value)
    1055             : {
    1056           0 :     return parentTable()->getValue(f_key, column_key, value);
    1057             : }
    1058             : 
    1059             : 
    1060             : /** \brief Add a value to a Cassandra counter.
    1061             :  *
    1062             :  * This function calls the table addValue() function to add the specified
    1063             :  * value to the Cassandra counter that is defined in a cell.
    1064             :  *
    1065             :  * If the cell counter does not exist yet, then value is set to the specified
    1066             :  * value.
    1067             :  * 
    1068             :  * \note this is a synonym for row::insertValue(), since counters
    1069             :  * are automatically sensed and handled with an "UPDATE" instead of an "INSERT".
    1070             :  *
    1071             :  * \param[in] column_key  The key used to identify the column.
    1072             :  * \param[in] value  To value to add to this counter.
    1073             :  */
    1074           0 : void row::addValue(const QByteArray& column_key, int64_t value)
    1075             : {
    1076           0 :     return parentTable()->insertValue(f_key, column_key, value);
    1077             : }
    1078             : 
    1079             : 
    1080           6 : } // namespace libdbproxy
    1081             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13