do not encrypt column needed for ORDER BY clause

This commit is contained in:
v-kaywon 2017-12-06 11:54:10 -08:00
parent 9196c557f8
commit 98d7307860
8 changed files with 62 additions and 167 deletions

View file

@ -153,10 +153,10 @@ class ColumnMeta
public $dataType; //a string that includes the size of the type if necessary (e.g., decimal(10,5))
public $colName; //column name
public $options; //a string that is null by default (e.g. NOT NULL Identity (1,1) )
public $encType; //randomized or deterministic; default is deterministic
public $forceEncrypt; //force encryption on a datatype no supported by Column Encrypton
public $encType; //randomized, deterministic, or normal; default is null
public $forceEncrypt; //force encryption on a datatype not supported by Column Encrypton
public function __construct($dataType, $colName = null, $options = null, $encType = "deterministic", $forceEncrypt = false)
public function __construct($dataType, $colName = null, $options = null, $encType = null, $forceEncrypt = false)
{
if (is_null($colName)) {
$this->colName = getDefaultColName($dataType);
@ -165,6 +165,15 @@ class ColumnMeta
}
$this->dataType = $dataType;
$this->options = $options;
if (is_null($encType)) {
if (isColEncrypted()) {
$this->encType = "deterministic";
} else {
$this->encType = "normal";
}
} else {
$this->encType = $encType;
}
$this->encType = $encType;
$this->forceEncrypt = $forceEncrypt;
}
@ -173,11 +182,11 @@ class ColumnMeta
*/
public function getColDef()
{
//return getColDef($this->colName, $this->dataType, $this->options, $this->encType);
$append = " ";
// an identity column is not encrypted because a select query with identity column as the where clause is often run and the user want to have to bind parameter every time
if (isColEncrypted() && $this->isEncryptableType() && stripos($this->options, "identity") === false && stripos($this->options, "rowguidcol") === false) {
if (isColEncrypted() && ($this->encType == "deterministic" || $this->encType == "ramdomized") && $this->isEncryptableType()
&& stripos($this->options, "identity") === false && stripos($this->options, "rowguidcol") === false) {
$cekName = getCekName();
if (stripos($this->dataType, "char") !== false) {
$append .= "COLLATE Latin1_General_BIN2 ";

View file

@ -48,7 +48,7 @@ try {
$num = $stmt2->fetchColumn();
echo "There are $num rows in the table.\n";
createTable($conn1, $tableName, array(new ColumnMeta("int", "idx", "NOT NULL PRIMARY KEY"), "txt" => "varchar(20)"));
createTable($conn1, $tableName, array(new ColumnMeta("int", "idx", "NOT NULL PRIMARY KEY", "normal"), "txt" => "varchar(20)"));
insertRow($conn1, $tableName, array("idx" => 0, "txt" => 'String0'));
insertRow($conn1, $tableName, array("idx" => 1, "txt" => 'String1'));
insertRow($conn1, $tableName, array("idx" => 2, "txt" => 'String2'));
@ -59,18 +59,9 @@ try {
var_dump($stmt1->fetchColumn());
unset($stmt1);
if (!isColEncrypted()) {
$stmt1 = $conn1->prepare("SELECT idx, txt FROM [$tableName] ORDER BY idx");
} else {
// ORDER BY does not work on encrypted columns
$stmt1 = $conn1->prepare("SELECT idx, txt FROM [$tableName]");
}
$stmt1 = $conn1->prepare("SELECT idx, txt FROM [$tableName] ORDER BY idx");
$stmt1->execute();
$data = $stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE);
// needs to order the result set manually as ORDER BY does not work properly on encrypted columns
if (isColEncrypted()) {
ksort($data);
}
var_dump($data);
echo "===WHILE===\n";
@ -100,7 +91,7 @@ try {
var_dump($stmt2->execute());
if ($idx == 0) { // bindColumn()s after execute() has been called at least once
$stmt2->bindColumn('txt', $txtCol);
$stmt2->bindColumn('txt', $col);
}
var_dump($stmt2->fetch(PDO::FETCH_BOUND));
$stmt2->closeCursor();
@ -112,23 +103,23 @@ try {
var_dump($stmt3->fetch(PDO::FETCH_BOUND));
$stmt3->closeCursor();
var_dump(array($idxCol=>$txtCol));
var_dump(array($idxCol=>$col));
}
echo "===REBIND/SAME===\n";
$stmt3->bindColumn('idx', $idxCol);
$stmt3->bindColumn('idx', $col);
foreach ($data as $idx => $txt) {
var_dump(array($idx=>$txt));
var_dump($stmt2->execute());
var_dump($stmt2->fetch(PDO::FETCH_BOUND));
$stmt2->closeCursor();
var_dump($idxCol);
var_dump($col);
var_dump($stmt3->execute());
var_dump($stmt3->fetch(PDO::FETCH_BOUND));
$stmt3->closeCursor();
var_dump($idxCol);
var_dump($col);
}
echo "===REBIND/CONFLICT===\n";

View file

@ -15,7 +15,7 @@ try {
// Prepare test table
$tableName = "pdo_test_table";
createTable($conn1, $tableName, array(new ColumnMeta("int", "idx", "NOT NULL PRIMARY KEY"), "txt" => "varchar(20)"));
createTable($conn1, $tableName, array(new ColumnMeta("int", "idx", "NOT NULL PRIMARY KEY", "normal"), "txt" => "varchar(20)"));
insertRow($conn1, $tableName, array("idx" => 0, "txt" => "String0"));
insertRow($conn1, $tableName, array("idx" => 1, "txt" => "String1"));
insertRow($conn1, $tableName, array("idx" => 2, "txt" => "String2"));
@ -28,36 +28,17 @@ try {
unset($stmt1);
logInfo(2, "Testing fetchAll() ...");
// ORDER BY doesn't work for encrypted columns
// need to fetch all rows first then sort and print
if (!isColEncrypted()) {
$stmt1 = $conn1->prepare("SELECT idx, txt FROM [$tableName] ORDER BY idx");
} else {
$stmt1 = $conn1->prepare("SELECT idx, txt FROM [$tableName]");
}
$stmt1 = $conn1->prepare("SELECT idx, txt FROM [$tableName] ORDER BY idx");
$stmt1->execute();
$data = $stmt1->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE);
if (isColEncrypted()) {
sort($data);
}
var_dump($data);
logInfo(3, "Testing bindColumn() ...");
$stmt1->bindColumn('idx', $idx);
$stmt1->bindColumn('txt', $txt);
$stmt1->execute();
$idxArray = array();
$txtArray = array();
while ($stmt1->fetch(PDO::FETCH_BOUND)) {
array_push($idxArray, $idx);
array_push($txtArray, $txt);
}
if (isColEncrypted()) {
sort($idxArray);
sort($txtArray);
}
for ($i = 0; $i < 4; $i++) {
var_dump(array($idxArray[$i] => $txtArray[$i]));
var_dump(array($idx=>$txt));
}
logInfo(4, "Testing bindColumn() with data check ...");
@ -74,27 +55,13 @@ try {
$stmt1->execute();
while ($stmt1->fetch(PDO::FETCH_BOUND)) {
$data[] = array('id' => $id, 'val' => $val);
printf("id = %s (%s) / val = %s (%s)\n",
var_export($id, true), gettype($id),
var_export($val, true), gettype($val));
}
$sortedData = $data;
if (isColEncrypted()) {
sort($sortedData);
}
foreach ($sortedData as $d) {
printf(
"id = %s (%s) / val = %s (%s)\n",
var_export($d['id'], true),
gettype($d['id']),
var_export($d['val'], true),
gettype($d['val'])
);
}
unset($stmt1);
if (!isColEncrypted()) {
$stmt1 = $conn1->query("SELECT idx, txt FROM [$tableName] ORDER BY idx");
} else {
$stmt1 = $conn1->query("SELECT idx, txt FROM [$tableName]");
}
$stmt1 = $conn1->query("SELECT idx, txt FROM [$tableName] ORDER BY idx");
while ($row = $stmt1->fetch(PDO::FETCH_ASSOC)) {
if ($row['idx'] != $data[$index]['id']) {
logInfo(6, "Data corruption for integer column in row $index");

View file

@ -15,7 +15,7 @@ try {
// Prepare test table
$tableName = "pdo_test_table";
createTable($conn1, $tableName, array(new ColumnMeta("int", "id", "NOT NULL PRIMARY KEY"), "label" => "char(1)"));
createTable($conn1, $tableName, array(new ColumnMeta("int", "id", "NOT NULL PRIMARY KEY", "normal"), "label" => "char(1)"));
insertRow($conn1, $tableName, array("id" => 1, "label" => "a"));
insertRow($conn1, $tableName, array("id" => 2, "label" => "b"));
insertRow($conn1, $tableName, array("id" => 3, "label" => "c"));
@ -27,36 +27,13 @@ try {
$midRow = 4;
// Check bind column
// order by does not work for encrypted columns
if (!isColEncrypted()) {
$tsql1 = "SELECT TOP($rowCount) id, label FROM [$tableName] ORDER BY id ASC";
} else {
$tsql1 = "SELECT TOP($rowCount) id, label FROM [$tableName]";
}
$data1 = bindColumn($conn1, $tsql1);
checkBind($conn1, $tsql1, $data1);
$tsql1 = "SELECT TOP($rowCount) id, label FROM [$tableName] ORDER BY id ASC";
$data = bindColumn($conn1, $tsql1);
checkBind($conn1, $tsql1, $data);
if (!isColEncrypted()) {
$tsql2 = "SELECT TOP($rowCount) id, label FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY id ASC) as row FROM [$tableName]) [$tableName] WHERE row >= $midRow";
} else {
$tsql2 = "SELECT TOP($rowCount) id, label FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY (SELECT 1)) as row FROM [$tableName]) [$tableName] WHERE row >= $midRow";
}
$data2 = bindColumn($conn1, $tsql2);
checkBind($conn1, $tsql2, $data2);
$data = array_merge($data1, $data2);
if (isColEncrypted()) {
sort($data);
}
foreach ($data as $d) {
printf(
"id = %s (%s) / label = %s (%s)\n",
var_export($d['id'], true),
gettype($d['id']),
var_export($d['label'], true),
gettype($d['label'])
);
}
$tsql2 = "SELECT TOP($rowCount) id, label FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY id ASC) as row FROM [$tableName]) [$tableName] WHERE row >= $midRow";
$data = bindColumn($conn1, $tsql2);
checkBind($conn1, $tsql2, $data);
// Cleanup
dropTable($conn1, $tableName);
@ -80,6 +57,9 @@ function bindColumn($conn, $tsql)
logInfo(1, "Cannot bind string column");
}
while ($stmt->fetch(PDO::FETCH_BOUND)) {
printf("id = %s (%s) / label = %s (%s)\n",
var_export($id, true), gettype($id),
var_export($label, true), gettype($label));
$data[] = array('id' => $id, 'label' => $label);
}
unset($stmt);

View file

@ -16,7 +16,7 @@ try {
// Prepare test table
$dataCols = "id, label";
$tableName = "pdo_test_table";
createTable($conn1, $tableName, array(new ColumnMeta("int", "id", "NOT NULL PRIMARY KEY"), "label" => "char(1)"));
createTable($conn1, $tableName, array(new ColumnMeta("int", "id", "NOT NULL PRIMARY KEY", "normal"), "label" => "char(1)"));
insertRow($conn1, $tableName, array("id" => 1, "label" => 'a'));
insertRow($conn1, $tableName, array("id" => 2, "label" => 'b'));
insertRow($conn1, $tableName, array("id" => 3, "label" => 'c'));
@ -28,13 +28,8 @@ try {
$label = null;
// Bind param @ SELECT
if (!isColEncrypted()) {
$tsql1 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? ORDER BY id ASC";
$value1 = array(1 => 0);
} else {
$tsql1 = "SELECT id, label FROM $tableName WHERE id = ? OR id = ?";
$value1 = array(1 => 1, 2 => 2);
}
$tsql1 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? ORDER BY id ASC";
$value1 = 0;
$stmt1 = $conn1->prepare($tsql1);
bindParam(1, $stmt1, $value1);
execStmt(1, $stmt1);
@ -45,13 +40,8 @@ try {
unset($stmt1);
// Bind param @ INSERT
if (!isColEncrypted()) {
$tsql2 = "INSERT INTO [$tableName](id, label) VALUES (100, ?)";
$value2 = array(1 => null);
} else {
$tsql2 = "INSERT INTO [$tableName](id, label) VALUES (?, ?)";
$value2 = array(1 => 100, 2 => null);
}
$tsql2 = "INSERT INTO [$tableName](id, label) VALUES (100, ?)";
$value2 = null;
$stmt1 = $conn1->prepare($tsql2);
bindParam(2, $stmt1, $value2);
execStmt(2, $stmt1);
@ -72,10 +62,10 @@ try {
echo $e->getMessage();
}
function bindParam($offset, $stmt, $value)
function bindParam($offset, $stmt, &$value)
{
foreach ($value as $key => &$val) {
$stmt->bindParam($key, $val);
if (!$stmt->bindParam(1, $value)) {
logInfo($offset,"Cannot bind parameter");
}
}

View file

@ -15,7 +15,7 @@ try {
// Prepare test table
$tableName = "pdo_test_table";
createTable($conn1, $tableName, array(new ColumnMeta("int", "id", "NOT NULL PRIMARY KEY"), "label" => "char(1)"));
createTable($conn1, $tableName, array(new ColumnMeta("int", "id", "NOT NULL PRIMARY KEY", "normal"), "label" => "char(1)"));
insertRow($conn1, $tableName, array("id" => 1, "label" => "a"));
insertRow($conn1, $tableName, array("id" => 2, "label" => "b"));
insertRow($conn1, $tableName, array("id" => 3, "label" => "c"));
@ -27,34 +27,18 @@ try {
$label = null;
// Check different value bind modes
if (!isColEncrypted()) {
$tsql1 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? ORDER BY id ASC";
} else {
$tsql1 = "SELECT id, label FROM [$tableName] WHERE id = ? OR id = ?";
}
$tsql1 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? ORDER BY id ASC";
$stmt1 = $conn1->prepare($tsql1);
printf("Binding value and not variable...\n");
if (!isColEncrypted()) {
bindValue(1, 1, $stmt1, 0);
} else {
bindValue(1, 1, $stmt1, 1);
bindValue(1, 2, $stmt1, 2);
}
bindValue(1, $stmt1, 0);
execStmt(1, $stmt1);
bindColumn(1, $stmt1, $id, $label);
fetchBound($stmt1, $id, $label);
printf("Binding variable...\n");
$var1 = 0;
if (!isColEncrypted()) {
bindVar(2, 1, $stmt1, $var1);
} else {
$var11 = $var1 + 1;
$var12 = $var1 + 2;
bindVar(2, 1, $stmt1, $var11);
bindVar(2, 2, $stmt1, $var12);
}
bindVar(2, $stmt1, $var1);
execStmt(2, $stmt1);
bindColumn(2, $stmt1, $id, $label);
fetchBound($stmt1, $id, $label);
@ -62,33 +46,17 @@ try {
printf("Binding variable which references another variable...\n");
$var2 = 0;
$var_ref = &$var2;
if (!isColEncrypted()) {
bindVar(3, 1, $stmt1, $var_ref);
} else {
$var21 = $var2 + 1;
$var22 = $var2 + 2;
$var_ref1 = &$var21;
$var_ref2 = &$var22;
bindVar(3, 1, $stmt1, $var_ref1);
bindVar(3, 2, $stmt1, $var_ref2);
}
bindVar(3, $stmt1, $var_ref);
execStmt(3, $stmt1);
bindColumn(3, $stmt1, $id, $label);
fetchBound($stmt1, $id, $label);
unset($stmt1);
if (!isColEncrypted()) {
$tsql2 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? AND id <= ? ORDER BY id ASC";
} else {
$tsql2 = "SELECT id, label FROM [$tableName] WHERE id = ? OR id = ?";
}
$tsql2 = "SELECT TOP(2) id, label FROM [$tableName] WHERE id > ? AND id <= ? ORDER BY id ASC";
$stmt1 = $conn1->prepare($tsql2);
printf("Binding a variable and a value...\n");
$var3 = 0;
if (isColEncrypted()) {
$var3++;
}
bindMixed(4, $stmt1, $var3, 2);
execStmt(4, $stmt1);
bindColumn(4, $stmt1, $id, $label);
@ -96,9 +64,6 @@ try {
printf("Binding a variable to two placeholders and changing the variable value in between the binds...\n");
$var4 = 0;
if (isColEncrypted()) {
$var4++;
}
$var5 = 2;
bindPlaceholder(5, $stmt1, $var4, $var5);
execStmt(5, $stmt1);
@ -114,16 +79,16 @@ try {
echo $e->getMessage();
}
function bindValue($offset, $index, $stmt, $value)
function bindValue($offset, $stmt, $value)
{
if (!$stmt->bindValue($index, $value)) {
if (!$stmt->bindValue(1, $value)) {
logInfo($offset, "Cannot bind value");
}
}
function bindVar($offset, $index, $stmt, &$var)
function bindVar($offset, $stmt, &$var)
{
if (!$stmt->bindValue($index, $var)) {
if (!$stmt->bindValue(1, $var)) {
logInfo($offset, "Cannot bind variable");
}
}

View file

@ -30,7 +30,10 @@ function katmaiBasicTypes($conn)
"c5_geometry" => '0000000001140000000000803e401f85eb51b81ee5bf48e17a14ae073f4052b81e85eb51d8bf',
"c6_hierarchyid" => '5bc0',
"c7_uniqueidentifier" => '35413141383846372d333734392d343641332d384137412d454641453733454645383846');
if (isColEncrypted()) {
// remove these types from tests because these types require direct query for the data to be inserted
// and the insertRow common function uses bind parameters to insertion when column encryption is enabled
$toRemove = array("c4_geography", "c5_geometry", "c6_hierarchyid");
foreach ($toRemove as $key) {
unset($dataTypes[$key]);

View file

@ -78,23 +78,13 @@ function updateFood($conn, $tableName, $id, $food, $category)
function fetchRows($conn, $tableName)
{
if (!isColEncrypted()) {
$query = "SELECT * FROM $tableName ORDER BY id";
} else {
$query = "SELECT * FROM $tableName";
}
$query = "SELECT * FROM $tableName ORDER BY id";
$stmt = $conn->query($query);
$stmt->setFetchMode(PDO::FETCH_CLASS, 'Food');
$foodArray = array();
while ($food = $stmt->fetch()) {
array_push($foodArray, $food);
}
if (isColEncrypted()) {
sort($foodArray);
}
foreach ($foodArray as $food) {
echo "ID: " . $food->id . " ";
echo "ID: " . $food->id . " ";
echo $food->getFood() . ", ";
echo $food->getcategory() . "\n";
}