#!/bin/sh # Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2.0, # as published by the Free Software Foundation. # # This program is also distributed with certain software (including # but not limited to OpenSSL) that is licensed under separate terms, # as designated in a particular file or component or in included license # documentation. The authors of MySQL hereby grant you an additional # permission to link the program and your derivative works with the # separately licensed software that they have included with MySQL. # # 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, version 2.0, 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA set -e : ${load:=1} : ${loops:=100} : ${queries:=1000} : ${host:=localhost} : ${port:=4401} : ${RQG_HOME:=/home/oaske/randgen/latest} while getopts ":nm:r:l:h:p:" opt; do case $opt in n) load=0 ;; m) MYSQLINSTALL=${OPTARG} ;; r) RQG_HOME=${OPTARG} ;; l) loops=${OPTARG} ;; h) host=${OPTARG} ;; p) port=${OPTARG} ;; \?) echo "Usage: `basename $0` [options]" >&2 echo "-n : Do not create database (assumed to exist already)." >&2 echo "-m " >&2 echo "-r " >&2 echo "-l " >&2 echo "-h " >&2 echo "-p " >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 exit 1 ;; esac done pre="spj" opre="$pre.$$" : ${data:= --spec=simple.zz} : ${grammar:=spj_test.yy} ##: ${grammar:=$RQG_HOME/conf/optimizer_no_subquery.yy} ## a pretty sensible grammar: ##: ${grammar:=$RQG_HOME/conf/optimizer_no_subquery_portable.yy} ##: ${grammar:=$RQG_HOME/conf/subquery_drizzle.yy} ##: ${grammar:=$RQG_HOME/conf/subquery_materialization.yy} ##: ${grammar:=$RQG_HOME/conf/subquery_semijoin.yy} ##: ${grammar:=$RQG_HOME/conf/subquery_semijoin_nested.yy} ##: ${grammar:=$RQG_HOME/conf/outer_join.yy} ##: ${grammar:=$RQG_HOME/conf/outer_join_portable.yy} ## Really simple (or: 'stupid') grammars: Have modified these, used to have nondeterministic behaviour ##: ${grammar:=$RQG_HOME/conf/subquery.yy} ##: ${grammar:=$RQG_HOME/conf/subquery-5.1.yy} ##: ${grammar:=$RQG_HOME/conf/optimizer_subquery.yy} gensql=${RQG_HOME}/gensql.pl gendata=${RQG_HOME}/gendata.pl ecp="set optimizer_switch = 'engine_condition_pushdown=on';" #dsn=dbi:mysql:host=${host}:port=${port}:user=root:database=${pre}_innodb #mysqltest="$MYSQLINSTALL/bin/mysqltest -uroot --host=${host} --port=${port}" dsn=dbi:mysql:host=${host}:mysql_socket=/tmp/mysql.sock:user=root:database=${pre}_innodb mysqltest="$MYSQLINSTALL/bin/mysqltest -uroot --port=${port}" #mysql="$MYSQLINSTALL/bin/mysql --host=${host} --port=${port} --user=root" mysql="$MYSQLINSTALL/bin/mysql --port=${port} --user=root" # Create database with a case sensitive collation to ensure a deterministic # resultset when 'LIMIT' is specified: charset_spec="character set latin1 collate latin1_bin" #charset_spec="default character set utf8 default collate utf8_bin" export RQG_HOME if [ "$load" ] then $mysql -uroot -e "drop database if exists ${pre}_innodb; drop database if exists ${pre}_ndb" $mysql -uroot -e "create database ${pre}_innodb ${charset_spec}; create database ${pre}_ndb ${charset_spec}" ${gendata} --dsn=$dsn ${data} cat > /tmp/sproc.$$ < 0) then set _unique = ' UNIQUE'; if ((cnt%2) = 0) then set indextype = ' USING HASH'; else set indextype = ''; end if; end if; ## Add some composite, possibly unique, indexes if tabname > 'T' then set @ddl = CONCAT('DROP INDEX col_varchar_10_unique ON ', dstdb, '.', tabname); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('CREATE', _unique, ' INDEX ix1 ', indextype, ' ON ', dstdb, '.', tabname, '(col_char_16,col_char_16_unique)'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('CREATE', _unique, ' INDEX ix2 ', indextype, ' ON ', dstdb, '.', tabname, '(col_varchar_256,col_varchar_10_unique)'); PREPARE stmt from @ddl; EXECUTE stmt; elseif tabname > 'O' then set @ddl = CONCAT('CREATE', _unique, ' INDEX ix1 ', indextype, ' ON ', dstdb, '.', tabname, '(col_int,col_int_unique)'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('CREATE', _unique, ' INDEX ix2 ', indextype, ' ON ', dstdb, '.', tabname, '(col_int_key,col_int_unique)'); PREPARE stmt from @ddl; EXECUTE stmt; elseif tabname > 'H' then set @ddl = CONCAT('CREATE', _unique, ' INDEX ix3 ', indextype, ' ON ', dstdb, '.', tabname, '(col_int,col_int_key,col_int_unique)'); PREPARE stmt from @ddl; EXECUTE stmt; else set @ddl = CONCAT('CREATE', _unique, ' INDEX ix1', indextype, ' ON ', dstdb, '.', tabname, '(col_int_unique)'); PREPARE stmt from @ddl; EXECUTE stmt; end if; ## Modify primary key & partition for some tables if ((cnt%3) = 0) then set @ddl = CONCAT('UPDATE ', srcdb, '.', tabname, ' SET col_int=0 WHERE col_int IS NULL'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' CHANGE COLUMN pk pk INT(11) NOT NULL', ', DROP PRIMARY KEY', ', ADD PRIMARY KEY ', '(col_int,pk)'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' PARTITION BY KEY(col_int)'); PREPARE stmt from @ddl; EXECUTE stmt; elseif ((cnt%5) = 0) then set @ddl = CONCAT('UPDATE ', srcdb, '.', tabname, ' SET col_int=0 WHERE col_int IS NULL'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' CHANGE COLUMN pk pk INT(11) NOT NULL', ', DROP PRIMARY KEY', ', ADD PRIMARY KEY', indextype, '(col_int,pk)'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' PARTITION BY KEY(pk)'); PREPARE stmt from @ddl; EXECUTE stmt; elseif ((cnt%7) = 0) then set @ddl = CONCAT('DELETE FROM ', srcdb, '.', tabname, ' WHERE col_char_16 IS NULL'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' CHANGE COLUMN pk pk INT(11) NOT NULL', ', DROP PRIMARY KEY', ', ADD PRIMARY KEY', indextype, '(col_char_16,pk)'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' PARTITION BY KEY(col_char_16)'); PREPARE stmt from @ddl; EXECUTE stmt; elseif ((cnt%11) = 0) then set @ddl = CONCAT('DELETE FROM ', srcdb, '.', tabname, ' WHERE col_varchar_10 IS NULL'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' CHANGE COLUMN pk pk INT(11) NOT NULL', ', DROP PRIMARY KEY', ', ADD PRIMARY KEY', indextype, '(pk,col_varchar_256)'); PREPARE stmt from @ddl; EXECUTE stmt; set @ddl = CONCAT('ALTER TABLE ', dstdb, '.', tabname, ' PARTITION BY KEY(col_varchar_256)'); PREPARE stmt from @ddl; EXECUTE stmt; end if; set @ddl = CONCAT('INSERT INTO ', dstdb, '.', tabname, ' SELECT * FROM ', srcdb, '.', tabname); PREPARE stmt from @ddl; EXECUTE stmt; end if; until done end repeat; close c; END \G DROP PROCEDURE IF EXISTS alterengine\G CREATE PROCEDURE alterengine (db varchar(64), newengine varchar(64)) BEGIN declare tabname varchar(255); declare done integer default 0; declare c cursor for SELECT table_name FROM INFORMATION_SCHEMA.TABLES where table_schema = db; declare continue handler for not found set done = 1; open c; repeat fetch c into tabname; if not done then set @ddl = CONCAT('ALTER TABLE ', db, '.', tabname, ' engine = ', newengine); select @ddl; PREPARE stmt from @ddl; EXECUTE stmt; end if; until done end repeat; close c; END \G DROP PROCEDURE IF EXISTS analyzedb\G CREATE PROCEDURE analyzedb(db varchar(64)) BEGIN declare tabname varchar(255); declare done integer default 0; declare cnt integer default 0; declare c cursor for SELECT table_name FROM INFORMATION_SCHEMA.TABLES where table_schema = db; declare continue handler for not found set done = 1; set @ddl = 'ANALYZE TABLE '; open c; repeat fetch c into tabname; if not done then set cnt = cnt+1; if cnt > 1 then set @ddl = CONCAT(@ddl, ', '); end if; set @ddl = CONCAT(@ddl, db, '.', tabname); end if; until done end repeat; close c; PREPARE stmt from @ddl; EXECUTE stmt; END \G CALL copydb('${pre}_ndb', '${pre}_innodb', 'ndb')\G CALL analyzedb('${pre}_ndb')\G ##CALL alterengine('${pre}_ndb', 'ndb')\G DROP PROCEDURE copydb\G DROP PROCEDURE alterengine\G DROP PROCEDURE analyzedb\G EOF $mysql -uroot test < /tmp/sproc.$$ rm -f /tmp/sproc.$$ fi check_query(){ file=$1 no=$2 line=`expr $no \* 3` || true line=`expr $line + 3 + 2 + 1 + 1` || true sql=`head -n $line $file | tail -n 1` tmp=${opre}.$no.sql cat > $tmp <> ${opre}.$no.innodb.$i.txt done for t in 1 do $mysqltest ${pre}_ndb < $tmp >> ${opre}.$no.ndb.$i.txt done NDB_JOIN_PUSHDOWN=on export NDB_JOIN_PUSHDOWN for t in 1 do $mysqltest ${pre}_ndb < $tmp >> ${opre}.$no.ndbpush.$i.txt done cnt=`md5sum ${opre}.$no.*.txt | awk '{ print $1;}' | sort | uniq | wc -l` if [ $cnt -ne 1 ] then echo -n "$no " echo $sql >> ${opre}.failing.sql fi rm $tmp ${opre}.$no.*.txt } locate_query (){ file=$1 rows=`cat $file | wc -l` queries=`expr $rows - 4` queries=`expr $queries / 3` q=0 echo -n "checking queries..." while [ $q -ne $queries ] do check_query $file $q q=`expr $q + 1` done echo } run_all() { file=$1 NDB_JOIN_PUSHDOWN=off export NDB_JOIN_PUSHDOWN echo "- run innodb" $mysqltest ${pre}_innodb < $file > ${opre}_innodb.out md5_innodb=`md5sum ${opre}_innodb.out | awk '{ print $1;}'` echo "- run ndb without push" NDB_JOIN_PUSHDOWN=off export NDB_JOIN_PUSHDOWN $mysqltest ${pre}_ndb < $file > ${opre}_ndb.out md5_ndb=`md5sum ${opre}_ndb.out | awk '{ print $1;}'` echo "- run ndb with push" NDB_JOIN_PUSHDOWN=on export NDB_JOIN_PUSHDOWN $mysqltest ${pre}_ndb < $file > ${opre}_ndbpush.out md5_ndbpush=`md5sum ${opre}_ndbpush.out | awk '{ print $1;}'` if [ "$md5_innodb" != "$md5_ndb" ] || [ "$md5_innodb" != "$md5_ndbpush" ] then echo "md5 missmatch: $md5_innodb $md5_ndb $md5_ndbpush" echo "locating failing query(s)" locate_query $file fi rm ${opre}_innodb.out ${opre}_ndb.out ${opre}_ndbpush.out } i=0 while [ $i -ne $loops ] do i=`expr $i + 1` echo "** loop $i" us="$seed" || true if [ -z "$us" ] then us=`date '+%N'` fi echo "- generating sql seed: $us" ( echo "--disable_warnings" echo "--disable_query_log" echo "--eval set ndb_join_pushdown='\$NDB_JOIN_PUSHDOWN';" echo "$ecp" ${gensql} --seed=$us --queries=$queries --dsn=$dsn --grammar=$grammar| awk '{ print "--sorted_result"; print "--error 0,233,1055,1242,4006"; print; }' echo "--exit" ) > ${opre}_test.sql run_all ${opre}_test.sql rm ${opre}_test.sql echo done