<commit_before>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "HugoCalculator.hpp"
#include <NDBT.hpp>
#include <Base64.hpp>

/* *************************************************************
 * HugoCalculator
 *
 *  Comon class for the Hugo test suite, provides the functions 
 *  that is used for calculating values to load in to table and 
 *  also knows how to verify a row that's been read from db 
 *
 * ************************************************************/
HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {

  // The "id" column of this table is found in the first integer column
  int i;
  for (i=0; i<m_tab.getNoOfColumns(); i++){ 
    const NdbDictionary::Column* attr = m_tab.getColumn(i);
    if (attr->getType() == NdbDictionary::Column::Unsigned){
      m_idCol = i;
      break;
    }
  }
  
  // The "number of updates" column for this table is found in the last column
  for (i=m_tab.getNoOfColumns()-1; i>=0; i--){
    const NdbDictionary::Column* attr = m_tab.getColumn(i);
    if (attr->getType() == NdbDictionary::Column::Unsigned && 
	!attr->getPrimaryKey()){
      m_updatesCol = i;
      break;
    }
  }
#if 0
  ndbout << "idCol = " << m_idCol << endl;
  ndbout << "updatesCol = " << m_updatesCol << endl;
#endif
  // Check that idCol is not conflicting with updatesCol
  assert(m_idCol != m_updatesCol && m_idCol != -1 && m_updatesCol != -1);
}

Int32
HugoCalculator::calcValue(int record, 
			  int attrib, 
			  int updates) const {
  
  Int32 i;
  calcValue(record, attrib, updates, (char*)&i, sizeof(i));

  return i;
}
#if 0
HugoCalculator::U_Int32 calcValue(int record, int attrib, int updates) const;
HugoCalculator::U_Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::float calcValue(int record, int attrib, int updates) const;
HugoCalculator::double calcValue(int record, int attrib, int updates) const;
#endif

const char* 
HugoCalculator::calcValue(int record, 
			  int attrib, 
			  int updates, 
			  char* buf,
			  int len) const {
  unsigned seed;
  const NdbDictionary::Column* attr = m_tab.getColumn(attrib);
  Uint32 val;
  do
  {
    if (attrib == m_idCol)
    {
      *((Uint32*)buf)= record;
      return buf;
    }
    
    // If this is the update column
    if (attrib == m_updatesCol)
    {
      *((Uint32*)buf)= updates;
      return buf;
    }
    
    if (attr->getPrimaryKey())
    {
      seed = record + attrib;
    }
    else
    {
      seed = record + attrib + updates;
    }
  } while (0);
  val = rand_r(&seed);  

  if(attr->getNullable() && (((val >> 16) & 255) > 220))
    return NULL;
  
  memcpy(buf, &val, (len > 4 ? 4 : len));
  int pos= 4;
  while(pos + 4 < len)
  {
    val= rand_r(&seed);
    memcpy(buf+pos, &val, 4);
    pos++;
  }

  if(pos < len)
  { 
    val= rand_r(&seed);
    memcpy(buf+pos, &val, (len - pos));
  }

  switch(attr->getType()){
  case NdbDictionary::Column::Tinyint:
  case NdbDictionary::Column::Tinyunsigned:
  case NdbDictionary::Column::Smallint:
  case NdbDictionary::Column::Smallunsigned:
  case NdbDictionary::Column::Mediumint:
  case NdbDictionary::Column::Mediumunsigned:
  case NdbDictionary::Column::Int:
  case NdbDictionary::Column::Unsigned:
  case NdbDictionary::Column::Bigint:
  case NdbDictionary::Column::Bigunsigned:
  case NdbDictionary::Column::Float:
  case NdbDictionary::Column::Double:
  case NdbDictionary::Column::Decimal:
  case NdbDictionary::Column::Binary:
  case NdbDictionary::Column::Datetime:
  case NdbDictionary::Column::Time:
  case NdbDictionary::Column::Date:
    break;
  case NdbDictionary::Column::Bit:
  {
    Uint32 bits= attr->getLength();
    Uint32 tmp = bits >> 5;
    Uint32 size = bits & 31;
    ((Uint32*)buf)[tmp] &= ((1 << size) - 1);
    break;
  }
  case NdbDictionary::Column::Varbinary:
  case NdbDictionary::Column::Varchar:
  case NdbDictionary::Column::Text:
  case NdbDictionary::Column::Char:
  case NdbDictionary::Column::Longvarchar:
  case NdbDictionary::Column::Longvarbinary:
  {
    BaseString tmp;
    base64_encode(buf, len, tmp);
    memcpy(buf, tmp.c_str(), len);
    break;
  }
  case NdbDictionary::Column::Blob:
  case NdbDictionary::Column::Undefined:
    abort();
    break;
  }

  
  return buf;
} 

int
HugoCalculator::verifyRowValues(NDBT_ResultRow* const  pRow) const{
  int id, updates;

  id = pRow->attributeStore(m_idCol)->u_32_value();<commit_msg>ndb - HugoCalculator, faster string generation<commit_after>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "HugoCalculator.hpp"
#include <NDBT.hpp>
#include <Base64.hpp>

static
Uint32
myRand(Uint64 * seed)
{
  const Uint64 mul= 0x5deece66dull;
  const Uint64 add= 0xb;
  Uint64 loc_result = *seed * mul + add;

  * seed= loc_result;
  return loc_result >> 1;
}

static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                             "abcdefghijklmnopqrstuvwxyz"
                             "0123456789+/";

/* *************************************************************
 * HugoCalculator
 *
 *  Comon class for the Hugo test suite, provides the functions 
 *  that is used for calculating values to load in to table and 
 *  also knows how to verify a row that's been read from db 
 *
 * ************************************************************/
HugoCalculator::HugoCalculator(const NdbDictionary::Table& tab) : m_tab(tab) {

  // The "id" column of this table is found in the first integer column
  int i;
  for (i=0; i<m_tab.getNoOfColumns(); i++){ 
    const NdbDictionary::Column* attr = m_tab.getColumn(i);
    if (attr->getType() == NdbDictionary::Column::Unsigned){
      m_idCol = i;
      break;
    }
  }
  
  // The "number of updates" column for this table is found in the last column
  for (i=m_tab.getNoOfColumns()-1; i>=0; i--){
    const NdbDictionary::Column* attr = m_tab.getColumn(i);
    if (attr->getType() == NdbDictionary::Column::Unsigned && 
	!attr->getPrimaryKey()){
      m_updatesCol = i;
      break;
    }
  }
#if 0
  ndbout << "idCol = " << m_idCol << endl;
  ndbout << "updatesCol = " << m_updatesCol << endl;
#endif
  // Check that idCol is not conflicting with updatesCol
  assert(m_idCol != m_updatesCol && m_idCol != -1 && m_updatesCol != -1);
}

Int32
HugoCalculator::calcValue(int record, 
			  int attrib, 
			  int updates) const {
  
  Int32 i;
  calcValue(record, attrib, updates, (char*)&i, sizeof(i));

  return i;
}
#if 0
HugoCalculator::U_Int32 calcValue(int record, int attrib, int updates) const;
HugoCalculator::U_Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::Int64 calcValue(int record, int attrib, int updates) const;
HugoCalculator::float calcValue(int record, int attrib, int updates) const;
HugoCalculator::double calcValue(int record, int attrib, int updates) const;
#endif

const char* 
HugoCalculator::calcValue(int record, 
			  int attrib, 
			  int updates, 
			  char* buf,
			  int len) const {
  Uint64 seed;
  const NdbDictionary::Column* attr = m_tab.getColumn(attrib);
  Uint32 val;
  do
  {
    if (attrib == m_idCol)
    {
      val= record;
      memcpy(buf, &val, 4);
      return buf;
    }
    
    // If this is the update column
    if (attrib == m_updatesCol)
    {
      val= updates;
      memcpy(buf, &val, 4);
      return buf;
    }
    
    if (attr->getPrimaryKey())
    {
      seed = record + attrib;
    }
    else
    {
      seed = record + attrib + updates;
    }
  } while (0);
  
  val = myRand(&seed);  
  
  if(attr->getNullable() && (((val >> 16) & 255) > 220))
    return NULL;

  int pos= 0;
  switch(attr->getType()){
  case NdbDictionary::Column::Tinyint:
  case NdbDictionary::Column::Tinyunsigned:
  case NdbDictionary::Column::Smallint:
  case NdbDictionary::Column::Smallunsigned:
  case NdbDictionary::Column::Mediumint:
  case NdbDictionary::Column::Mediumunsigned:
  case NdbDictionary::Column::Int:
  case NdbDictionary::Column::Unsigned:
  case NdbDictionary::Column::Bigint:
  case NdbDictionary::Column::Bigunsigned:
  case NdbDictionary::Column::Float:
  case NdbDictionary::Column::Double:
  case NdbDictionary::Column::Decimal:
  case NdbDictionary::Column::Binary:
  case NdbDictionary::Column::Datetime:
  case NdbDictionary::Column::Time:
  case NdbDictionary::Column::Date:
  case NdbDictionary::Column::Bit:
    while (len > 4)
    {
      memcpy(buf+pos, &val, 4);
      pos += 4;
      len -= 4;
      val= myRand(&seed);
    }
    
    memcpy(buf+pos, &val, len);
    if(attr->getType() == NdbDictionary::Column::Bit)
    {
      Uint32 bits= attr->getLength();
      Uint32 tmp = bits >> 5;
      Uint32 size = bits & 31;
      ((Uint32*)buf)[tmp] &= ((1 << size) - 1);
    }
    break;
  case NdbDictionary::Column::Varbinary:
  case NdbDictionary::Column::Varchar:
  case NdbDictionary::Column::Text:
  case NdbDictionary::Column::Char:
  case NdbDictionary::Column::Longvarchar:
  case NdbDictionary::Column::Longvarbinary:
  {
    char* ptr= (char*)&val;
    while(len >= 4)
    {
      len -= 4;
      buf[pos++] = base64_table[ptr[0] & 0x3f];
      buf[pos++] = base64_table[ptr[1] & 0x3f];
      buf[pos++] = base64_table[ptr[2] & 0x3f];
      buf[pos++] = base64_table[ptr[3] & 0x3f];
      val= myRand(&seed);
    }
    
    for(; len; len--, pos++)
      buf[pos] = base64_table[ptr[len] & 0x3f];

    pos--;
    break;
  }
  case NdbDictionary::Column::Blob:
  case NdbDictionary::Column::Undefined:
    abort();
    break;
  }

  
  return buf;
} 

int
HugoCalculator::verifyRowValues(NDBT_ResultRow* const  pRow) const{
  int id, updates;

  id = pRow->attributeStore(m_idCol)->u_32_value();
{'fraction_non_alphanumeric': 0.1432315199710826, 'fraction_numerical': 0.01825411169347551, 'mean_word_length': 3.5487053020961774, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4988167', 'n_tokens_mistral': 3883, 'n_tokens_neox': 3609, 'n_words': 1029}