diff --git a/core/ArchiveProcessor/Period.php b/core/ArchiveProcessor/Period.php
index 8a87c1fd1e7d96557d77db8750c97dd925e828e1..a885bfefde9533a856d1392830199876cdaece29 100644
--- a/core/ArchiveProcessor/Period.php
+++ b/core/ArchiveProcessor/Period.php
@@ -164,7 +164,7 @@ class Period extends ArchiveProcessor
     {
         $table = new DataTable();
         if (!empty($columnAggregationOperations)) {
-            $table->setColumnAggregationOperations($columnAggregationOperations);
+            $table->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME] = $columnAggregationOperations;
         }
 
         $data = $this->archiver->getDataTableExpanded($name, $idSubTable = null, $depth = null, $addMetadataSubtableId = false);
diff --git a/core/DataTable.php b/core/DataTable.php
index 208e2173506e71f895c2c5dac7f22122bc6a5c11..e985f09b7591dee385acefd8d0345168af061386 100644
--- a/core/DataTable.php
+++ b/core/DataTable.php
@@ -29,11 +29,14 @@ require_once PIWIK_INCLUDE_PATH . '/core/Common.php';
 /**
  * The primary data structure used to store analytics data in Piwik.
  * 
+ * <a name="class-desc-the-basics"></a>
  * ### The Basics
  * 
  * DataTables consist of rows and each row consists of columns. A column value can be
  * be a numeric, string or array.
  * 
+ * Every row has an ID. The ID is either the index of the row or [ID_SUMMARY_ROW](#ID_SUMMARY_ROW).
+ * 
  * DataTables are hierarchical data structures. Each row can also contain an additional
  * nested sub-DataTable.
  * 
@@ -100,9 +103,64 @@ require_once PIWIK_INCLUDE_PATH . '/core/Common.php';
  * ### Examples
  * 
  * **Populating a DataTable**
+ * 
+ *     // adding one row at a time
+ *     $dataTable = new DataTable();
+ *     $dataTable->addRow(new Row(array(
+ *         Row::COLUMNS => array('label' => 'thing1', 'nb_visits' => 1, 'nb_actions' => 1),
+ *         Row::METADATA => array('url' => 'http://thing1.com')
+ *     )));
+ *     $dataTable->addRow(new Row(array(
+ *         Row::COLUMNS => array('label' => 'thing2', 'nb_visits' => 2, 'nb_actions' => 2),
+ *         Row::METADATA => array('url' => 'http://thing2.com')
+ *     )));
+ *     
+ *     // using an array of rows
+ *     $dataTable = new DataTable();
+ *     $dataTable->addRowsFromArray(array(
+ *         array(
+ *             Row::COLUMNS => array('label' => 'thing1', 'nb_visits' => 1, 'nb_actions' => 1),
+ *             Row::METADATA => array('url' => 'http://thing1.com')
+ *         ),
+ *         array(
+ *             Row::COLUMNS => array('label' => 'thing2', 'nb_visits' => 2, 'nb_actions' => 2),
+ *             Row::METADATA => array('url' => 'http://thing2.com')
+ *         )
+ *     ));
+ * 
+ *     // using a "simple" array
+ *     $dataTable->addRowsFromSimpleArray(array(
+ *         array('label' => 'thing1', 'nb_visits' => 1, 'nb_actions' => 1),
+ *         array('label' => 'thing2', 'nb_visits' => 2, 'nb_actions' => 2)
+ *     ));
+ * 
+ * **Getting & setting metadata**
+ * 
+ *     $dataTable = \Piwik\Plugins\Referrers\API::getInstance()->getSearchEngines($idSite = 1, $period = 'day', $date = '2007-07-24');
+ *     $oldPeriod = $dataTable->metadata['period'];
+ *     $dataTable->metadata['period'] = Period::factory('week', Date::factory('2013-10-18'));
+ * 
  * **Serializing & unserializing**
+ * 
+ *     $maxRowsInTable = Config::getInstance()->General['datatable_archiving_maximum_rows_standard'];j
+ *     
+ *     $dataTable = // ... build by aggregating visits ...
+ *     $serializedData = $dataTable->getSerialized($maxRowsInTable, $maxRowsInSubtable = $maxRowsInTable,
+ *                                                 $columnToSortBy = Metrics::INDEX_NB_VISITS);
+ *     
+ *     $serializedDataTable = $serializedData['0'];
+ *     $serailizedSubTable = $serializedData[$idSubtable];
+ * 
  * **Filtering for an API method**
- * ??? TODO
+ * 
+ *     public function getMyReport($idSite, $period, $date, $segment = false, $expanded = false)
+ *     {
+ *         $dataTable = Archive::getDataTableFromArchive('MyPlugin_MyReport', $idSite, $period, $date, $segment, $expanded);
+ *         $dataTable->filter('Sort', array(Metrics::INDEX_NB_VISITS, 'desc', $naturalSort = false, $expanded));
+ *         $dataTable->queueFilter('ReplaceColumnNames');
+ *         $dataTable->queueFilter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getUrlFromLabelForMyReport'));
+ *         return $dataTable;
+ *     }
  * 
  * @package Piwik
  * @subpackage DataTable
@@ -111,12 +169,38 @@ require_once PIWIK_INCLUDE_PATH . '/core/Common.php';
  */
 class DataTable implements DataTableInterface
 {
+    const MAX_DEPTH_DEFAULT = 15;
+
     /** Name for metadata that describes when a report was archived. */
     const ARCHIVED_DATE_METADATA_NAME = 'archived_date';
-    const MAX_DEPTH_DEFAULT = 15;
+
     /** Name for metadata that describes which columns are empty and should not be shown. */
     const EMPTY_COLUMNS_METADATA_NAME = 'empty_column';
 
+    /** Name for metadata that describes the number of rows that existed before the Limit filter was applied. */
+    const TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME = 'total_rows_before_limit';
+
+    /**
+     * Name for metadata that describes how individual columns should be aggregated when [addDataTable](#addDataTable)
+     * or [DataTable\Row::sumRow](#) is called.
+     * 
+     * This metadata value must be an array that maps column names with valid operations. Valid aggregation operations are:
+     * 
+     * - `'skip'`: do nothing
+     * - `'max'`: does `max($column1, $column2)`
+     * - `'min'`: does `min($column1, $column2)`
+     * - `'sum'`: does `$column1 + $column2`
+     * 
+     * See [addDataTable](#addDataTable) and [DataTable\Row::sumRow](#) for more information.
+     */
+    const COLUMN_AGGREGATION_OPS_METADATA_NAME = 'column_aggregation_ops';
+
+    /** The ID of the Summary Row. */
+    const ID_SUMMARY_ROW = -1;
+
+    /** The original label of the Summary Row. */
+    const LABEL_SUMMARY_ROW = -1;
+
     /**
      * Maximum nesting level.
      */
@@ -207,7 +291,9 @@ class DataTable implements DataTableInterface
     protected $summaryRow = null;
 
     /**
-     * Table metadata.
+     * Table metadata. Read [this](#class-desc-the-basics) to learn more.
+     * 
+     * Any data that describes the data held in the table's rows should go here.
      *
      * @var array
      */
@@ -222,24 +308,19 @@ class DataTable implements DataTableInterface
     protected $maximumAllowedRows = 0;
 
     /**
-     * The operations that should be used when aggregating columns from multiple rows.
-     * @see self::addDataTable() and DataTable\Row::sumRow()
-     */
-    protected $columnAggregationOperations = array();
-
-    const ID_SUMMARY_ROW = -1;
-    const LABEL_SUMMARY_ROW = -1;
-
-    /**
-     * Builds the DataTable, registers itself to the manager
+     * Constructor. Creates an empty DataTable.
      */
     public function __construct()
     {
+        // registers this instance to the manager
         $this->currentId = Manager::getInstance()->addTable($this);
+
+        // initialize some metadata
+        $this->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME] = array();
     }
 
     /**
-     * At destruction we free all memory
+     * Destructor. Makes sure DataTable memory will be cleaned up.
      */
     public function __destruct()
     {
@@ -259,10 +340,11 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Sort the dataTable rows using the php callback function
+     * Sorts the DataTable rows using the supplied callback function.
      *
-     * @param string $functionCallback
-     * @param string $columnSortedBy The column name. Used to then ask the datatable what column are you sorted by
+     * @param string $functionCallback A comparison callback compatible with `usort`.
+     * @param string $columnSortedBy The column name `$functionCallback` sorts by. This is stored
+     *                               so we can determine how the DataTable is sorted in the future.
      */
     public function sort($functionCallback, $columnSortedBy)
     {
@@ -282,9 +364,11 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the name of the column the tables is sorted by
+     * Returns the name of the column this table was sorted by (if any).
      *
-     * @return bool|string
+     * See [sort](#sort).
+     *
+     * @return false|string The sorted column name or false if none.
      */
     public function getSortedByColumnName()
     {
@@ -292,8 +376,8 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Enables the recursive sort. Means that when using $table->sort()
-     * it will also sort all subtables using the same callback
+     * Enables recursive sorting. If this method is called [sort](#sort) will also sort all
+     * subtables.
      */
     public function enableRecursiveSort()
     {
@@ -301,8 +385,8 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Enables the recursive filter. Means that when using $table->filter()
-     * it will also filter all subtables using the same callback
+     * Enables recursive filtering. If this method is called then the [filter](#filter) method
+     * will apply filters to every subtable in addition to this instance.
      */
     public function enableRecursiveFilters()
     {
@@ -310,33 +394,15 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the number of rows before we applied the limit filter
-     *
-     * @return int
-     */
-    public function getRowsCountBeforeLimitFilter()
-    {
-        $toReturn = $this->rowsCountBeforeLimitFilter;
-        if ($toReturn == 0) {
-            return $this->getRowsCount();
-        }
-        return $toReturn;
-    }
-
-    /**
-     * Saves the current number of rows
-     */
-    public function setRowsCountBeforeLimitFilter()
-    {
-        $this->rowsCountBeforeLimitFilter = $this->getRowsCount();
-    }
-
-    /**
-     * Apply a filter to this datatable
+     * Applies filter to this datatable.
+     * 
+     * If [enableRecursiveFilters](#enableRecursiveFilters) was called, the filter will be applied
+     * to all subtables as well.
      *
-     * @param string|Closure $className Class name, eg. "Sort" or "Sort".
-     *                                    If this variable is a closure, it will get executed immediately.
-     * @param array $parameters Array of parameters to the filter, eg. array('nb_visits', 'asc')
+     * @param string|Closure $className Class name, eg. "Sort" or "Sort". If no namespace is supplied,
+     *                                  `Piwik\DataTable\Filter` is assumed. This parameter can also be
+     *                                  a closure that takes a DataTable as its first parameter.
+     * @param array $parameters Array of parameters pass to the filter in addition to the table.
      */
     public function filter($className, $parameters = array())
     {
@@ -363,10 +429,13 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Queue a DataTable_Filter that will be applied when applyQueuedFilters() is called.
-     * (just before sending the datatable back to the browser (or API, etc.)
+     * Adds a filter and a list of parameters to the list of queued filters. These filters will be
+     * executed when [applyQueuedFilters](#applyQueuedFilters) is called.
+     * 
+     * Filters that prettify the output or don't need the full set of rows should be queued. This
+     * way they will be run after the table is truncated which will result in better performance.
      *
-     * @param string $className The class name of the filter, eg. Limit
+     * @param string|Closure $className The class name of the filter, eg. Limit
      * @param array $parameters The parameters to give to the filter, eg. array( $offset, $limit) for the filter Limit
      */
     public function queueFilter($className, $parameters = array())
@@ -378,8 +447,8 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Apply all filters that were previously queued to this table
-     * @see queueFilter()
+     * Applies all filters that were previously queued to the table. See [queueFilter](#queueFilter)
+     * for more information.
      */
     public function applyQueuedFilters()
     {
@@ -390,16 +459,18 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Adds a new DataTable to this DataTable
-     * Go through all the rows of the new DataTable and applies the algorithm:
-     * - if a row in $table doesnt exist in $this we add the new row to $this
-     * - if a row exists in both $table and $this we sum the columns values into $this
-     * - if a row in $this doesnt exist in $table we add in $this the row of $table without modification
-     *
-     * A common row to 2 DataTable is defined by the same label
-     *
-     * @example  tests/core/DataTable.test.php
-     *
+     * Sums a DataTable to this one.
+     * 
+     * This method will sum rows that have the same label. If a row is found in `$tableToSum` whose
+     * label is not found in `$this`, the row will be added to `$this` DataTable.
+     * 
+     * If the subtables for this table are loaded, they will be summed as well.
+     * 
+     * Rows are summed together by summing individual columns. By default columns are summed by
+     * adding one column value to another. Some columns cannot be aggregated this way. In these
+     * cases, the [COLUMN_AGGREGATION_OPS_METADATA_NAME](#COLUMN_AGGREGATION_OPS_METADATA_NAME)
+     * metadata can be used to specify a different type of operation.
+     * 
      * @param \Piwik\DataTable $tableToSum
      */
     public function addDataTable(DataTable $tableToSum)
@@ -422,7 +493,8 @@ class DataTable implements DataTableInterface
                 // then we have to recursively sum the subtables
                 if (($idSubTable = $row->getIdSubDataTable()) !== null) {
                     $subTable = Manager::getInstance()->getTable($idSubTable);
-                    $subTable->setColumnAggregationOperations($this->columnAggregationOperations);
+                    $subTable->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME]
+                        = $this->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME];
                     $rowFound->sumSubtable($subTable);
                 }
             }
@@ -430,10 +502,13 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the Row that has a column 'label' with the value $label
-     *
-     * @param string $label Value of the column 'label' of the row to return
-     * @return \Piwik\DataTable\Row|bool  The row if found, false otherwise
+     * Returns the Row whose `'label'` column is equal to `$label`.
+     * 
+     * This method executes in constant time except for the first call which caches row
+     * label => row ID mappings.
+     * 
+     * @param string $label `'label'` column value to look for.
+     * @return Row|false The row if found, false if otherwise.
      */
     public function getRowFromLabel($label)
     {
@@ -453,10 +528,13 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the row id for the givel label
+     * Returns the row id for the row whose `'label'` column is equal to `$label`.
      *
-     * @param string $label Value of the column 'label' of the row to return
-     * @return int|Row
+     * This method executes in constant time except for the first call which caches row
+     * label => row ID mappings.
+     * 
+     * @param string $label `'label'` column value to look for.
+     * @return int The row ID.
      */
     public function getRowIdFromLabel($label)
     {
@@ -468,7 +546,7 @@ class DataTable implements DataTableInterface
         if ($label === self::LABEL_SUMMARY_ROW
             && !is_null($this->summaryRow)
         ) {
-            return $this->summaryRow;
+            return self::ID_SUMMARY_ROW;
         }
 
         $label = (string)$label;
@@ -479,11 +557,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Get an empty table with the same properties as this one
-     *
-     * @param bool $keepFilters
+     * Returns an empty DataTable with the same metadata and queued filters as `$this` one.
      *
-     * @return \Piwik\DataTable
+     * @param bool $keepFilters Whether to pass the queued filter list to the new DataTable or not.
+     * @return DataTable
      */
     public function getEmptyClone($keepFilters = true)
     {
@@ -510,10 +587,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the ith row in the array
+     * Returns a row by ID. The ID is either the index of the row or [ID_SUMMARY_ROW](#ID_SUMMARY_ROW).
      *
-     * @param int $id
-     * @return \Piwik\DataTable\Row or false if not found
+     * @param int $id The row ID.
+     * @return Row|false The Row or false if not found.
      */
     public function getRowFromId($id)
     {
@@ -529,10 +606,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns a row that has the subtable ID matching the parameter
-     *
-     * @param int $idSubTable
-     * @return \Piwik\DataTable\Row|bool    false if not found
+     * Returns the row that has a subtable with ID matching `$idSubtable`.
+     * 
+     * @param int $idSubTable The subtable ID.
+     * @return Row|false The row or false if not found
      */
     public function getRowFromIdSubDataTable($idSubTable)
     {
@@ -546,10 +623,14 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Add a row to the table and rebuild the index if necessary
+     * Adds a row to this table.
+     * 
+     * If [setMaximumAllowedRows](#setMaximumAllowedRows) was called and the current row count is 
+     * at the maximum, the new row will be summed to the summary row. If there is no summary row,
+     * this row is set as the summary row.
      *
-     * @param \Piwik\DataTable\Row $row to add at the end of the array
-     * @return \Piwik\DataTable\Row
+     * @param Row $row
+     * @return Row `$row` or the summary row if we're at the maximum number of rows.
      */
     public function addRow(Row $row)
     {
@@ -581,10 +662,12 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Sets the summary row (a dataTable can have only one summary row)
+     * Sets the summary row.
+     * 
+     * Note: A dataTable can have only one summary row.
      *
      * @param Row $row
-     * @return Row Returns $row.
+     * @return Row Returns `$row`.
      */
     public function addSummaryRow(Row $row)
     {
@@ -604,7 +687,7 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the dataTable ID
+     * Returns the DataTable ID.
      *
      * @return int
      */
@@ -614,9 +697,12 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Adds a new row from a PHP array data structure
+     * Adds a new row from an array.
+     * 
+     * You can add Row metadata with this method.
      *
-     * @param array $row eg. array(Row::COLUMNS => array( 'visits' => 13, 'test' => 'toto'),)
+     * @param array $row eg. array(Row::COLUMNS => array('visits' => 13, 'test' => 'toto'),
+     *                             Row::METADATA => array('mymetadata' => 'myvalue'))
      */
     public function addRowFromArray($row)
     {
@@ -624,7 +710,9 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Adds a new row a PHP array data structure
+     * Adds a new row a from an array of column values.
+     * 
+     * Row metadata cannot be added with this method.
      *
      * @param array $row eg. array('name' => 'google analytics', 'license' => 'commercial')
      */
@@ -634,9 +722,9 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the array of Row
+     * Returns the array of Rows.
      *
-     * @return Row[]
+     * @return array
      */
     public function getRows()
     {
@@ -648,10 +736,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the array containing all rows values for the requested column
+     * Returns an array containing all column values for the requested column.
      *
-     * @param string $name
-     * @return array
+     * @param string $name The column name.
+     * @return array The array of column values.
      */
     public function getColumn($name)
     {
@@ -663,12 +751,12 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns  the array containing all rows values of all columns which name starts with $name
+     * Returns an array containing all column values of columns whose name starts with `$name`.
      *
-     * @param $name
-     * @return array
+     * @param $namePrefix The column name prefix.
+     * @return array The array of column values.
      */
-    public function getColumnsStartingWith($name)
+    public function getColumnsStartingWith($namePrefix)
     {
         $columnValues = array();
         foreach ($this->getRows() as $row) {
@@ -685,8 +773,11 @@ class DataTable implements DataTableInterface
     /**
      * Returns the list of columns the rows in this datatable contain. This will return the
      * columns of the first row with data and assume they occur in every other row as well.
-     *
-     * @return array
+     * 
+     * Note: If column names still use their in-database INDEX values (@see Metrics), they
+     *       will be converted to their string name in the array result.
+     * 
+     * @return array Array of string column names.
      */
     public function getColumns()
     {
@@ -710,9 +801,9 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns an array containing the rows Metadata values
-     *
-     * @param string $name Metadata column to return
+     * Returns an array containing the requested metadata value of each row.
+     * 
+     * @param string $name The metadata column to return.
      * @return array
      */
     public function getRowsMetadata($name)
@@ -725,8 +816,8 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the number of rows in the table
-     *
+     * Returns the number of rows in the table including the summary row.
+     * 
      * @return int
      */
     public function getRowsCount()
@@ -739,9 +830,9 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns the first row of the DataTable
+     * Returns the first row of the DataTable.
      *
-     * @return \Piwik\DataTable\Row
+     * @return Row|false The first row or `false` if it cannot be found.
      */
     public function getFirstRow()
     {
@@ -751,14 +842,14 @@ class DataTable implements DataTableInterface
             }
             return false;
         }
-        $row = array_slice($this->rows, 0, 1);
-        return $row[0];
+        return reset($this->rows);
     }
 
     /**
-     * Returns the last row of the DataTable
+     * Returns the last row of the DataTable. If there is a summary row, it
+     * will always be considered the last row.
      *
-     * @return Row
+     * @return Row|false The last row or `false` if it cannot be found.
      */
     public function getLastRow()
     {
@@ -769,13 +860,13 @@ class DataTable implements DataTableInterface
         if (count($this->rows) == 0) {
             return false;
         }
-        $row = array_slice($this->rows, -1);
-        return $row[0];
+
+        return end($this->rows);
     }
 
     /**
-     * Returns the sum of the number of rows of all the subtables
-     *        + the number of rows in the parent table
+     * Returns the number of rows in this DataTable summed with the row count of each subtable
+     * in the DataTable hierarchy. This includes the subtables of subtables and further descendants.
      *
      * @return int
      */
@@ -795,9 +886,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Delete a given column $name in all the rows
+     * Delete a column by name in every row. This change is NOT applied recursively to all
+     * subtables.
      *
-     * @param string $name
+     * @param string $name Column name to delete.
      */
     public function deleteColumn($name)
     {
@@ -810,10 +902,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Rename a column in all rows
+     * Rename a column in every row. This change is applied recursively to all subtables.
      *
-     * @param string $oldName Old column name
-     * @param string $newName New column name
+     * @param string $oldName Old column name.
+     * @param string $newName New column name.
      */
     public function renameColumn($oldName, $newName)
     {
@@ -829,10 +921,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Delete columns by name in all rows
+     * Deletes several columns by name in every row.
      *
-     * @param array $names
-     * @param bool $deleteRecursiveInSubtables
+     * @param array $names List of column names to delete.
+     * @param bool $deleteRecursiveInSubtables Whether to apply this change to all subtables or not.
      */
     public function deleteColumns($names, $deleteRecursiveInSubtables = false)
     {
@@ -852,12 +944,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Deletes the ith row
-     *
-     * @param int $id
+     * Deletes a row by ID.
      *
-     * @throws Exception if the row $id cannot be found
-     * @return void
+     * @param int $id The row ID.
+     * @throws Exception If the row `$id` cannot be found.
      */
     public function deleteRow($id)
     {
@@ -872,12 +962,12 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Deletes all row from offset, offset + limit.
-     * If limit is null then limit = $table->getRowsCount()
+     * Deletes rows from `$offset` to `$offset + $limit`.
      *
-     * @param int $offset
-     * @param int $limit
-     * @return int
+     * @param int $offset The offset to start deleting rows from.
+     * @param int|null $limit The number of rows to delete. If `null` all rows after the offset
+     *                        will be removed.
+     * @return int The number of rows deleted.
      */
     public function deleteRowsOffset($offset, $limit = null)
     {
@@ -907,21 +997,22 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Deletes the rows from the list of rows ID
+     * Deletes a set of rows by ID.
      *
-     * @param array $aKeys ID of the rows to delete
-     * @throws Exception if any of the row to delete couldn't be found
+     * @param array $rowIds The list of row IDs to delete.
+     * @throws Exception If a row ID cannot be found.
      */
-    public function deleteRows(array $aKeys)
+    public function deleteRows(array $rowIds)
     {
-        foreach ($aKeys as $key) {
+        foreach ($rowIds as $key) {
             $this->deleteRow($key);
         }
     }
 
     /**
-     * Returns a simple output of the DataTable for easy visualization
-     * Example: echo $datatable;
+     * Returns a string representation of this DataTable for convenient viewing.
+     * 
+     * Note: This uses the Html DataTable renderer.
      *
      * @return string
      */
@@ -933,9 +1024,13 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns true if both DataTable are exactly the same.
-     * Used in unit tests.
+     * Returns true if both DataTable instances are exactly the same.
      *
+     * DataTables are equal if they have the same number of rows, if
+     * each row has a label that exists in the other table, and if each row
+     * is equal to the row in the other table with the same label. The order
+     * of rows is not important.
+     * 
      * @param \Piwik\DataTable $table1
      * @param \Piwik\DataTable $table2
      * @return bool
@@ -965,37 +1060,34 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * The serialization returns a one dimension array containing all the
-     * serialized DataTable contained in this DataTable.
-     * We save DataTable in serialized format in the Database.
-     * Each row of this returned PHP array will be a row in the DB table.
-     * At the end of the method execution, the dataTable may be truncated (if $maximum* parameters are set).
+     * Serializes an entire DataTable hierarchy and returns the array of serialized DataTables.
+     * 
+     * The first element in the returned array will be the serialized representation of this DataTable.
+     * Every subsequent element will be a serialized subtable.
+     * 
+     * This DataTable and subtables can optionally be truncated before being serialized. In most
+     * cases where DataTables can become quite large, they should be truncated before being persisted
+     * in an archive.
      *
-     * The keys of the array are very important as they are used to define the DataTable
+     * The result of this method is intended for use with the [ArchiveProcessor::insertBlobRecord](#) method.
      *
-     * IMPORTANT: The main table (level 0, parent of all tables) will always be indexed by 0
-     *    even it was created after some other tables.
-     *    It also means that all the parent tables (level 0) will be indexed with 0 in their respective
-     *  serialized arrays. You should never lookup a parent table using the getTable( $id = 0) as it
-     *  won't work.
+     * @throws Exception If infinite recursion detected. This will occur if a table's subtable is one of its parent tables.
+     * @param int $maximumRowsInDataTable If not null, defines the maximum number of rows allowed in the serialized DataTable.
+     * @param int $maximumRowsInSubDataTable If not null, defines the maximum number of rows allowed in serialized subtables.
+     * @param string $columnToSortByBeforeTruncation The column to sort by before truncating, eg, `Metrics::INDEX_NB_VISITS`.
+     * @return array The array of serialized DataTables:
+     *                   array(
+     *                       // this DataTable (the root)
+     *                       0 => 'eghuighahgaueytae78yaet7yaetae',
      *
-     * @throws Exception if an infinite recursion is found (a table row's has a subtable that is one of its parent table)
-     * @param int $maximumRowsInDataTable If not null, defines the number of rows maximum of the serialized dataTable
-     * @param int $maximumRowsInSubDataTable If not null, defines the number of rows maximum of the serialized subDataTable
-     * @param string $columnToSortByBeforeTruncation Column to sort by before truncation
-     * @return array  Serialized arrays
-     *            array(    // Datatable level0
-     *                    0 => 'eghuighahgaueytae78yaet7yaetae',
+     *                       // a subtable
+     *                       1 => 'gaegae gh gwrh guiwh uigwhuige',
      *
-     *                    // first Datatable level1
-     *                    1 => 'gaegae gh gwrh guiwh uigwhuige',
-     *
-     *                    //second Datatable level1
-     *                    2 => 'gqegJHUIGHEQjkgneqjgnqeugUGEQHGUHQE',
-     *
-     *                    //first Datatable level3 (child of second Datatable level1 for example)
-     *                    3 => 'eghuighahgaueytae78yaet7yaetaeGRQWUBGUIQGH&QE',
-     *                    );
+     *                       // another subtable
+     *                       2 => 'gqegJHUIGHEQjkgneqjgnqeugUGEQHGUHQE',
+     *                    
+     *                       // etc.
+     *                   );
      */
     public function getSerialized($maximumRowsInDataTable = null,
                                   $maximumRowsInSubDataTable = null,
@@ -1047,15 +1139,14 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Load a serialized string of a datatable.
-     *
-     * Does not load recursively all the sub DataTable.
-     * They will be loaded only when requesting them specifically.
+     * Adds a set of rows from a serialized DataTable string.
      *
-     * The function creates all the necessary DataTable\Row
-     *
-     * @param string $stringSerialized string of serialized datatable
-     * @throws Exception
+     * See [serialize](#serialize).
+     * 
+     * @param string $stringSerialized A serialized DataTable string in the format of a string in the
+     *                                 array returned by [serialize](#serialize). This function will
+     *                                 successfully load DataTables serialized by Piwik 1.X.
+     * @throws Exception if `$stringSerialized` is invalid.
      */
     public function addRowsFromSerializedArray($stringSerialized)
     {
@@ -1069,18 +1160,20 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Loads the DataTable from a PHP array data structure
+     * Adds many rows from an array.
+     * 
+     * You can add Row metadata with this method.
      *
      * @param array $array Array with the following structure
-     *                       array(
+     *                         array(
      *                             // row1
      *                             array(
-     *                                   Row::COLUMNS => array( col1_name => value1, col2_name => value2, ...),
-     *                                   Row::METADATA => array( metadata1_name => value1,  ...), // see Row
+     *                                 Row::COLUMNS => array( col1_name => value1, col2_name => value2, ...),
+     *                                 Row::METADATA => array( metadata1_name => value1,  ...), // see Row
      *                             ),
      *                             // row2
      *                             array( ... ),
-     *                       )
+     *                         )
      */
     public function addRowsFromArray($array)
     {
@@ -1097,9 +1190,9 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Loads the data from a simple php array.
-     * Basically maps a simple multidimensional php array to a DataTable.
-     * Not recursive (if a row contains a php array itself, it won't be loaded)
+     * Adds many rows from an array containing arrays of column values.
+     * 
+     * Row metadata cannot be added with this method.
      *
      * @param array $array Array with the simple structure:
      *                       array(
@@ -1107,7 +1200,6 @@ class DataTable implements DataTableInterface
      *                             array( col1_name => valueB, col2_name => valueD, ...),
      *                       )
      * @throws Exception
-     * @return void
      */
     public function addRowsFromSimpleArray($array)
     {
@@ -1200,7 +1292,6 @@ class DataTable implements DataTableInterface
      *     array( Row::COLUMNS => array('label' => LABEL2, 'value' => Y)),
      * )
      *
-     *
      * @param array $array Indexed array, two formats are supported
      * @param array|null $subtablePerLabel An indexed array of up to one DataTable to associate as a sub table
      * @return \Piwik\DataTable
@@ -1226,9 +1317,13 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Sets the maximum nesting level to at least a certain value. If the current value is
+     * Sets the maximum depth level to at least a certain value. If the current value is
      * greater than the supplied level, the maximum nesting level is not changed.
-     *
+     * 
+     * The maximum depth level determines the maximum number of subtable levels in the
+     * DataTable tree. For example, if it is set to `2`, this DataTable is allowed to
+     * have subtables, but the subtables are not.
+     * 
      * @param int $atLeastLevel
      */
     public static function setMaximumDepthLevelAllowedAtLeast($atLeastLevel)
@@ -1239,21 +1334,11 @@ class DataTable implements DataTableInterface
         }
     }
 
-    /**
-     * Returns all table metadata.
-     *
-     * @return array
-     */
-    public function getAllTableMetadata()
-    {
-        return $this->metadata;
-    }
-
     /**
      * Returns metadata by name.
      *
      * @param string $name The metadata name.
-     * @return mixed
+     * @return mixed|false The metadata value or false if it cannot be found.
      */
     public function getMetadata($name)
     {
@@ -1277,9 +1362,9 @@ class DataTable implements DataTableInterface
     /**
      * Sets the maximum number of rows allowed in this datatable (including the summary
      * row). If adding more then the allowed number of rows is attempted, the extra
-     * rows are added to the summary row.
+     * rows are summed to the summary row.
      *
-     * @param int|null $maximumAllowedRows
+     * @param int $maximumAllowedRows If `0`, the maximum number of rows is unset.
      */
     public function setMaximumAllowedRows($maximumAllowedRows)
     {
@@ -1290,18 +1375,22 @@ class DataTable implements DataTableInterface
      * Traverses a DataTable tree using an array of labels and returns the row
      * it finds or false if it cannot find one, and the number of segments of
      * the path successfully walked.
+     * 
      * If $missingRowColumns is supplied, the specified path is created. When
      * a subtable is encountered w/o the queried label, a new row is created
      * with the label, and a subtable is added to the row.
      *
-     * @param array $path The path to walk. An array of label values.
-     * @param array|bool $missingRowColumns
-     *                                      The default columns to use when creating new arrays.
+     * Read [http://en.wikipedia.org/wiki/Tree_(data_structure)#Traversal_methods](http://en.wikipedia.org/wiki/Tree_(data_structure)#Traversal_methods)
+     * for more information about tree walking.
+     * 
+     * @param array $path The path to walk. An array of label values. The first element
+     *                    refers to a row in this DataTable, the second in a subtable of
+     *                    the first row, the third a subtable of the second row, etc.
+     * @param array|bool $missingRowColumns The default columns to use when creating new rows.
      *                                      If this parameter is supplied, new rows will be
-     *                                      created if labels cannot be found.
-     * @param int $maxSubtableRows The maximum number of allowed rows in new
-     *                                      subtables.
-     *
+     *                                      created for path labels that cannot be found.
+     * @param int $maxSubtableRows The maximum number of allowed rows in new subtables. New
+     *                             subtables are only created if `$missingRowColumns` is provided.
      * @return array First element is the found row or false. Second element is
      *               the number of path segments walked. If a row is found, this
      *               will be == to count($path). Otherwise, it will be the index
@@ -1347,7 +1436,8 @@ class DataTable implements DataTableInterface
                 {
                     $table = new DataTable();
                     $table->setMaximumAllowedRows($maxSubtableRows);
-                    $table->setColumnAggregationOperations($this->columnAggregationOperations);
+                    $table->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME]
+                        = $this->metadata[self::COLUMN_AGGREGATION_OPS_METADATA_NAME];
                     $next->setSubtable($table);
                     // Summary row, has no metadata
                     $next->deleteMetadata();
@@ -1359,15 +1449,17 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Returns a new DataTable that contains the rows of each of this table's subtables.
+     * Returns a new DataTable in which the rows of this table are replaced with its subtable's
+     * rows.
      *
-     * @param string|bool $labelColumn If supplied the label of the parent row will be
-     *                                        added to a new column in each subtable row. If set to,
-     *                                  'label' each subtable row's label will be prepended w/
-     *                                        the parent row's label.
+     * @param string|bool $labelColumn If supplied the label of the parent row will be added to
+     *                                 a new column in each subtable row.
+     * 
+     *                                 If set to, 'label' each subtable row's label will be prepended
+     *                                 w/ the parent row's label. So `'child_label'` becomes
+     *                                 `'parent_label - child_label'`.
      * @param bool $useMetadataColumn If true and if $labelColumn is supplied, the parent row's
-     *                                        label will be added as metadata.
-     *
+     *                                label will be added as metadata and not a new column.
      * @return \Piwik\DataTable
      */
     public function mergeSubtables($labelColumn = false, $useMetadataColumn = false)
@@ -1418,7 +1510,9 @@ class DataTable implements DataTableInterface
 
     /**
      * Returns a new DataTable created with data from a 'simple' array.
-     *
+     * 
+     * See [addRowsFromSimpleArray](#addRowsFromSimpleArray).
+     * 
      * @param array $array
      * @return \Piwik\DataTable
      */
@@ -1430,38 +1524,10 @@ class DataTable implements DataTableInterface
     }
 
     /**
-     * Set the aggregation operation for a column, e.g. "min".
-     * @see self::addDataTable() and DataTable\Row::sumRow()
-     *
-     * @param string $columnName
-     * @param string $operation
-     */
-    public function setColumnAggregationOperation($columnName, $operation)
-    {
-        $this->columnAggregationOperations[$columnName] = $operation;
-    }
-
-    /**
-     * Set multiple aggregation operations at once.
-     * @param array $operations format: column name => operation
-     */
-    public function setColumnAggregationOperations($operations)
-    {
-        foreach ($operations as $columnName => $operation) {
-            $this->setColumnAggregationOperation($columnName, $operation);
-        }
-    }
-
-    /**
-     * Get the configured column aggregation operations
-     */
-    public function getColumnAggregationOperations()
-    {
-        return $this->columnAggregationOperations;
-    }
-
-    /**
-     * Creates a new DataTable instance from a serialize()'d array of rows.
+     * Creates a new DataTable instance from a serialized DataTable string.
+     * 
+     * See [getSerialized](#getSerialized) and [addRowsFromSerializedArray](#addRowsFromSerializedArray)
+     * for more information on DataTable serialization.
      *
      * @param string $data
      * @return \Piwik\DataTable
diff --git a/core/DataTable/Filter/AddSummaryRow.php b/core/DataTable/Filter/AddSummaryRow.php
index 1aa03257999950fe398ee1ad4dd59ddc4aa01c94..0a838d5b13177b00041231cad768c3dbaa294fe5 100644
--- a/core/DataTable/Filter/AddSummaryRow.php
+++ b/core/DataTable/Filter/AddSummaryRow.php
@@ -78,10 +78,10 @@ class AddSummaryRow extends Filter
 
                 //FIXME: I'm not sure why it could return false, but it was reported in: http://forum.piwik.org/read.php?2,89324,page=1#msg-89442
                 if ($summaryRow) {
-                    $newRow->sumRow($summaryRow, $enableCopyMetadata = false, $table->getColumnAggregationOperations());
+                    $newRow->sumRow($summaryRow, $enableCopyMetadata = false, $table->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME]);
                 }
             } else {
-                $newRow->sumRow($rows[$i], $enableCopyMetadata = false, $table->getColumnAggregationOperations());
+                $newRow->sumRow($rows[$i], $enableCopyMetadata = false, $table->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME]);
             }
         }
 
diff --git a/core/DataTable/Filter/GroupBy.php b/core/DataTable/Filter/GroupBy.php
index e33a2e7c9cc2158359f9c3e82120129253510b90..0ee3fa6e6c4885cf7b3417d087c7281bfaba25d0 100755
--- a/core/DataTable/Filter/GroupBy.php
+++ b/core/DataTable/Filter/GroupBy.php
@@ -87,7 +87,7 @@ class GroupBy extends Filter
             } else {
                 // if we have already encountered this group by value, we add this row to the
                 // row that will be kept, and mark this one for deletion
-                $groupByRows[$groupByValue]->sumRow($row, $copyMeta = true, $table->getColumnAggregationOperations());
+                $groupByRows[$groupByValue]->sumRow($row, $copyMeta = true, $table->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME]);
                 $nonGroupByRowIds[] = $rowId;
             }
         }
diff --git a/core/DataTable/Filter/Limit.php b/core/DataTable/Filter/Limit.php
index db79c8a1eea5c676ef79b25ca80fe4c3c20b5eed..501d5fbcb30c55138fdf5d1b8d5b882e97fe8b34 100644
--- a/core/DataTable/Filter/Limit.php
+++ b/core/DataTable/Filter/Limit.php
@@ -45,7 +45,7 @@ class Limit extends Filter
      */
     public function filter($table)
     {
-        $table->setRowsCountBeforeLimitFilter();
+        $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME] = $table->getRowsCount();
 
         if ($this->keepSummaryRow) {
             $summaryRow = $table->getRowFromId(DataTable::ID_SUMMARY_ROW);
diff --git a/core/DataTable/Row.php b/core/DataTable/Row.php
index 3bead313f3ec12ecc10c5d3280798370b460e220..36f057586f92f1fd05c3a417d6d042a00fa18505 100644
--- a/core/DataTable/Row.php
+++ b/core/DataTable/Row.php
@@ -287,7 +287,8 @@ class Row
             $thisSubTable = new DataTable();
             $this->addSubtable($thisSubTable);
         }
-        $thisSubTable->setColumnAggregationOperations($subTable->getColumnAggregationOperations());
+        $thisSubTable->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME]
+            = $subTable->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME];
         $thisSubTable->addDataTable($subTable);
     }
 
diff --git a/core/DataTable/Row/DataTableSummaryRow.php b/core/DataTable/Row/DataTableSummaryRow.php
index 7e1d939da28e62a63da34e3a9251cd202dd54d66..86032814563feba9cc5005e53f4aba6a189e69d5 100644
--- a/core/DataTable/Row/DataTableSummaryRow.php
+++ b/core/DataTable/Row/DataTableSummaryRow.php
@@ -59,7 +59,7 @@ class DataTableSummaryRow extends Row
     private function sumTable($table)
     {
         foreach ($table->getRows() as $row) {
-            $this->sumRow($row, $enableCopyMetadata = false, $table->getColumnAggregationOperations());
+            $this->sumRow($row, $enableCopyMetadata = false, $table->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME]);
         }
     }
 }
diff --git a/core/Plugin/Visualization.php b/core/Plugin/Visualization.php
index bcc8069726af5fafb172697d1107ccc0e46f224d..86138a71d59ea411c4ec69895c610bf109f7b7f6 100644
--- a/core/Plugin/Visualization.php
+++ b/core/Plugin/Visualization.php
@@ -175,7 +175,7 @@ class Visualization extends ViewDataTable
 
         // deal w/ table metadata
         if ($this->dataTable instanceof DataTable) {
-            $this->config->metadata = $this->dataTable->getAllTableMetadata();
+            $this->config->metadata = $this->dataTable->metadata;
 
             if (isset($this->config->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])) {
                 $this->config->report_last_updated_message = $this->makePrettyArchivedOnText();
@@ -372,7 +372,8 @@ class Visualization extends ViewDataTable
             !($this->dataTable instanceof DataTable\Map)
             && empty($javascriptVariablesToSet['totalRows'])
         ) {
-            $javascriptVariablesToSet['totalRows'] = $this->dataTable->getRowsCountBeforeLimitFilter();
+            $javascriptVariablesToSet['totalRows'] =
+                $this->dataTable->getMetadata(DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME) ?: $this->dataTable->getRowsCount();
         }
 
         $deleteFromJavascriptVariables = array(
diff --git a/plugins/Actions/Archiver.php b/plugins/Actions/Archiver.php
index 99cabed9b3effc812d328e8aa758f8e000c7eb06..e9e298ceb919a6021bc035f07df5645f88e8aa95 100644
--- a/plugins/Actions/Archiver.php
+++ b/plugins/Actions/Archiver.php
@@ -166,7 +166,7 @@ class Archiver extends \Piwik\Plugin\Archiver
                 || $type == Action::TYPE_ACTION_NAME
             ) {
                 // for page urls and page titles, performance metrics exist and have to be aggregated correctly
-                $dataTable->setColumnAggregationOperations(self::$actionColumnAggregationOperations);
+                $dataTable->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME] = self::$actionColumnAggregationOperations;
             }
 
             $this->actionsTablesByType[$type] = $dataTable;
diff --git a/plugins/UserSettings/API.php b/plugins/UserSettings/API.php
index 90dd4752c788263113dfd79c04840d256d7f4f26..d01b50793f2c89b597d0817f8cada22a2c38de7a 100644
--- a/plugins/UserSettings/API.php
+++ b/plugins/UserSettings/API.php
@@ -219,7 +219,7 @@ class API extends \Piwik\Plugin\API
 
             // When Truncate filter is applied, it will call AddSummaryRow which tries to sum all rows.
             // We tell the object to skip the column nb_visits_percentage when aggregating (since it's not correct to sum % values)
-            $table->setColumnAggregationOperation('nb_visits_percentage', 'skip');
+            $table->metadata[DataTable::COLUMN_AGGREGATION_OPS_METADATA_NAME]['nb_visits_percentage'] = 'skip';
 
             // The filter must be applied now so that the new column can
             // be sorted by the generic filters (applied right after this loop exits)
diff --git a/tests/PHPUnit/BaseFixture.php b/tests/PHPUnit/BaseFixture.php
index 3ab347fd31d77c3e329f22ee4c3cc15ad8baf118..1d9c8b731f9138e1c91dd33741057f80991384c0 100644
--- a/tests/PHPUnit/BaseFixture.php
+++ b/tests/PHPUnit/BaseFixture.php
@@ -383,6 +383,7 @@ abstract class Test_Piwik_BaseFixture extends PHPUnit_Framework_Assert
 
         // run the command
         exec($cmd, $output, $result);
+        echo "OUTPUT: ".implode("\n", $output);
         if ($result !== 0) {
             throw new Exception("log importer failed: " . implode("\n", $output) . "\n\ncommand used: $cmd");
         }
diff --git a/tests/PHPUnit/Core/DataTable/Filter/LimitTest.php b/tests/PHPUnit/Core/DataTable/Filter/LimitTest.php
index 3b786b0f011ff7bc788a770d1d6981b2f55fa3ec..073c66061aa4da121fb6e051751bbc45fea75140 100644
--- a/tests/PHPUnit/Core/DataTable/Filter/LimitTest.php
+++ b/tests/PHPUnit/Core/DataTable/Filter/LimitTest.php
@@ -49,7 +49,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(3, $table->getRowsCount());
         $this->assertEquals(2, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(4, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -65,7 +65,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(7, $table->getRowsCount());
         $this->assertEquals(2, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(8, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -76,13 +76,13 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $offset = 0;
         $limit = 10;
         $table = $this->getDataTableCount10();
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
         $filter = new Limit($table, $offset, $limit);
         $filter->filter($table);
         $this->assertEquals(10, $table->getRowsCount());
         $this->assertEquals(0, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(9, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -93,13 +93,13 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $offset = 5;
         $limit = 20;
         $table = $this->getDataTableCount10();
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
         $filter = new Limit($table, $offset, $limit);
         $filter->filter($table);
         $this->assertEquals(5, $table->getRowsCount());
         $this->assertEquals(5, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(9, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -114,7 +114,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(9, $table->getRowsCount());
         $this->assertEquals(1, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(9, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -130,7 +130,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(1, $table->getRowsCount());
         $this->assertEquals(9, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(9, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -146,7 +146,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(1, $table->getRowsCount());
         $this->assertEquals(9, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(9, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -162,7 +162,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(2, $table->getRowsCount());
         $this->assertEquals(8, $table->getFirstRow()->getColumn('idRow'));
         $this->assertEquals(9, $table->getLastRow()->getColumn('idRow'));
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -176,7 +176,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $filter = new Limit($table, $offset, $limit);
         $filter->filter($table);
         $this->assertEquals(0, $table->getRowsCount());
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**
@@ -190,7 +190,7 @@ class DataTable_Filter_LimitTest extends PHPUnit_Framework_TestCase
         $filter = new Limit($table, $offset, $limit);
         $filter->filter($table);
         $this->assertEquals(0, $table->getRowsCount());
-        $this->assertEquals(10, $table->getRowsCountBeforeLimitFilter());
+        $this->assertEquals(10, $table->metadata[DataTable::TOTAL_ROWS_BEFORE_LIMIT_METADATA_NAME]);
     }
 
     /**