original_string: protected function get_iterator_sql(string $tablename, int $contextlevel, ?string $action = null, ?string $tablealias = null) {
  
          if (!$tablealias) {
              $tablealias = 'analysable';
          }
  
          $params = ['contextlevel' => $contextlevel, 'modelid' => $this->get_modelid()];
          $select = $tablealias . '.*, ' . \context_helper::get_preload_record_columns_sql('ctx');
  
          // We add the action filter on ON instead of on WHERE because otherwise records are not returned if there are existing
          // records for another action or model.
          $usedanalysablesjoin = ' LEFT JOIN {analytics_used_analysables} aua ON ' . $tablealias . '.id = aua.analysableid AND ' .
              '(aua.modelid = :modelid OR aua.modelid IS NULL)';
  
          if ($action) {
              $usedanalysablesjoin .= " AND aua.action = :action";
              $params = $params + ['action' => $action];
          }
  
          // Adding the 1 = 1 just to have the WHERE part so that all further conditions added by callers can be
          // appended to $sql with and ' AND'.
          $sql = 'SELECT ' . $select . '
                    FROM {' . $tablename . '} ' . $tablealias . '
                    ' . $usedanalysablesjoin . '
                    JOIN {context} ctx ON (ctx.contextlevel = :contextlevel AND ctx.instanceid = ' . $tablealias . '.id)
                    WHERE 1 = 1';
  
          return [$sql, $params];
      }
code: protected function get_iterator_sql(string $tablename, int $contextlevel, ?string $action = null, ?string $tablealias = null) {
  
          if (!$tablealias) {
              $tablealias = 'analysable';
          }
  
          $params = ['contextlevel' => $contextlevel, 'modelid' => $this->get_modelid()];
          $select = $tablealias . '.*, ' . \context_helper::get_preload_record_columns_sql('ctx');
  
          // We add the action filter on ON instead of on WHERE because otherwise records are not returned if there are existing
          // records for another action or model.
          $usedanalysablesjoin = ' LEFT JOIN {analytics_used_analysables} aua ON ' . $tablealias . '.id = aua.analysableid AND ' .
              '(aua.modelid = :modelid OR aua.modelid IS NULL)';
  
          if ($action) {
              $usedanalysablesjoin .= " AND aua.action = :action";
              $params = $params + ['action' => $action];
          }
  
          // Adding the 1 = 1 just to have the WHERE part so that all further conditions added by callers can be
          // appended to $sql with and ' AND'.
          $sql = 'SELECT ' . $select . '
                    FROM {' . $tablename . '} ' . $tablealias . '
                    ' . $usedanalysablesjoin . '
                    JOIN {context} ctx ON (ctx.contextlevel = :contextlevel AND ctx.instanceid = ' . $tablealias . '.id)
                    WHERE 1 = 1';
  
          return [$sql, $params];
      }
code_tokens: protected function get_iterator_sql ( string $ tablename , int $ contextlevel , ? string $ action = null , ? string $ tablealias = null ) { if ( ! $ tablealias ) { $ tablealias = 'analysable' ; } $ params = [ 'contextlevel' => $ contextlevel , 'modelid' => $ this -> get_modelid ( ) ] ; $ select = $ tablealias . '.*, ' . \ context_helper :: get_preload_record_columns_sql ( 'ctx' ) ; // We add the action filter on ON instead of on WHERE because otherwise records are not returned if there are existing // records for another action or model. $ usedanalysablesjoin = ' LEFT JOIN {analytics_used_analysables} aua ON ' . $ tablealias . '.id = aua.analysableid AND ' . '(aua.modelid = :modelid OR aua.modelid IS NULL)' ; if ( $ action ) { $ usedanalysablesjoin .= " AND aua.action = :action" ; $ params = $ params + [ 'action' => $ action ] ; } // Adding the 1 = 1 just to have the WHERE part so that all further conditions added by callers can be // appended to $sql with and ' AND'. $ sql = 'SELECT ' . $ select . '
                    FROM {' . $ tablename . '} ' . $ tablealias . '
                    ' . $ usedanalysablesjoin . '
                    JOIN {context} ctx ON (ctx.contextlevel = :contextlevel AND ctx.instanceid = ' . $ tablealias . '.id)
                    WHERE 1 = 1' ; return [ $ sql , $ params ] ; }
docstring: Get the sql of a default implementation of the iterator.
  
  This method only works for analysers that return analysable elements which ids map to a context instance ids.
  
  @param  string      $tablename    The name of the table
  @param  int         $contextlevel The context level of the analysable
  @param  string|null $action
  @param  string|null $tablealias   The table alias
  @return array                     [0] => sql and [1] => params array
docstring_tokens: Get the sql of a default implementation of the iterator .