From 98d7307860df92bacfcb81bc6a70b1c6dfc1a369 Mon Sep 17 00:00:00 2001 From: v-kaywon Date: Wed, 6 Dec 2017 11:54:10 -0800 Subject: [PATCH] do not encrypt column needed for ORDER BY clause --- .../pdo_sqlsrv/MsCommon_mid-refactor.inc | 19 +++++-- .../pdo_sqlsrv/PDO38_FetchBound.phpt | 23 +++----- .../pdo_sqlsrv/PDO61_BindColumn1.phpt | 49 +++-------------- .../pdo_sqlsrv/PDO62_BindColumn2.phpt | 40 ++++---------- .../pdo_sqlsrv/PDO64_BindParam2.phpt | 26 +++------ .../pdo_sqlsrv/PDO66_BindValue2.phpt | 55 ++++--------------- .../pdo_sqlsrv/pdo_katmai_special_types.phpt | 3 + .../pdo_simple_update_variants.phpt | 14 +---- 8 files changed, 62 insertions(+), 167 deletions(-) diff --git a/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc b/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc index 35a175c7..e9752379 100644 --- a/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc +++ b/test/functional/pdo_sqlsrv/MsCommon_mid-refactor.inc @@ -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 "; diff --git a/test/functional/pdo_sqlsrv/PDO38_FetchBound.phpt b/test/functional/pdo_sqlsrv/PDO38_FetchBound.phpt index 2885916a..26bf378a 100644 --- a/test/functional/pdo_sqlsrv/PDO38_FetchBound.phpt +++ b/test/functional/pdo_sqlsrv/PDO38_FetchBound.phpt @@ -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"; diff --git a/test/functional/pdo_sqlsrv/PDO61_BindColumn1.phpt b/test/functional/pdo_sqlsrv/PDO61_BindColumn1.phpt index 31976354..e70a514d 100644 --- a/test/functional/pdo_sqlsrv/PDO61_BindColumn1.phpt +++ b/test/functional/pdo_sqlsrv/PDO61_BindColumn1.phpt @@ -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"); diff --git a/test/functional/pdo_sqlsrv/PDO62_BindColumn2.phpt b/test/functional/pdo_sqlsrv/PDO62_BindColumn2.phpt index abb2b62a..acb5e9b6 100644 --- a/test/functional/pdo_sqlsrv/PDO62_BindColumn2.phpt +++ b/test/functional/pdo_sqlsrv/PDO62_BindColumn2.phpt @@ -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); diff --git a/test/functional/pdo_sqlsrv/PDO64_BindParam2.phpt b/test/functional/pdo_sqlsrv/PDO64_BindParam2.phpt index d7b203ac..f6fbde34 100644 --- a/test/functional/pdo_sqlsrv/PDO64_BindParam2.phpt +++ b/test/functional/pdo_sqlsrv/PDO64_BindParam2.phpt @@ -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"); } } diff --git a/test/functional/pdo_sqlsrv/PDO66_BindValue2.phpt b/test/functional/pdo_sqlsrv/PDO66_BindValue2.phpt index 1390fc39..75fee971 100644 --- a/test/functional/pdo_sqlsrv/PDO66_BindValue2.phpt +++ b/test/functional/pdo_sqlsrv/PDO66_BindValue2.phpt @@ -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"); } } diff --git a/test/functional/pdo_sqlsrv/pdo_katmai_special_types.phpt b/test/functional/pdo_sqlsrv/pdo_katmai_special_types.phpt index 082017df..e342b88f 100644 --- a/test/functional/pdo_sqlsrv/pdo_katmai_special_types.phpt +++ b/test/functional/pdo_sqlsrv/pdo_katmai_special_types.phpt @@ -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]); diff --git a/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt b/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt index cb3d9917..3657eb40 100644 --- a/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt +++ b/test/functional/pdo_sqlsrv/pdo_simple_update_variants.phpt @@ -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"; }