/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.voltdb_testprocs.regressionsuites.matviewprocs;
import org.voltdb.ProcInfo;
import org.voltdb.SQLStmt;
import org.voltdb.VoltProcedure;
import org.voltdb.VoltTable;
import org.voltdb.VoltType;
@ProcInfo (
singlePartition = false
)
public class TruncatePeople extends VoltProcedure {
public final SQLStmt captureview1 = new SQLStmt("SELECT * FROM MATPEOPLE ORDER BY AGE, PARTITION;");
public final SQLStmt captureview2 = new SQLStmt("SELECT * FROM MATPEOPLE2 ORDER BY AGE, PARTITION;");
public final SQLStmt clearcache1 = new SQLStmt("TRUNCATE TABLE WAS_PEOPLE;");
public final SQLStmt cachebase1 = new SQLStmt("INSERT INTO WAS_PEOPLE SELECT * FROM PEOPLE ORDER BY ID, PARTITION;");
public final SQLStmt truncatebase0 = new SQLStmt("TRUNCATE TABLE PEOPLE;");
public final SQLStmt validatebase0 = new SQLStmt("SELECT COUNT(*) FROM PEOPLE;");
public final SQLStmt renewbase0 = new SQLStmt("INSERT INTO PEOPLE SELECT * FROM WAS_PEOPLE ORDER BY ID, PARTITION;");
public VoltTable run(int rollback, int repeats, int restores) {
try {
//* enable to debug */ System.out.println("IN TruncatePeople." + rollback + "." + repeats + "." + restores);
voltQueueSQL(captureview1);
voltQueueSQL(captureview2);
VoltTable[] beforeViews = voltExecuteSQL();
throwVoltAbortExceptionIf("Initial empty view is not a representative test.",
! beforeViews[0].advanceRow(), null, beforeViews[0]);
//* enable to debug */ System.out.println("IN TruncatePeople captured");
voltQueueSQL(clearcache1);
voltQueueSQL(cachebase1);
voltExecuteSQL();
//* enable to debug */ System.out.println("IN TruncatePeople cached");
VoltTable[] afterViews = null;
int leaveTruncated = repeats - restores;
for (int ii = 0; ii < repeats; ++ii) {
voltQueueSQL(truncatebase0); // ("TRUNCATE TABLE PEOPLE;");
voltQueueSQL(validatebase0); // ("SELECT COUNT(*) FROM PEOPLE;");
VoltTable validated = voltExecuteSQL()[1];
throwVoltAbortExceptionIf(
"Rolling back unexpectedly after truncate misbehavior.",
( ! validated.advanceRow()) || validated.getLong(0) != 0,
null, null);
// Optionally leave the table truncated between early truncates,
// but always restore the rows towards the end of the iterations.
if (leaveTruncated-- <= 0) {
voltQueueSQL(renewbase0); // ("INSERT INTO PEOPLE ...");
voltExecuteSQL();
voltQueueSQL(captureview1);
voltQueueSQL(captureview2);
afterViews = voltExecuteSQL();
//* enable to debug */ System.out.println("IN TruncatePeople captured expecting renewed");
validateSame(beforeViews[0], afterViews[0]);
validateSame(beforeViews[1], afterViews[1]);
//* enable to debug */ System.out.println("IN TruncatePeople confirmed renewed");
}
else {
voltQueueSQL(captureview1);
voltQueueSQL(captureview2);
afterViews = voltExecuteSQL();
//* enable to debug */ System.out.println("IN TruncatePeople captured expecting empty");
validatePurged(afterViews);
//* enable to debug */ System.out.println("IN TruncatePeople confirmed empty");
}
}
throwVoltAbortExceptionIf("Rolling back as requested.",
rollback != 0, null, null);
//* enable to debug */ System.out.println("IN TruncatePeople exiting normally");
return afterViews[0];
}
catch(Throwable t) {
//* enable to debug */ System.out.println("IN TruncatePeople exiting abnormally");
throw t;
}
}
private void validatePurged(VoltTable[] afterViews) {
for (VoltTable viewContent : afterViews) {
throwVoltAbortExceptionIf("view should reflect 0 rows",
viewContent.advanceRow(), null, viewContent);
}
}
private void validateSame(VoltTable expectedRows, VoltTable actualRows) {
throwVoltAbortExceptionIf("column count mismatch. Expected: " + expectedRows.getColumnCount() +
" actual: " + actualRows.getColumnCount(),
expectedRows.getColumnCount() != actualRows.getColumnCount(), expectedRows, actualRows);
throwVoltAbortExceptionIf("row count mismatch. Expected: " + expectedRows.getRowCount() +
" actual: " + actualRows.getRowCount(),
expectedRows.getRowCount() != actualRows.getRowCount(), expectedRows, actualRows);
int ii = 0;
while (expectedRows.advanceToRow(ii)) {
throwVoltAbortExceptionIf("too few actual rows; expected more than " + (ii + 1),
! actualRows.advanceToRow(ii), expectedRows, actualRows);
for (int j = 0; j < actualRows.getColumnCount(); j++) {
String columnName = actualRows.getColumnName(j);
String colPrefix = "row " + ii + ": column: " + columnName + ": ";
VoltType actualType = actualRows.getColumnType(j);
VoltType expectedType = expectedRows.getColumnType(j);
throwVoltAbortExceptionIf(colPrefix + "type mismatch",
expectedType != actualType, expectedRows, actualRows);
Object expectedObj = expectedRows.get(j, expectedType);
Object actualObj = actualRows.get(j, actualType);
boolean expectedNull = expectedRows.wasNull();
boolean actualNull = actualRows.wasNull();
throwVoltAbortExceptionIf(colPrefix + "null/not null mismatch",
expectedNull != actualNull, expectedRows, actualRows);
if (expectedNull) {
continue;
}
if (expectedType == VoltType.FLOAT) {
//TODO: inject epsilon comparison logic here rather
// than assuming that FLOAT is a don't care case.
continue;
}
String message = colPrefix + "values not equal: expected: " + expectedObj + ", actual: " + actualObj;
throwVoltAbortExceptionIf(message,
! expectedObj.toString().equals(actualObj.toString()), expectedRows, actualRows);
}
ii++;
}
}
private void throwVoltAbortExceptionIf(String label, boolean condition,
VoltTable expectedRows, VoltTable actualRows) {
if (condition) {
System.out.println("IN TruncatePeople throwing: " + label);
if (expectedRows != null) {
System.out.println("EXPECTED: " + expectedRows);
}
if (actualRows != null) {
System.out.println(" ACTUAL: " + actualRows);
}
throw new VoltAbortException(label);
}
}
}