+
+ $this->output( "$count rows processed\n" );
+
+ if ( $verboseStats ) {
+ $this->output( "\n" );
+ $this->showSortKeySizeHistogram();
+ }
+ }
+
+ /**
+ * Return an SQL expression selecting rows which sort above the given row,
+ * assuming an ordering of cl_collation, cl_to, cl_type, cl_from
+ * @param stdClass $row
+ * @param IDatabase $dbw
+ * @return string
+ */
+ function getBatchCondition( $row, $dbw ) {
+ if ( $this->hasOption( 'previous-collation' ) ) {
+ $fields = [ 'cl_to', 'cl_type', 'cl_from' ];
+ } else {
+ $fields = [ 'cl_collation', 'cl_to', 'cl_type', 'cl_from' ];
+ }
+ $first = true;
+ $cond = false;
+ $prefix = false;
+ foreach ( $fields as $field ) {
+ if ( $dbw->getType() === 'mysql' && $field === 'cl_type' ) {
+ // Range conditions with enums are weird in mysql
+ // This must be a numeric literal, or it won't work.
+ $encValue = intval( $row->cl_type_numeric );
+ } else {
+ $encValue = $dbw->addQuotes( $row->$field );
+ }
+ $inequality = "$field > $encValue";
+ $equality = "$field = $encValue";
+ if ( $first ) {
+ $cond = $inequality;
+ $prefix = $equality;
+ $first = false;
+ } else {
+ $cond .= " OR ($prefix AND $inequality)";
+ $prefix .= " AND $equality";
+ }
+ }
+
+ return $cond;
+ }
+
+ function updateSortKeySizeHistogram( $key ) {
+ $length = strlen( $key );
+ if ( !isset( $this->sizeHistogram[$length] ) ) {
+ $this->sizeHistogram[$length] = 0;
+ }
+ $this->sizeHistogram[$length]++;
+ }
+
+ function showSortKeySizeHistogram() {
+ $maxLength = max( array_keys( $this->sizeHistogram ) );
+ if ( $maxLength == 0 ) {
+ return;
+ }
+ $numBins = 20;
+ $coarseHistogram = array_fill( 0, $numBins, 0 );
+ $coarseBoundaries = [];
+ $boundary = 0;
+ for ( $i = 0; $i < $numBins - 1; $i++ ) {
+ $boundary += $maxLength / $numBins;
+ $coarseBoundaries[$i] = round( $boundary );
+ }
+ $coarseBoundaries[$numBins - 1] = $maxLength + 1;
+ $raw = '';
+ for ( $i = 0; $i <= $maxLength; $i++ ) {
+ if ( $raw !== '' ) {
+ $raw .= ', ';
+ }
+ if ( !isset( $this->sizeHistogram[$i] ) ) {
+ $val = 0;
+ } else {
+ $val = $this->sizeHistogram[$i];
+ }
+ for ( $coarseIndex = 0; $coarseIndex < $numBins - 1; $coarseIndex++ ) {
+ if ( $coarseBoundaries[$coarseIndex] > $i ) {
+ $coarseHistogram[$coarseIndex] += $val;
+ break;
+ }
+ }
+ if ( $coarseIndex == $numBins - 1 ) {
+ $coarseHistogram[$coarseIndex] += $val;
+ }
+ $raw .= $val;
+ }
+
+ $this->output( "Sort key size histogram\nRaw data: $raw\n\n" );
+
+ $maxBinVal = max( $coarseHistogram );
+ $scale = 60 / $maxBinVal;
+ $prevBoundary = 0;
+ for ( $coarseIndex = 0; $coarseIndex < $numBins; $coarseIndex++ ) {
+ if ( !isset( $coarseHistogram[$coarseIndex] ) ) {
+ $val = 0;
+ } else {
+ $val = $coarseHistogram[$coarseIndex];
+ }
+ $boundary = $coarseBoundaries[$coarseIndex];
+ $this->output( sprintf( "%-10s %-10d |%s\n",
+ $prevBoundary . '-' . ( $boundary - 1 ) . ': ',
+ $val,
+ str_repeat( '*', $scale * $val ) ) );
+ $prevBoundary = $boundary;
+ }